2016-12-01 2 views
0

Прошу вас, поскольку у меня не было опыта работы с Spring MVC, пока я не начал свою новую работу не так давно, и я в основном занимаюсь кодом, написанным других разработчиков. Это будет довольно длинный вопрос (я упростил некоторые из моих примеров, поэтому они, надеюсь, не слишком долго).SpringMVC/JAVA - Получить значение параметра из метода в другом классе

То, что я пытаюсь достичь, заключается в использовании Raygun (службы отчетов о сбоях), чтобы отправить пользователю информацию о пользователе, который столкнулся с проблемой.

Первоначально я пытался использовать метод, аналогичный этому, чтобы получить имя пользователя:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
username = authentication.getName(); 

Но по какой-то причине это возвращается значение, ipaduser. Я не уверен, откуда эта ценность, но это, очевидно, не ответ.

Затем я попробовал:

System.getProperty("user.name"); 

Но это только получает имя зарегистрированного пользователя для нашего сервера API, а не имя пользователя, с помощью приложения.

После некоторого поиска я обнаружил, что имя пользователя и имя базы данных для пользователя хранится в пользовательском объекте ApiAccessToken. Проблема в том, что этот объект ApiAccessToken устанавливается только в методах наших классов контроллера.

Например:

@RequestMapping(path = "/api/foo", method = RequestMethod.GET) 
public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey{ 
    ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey); 
    // Etc 
} 

Код для ApiAccessToken и validateApiKey() следующим образом:

public final class ApiAccessToken { 

    private String databaseName; 
    private String username; 

    public String getDatabaseName() { return databaseName; } 

    public void setDatabaseName(String databaseName) { this.databaseName = databaseName; } 

    public String getUsername() { return username; } 

    public void setUsername(String username) { this.username = username; } 
} 

И

protected ApiAccessToken validateApiKey(ApiKeyService apiKeyService, String apiKey){ 
    UserAccountJdbcRepository userAccountJdbcRepository = new UserAccountJdbcRepository(createDataSourceForDatabase(USERS_DATABASE_NAME)); 
    ApiAccessToken accessToken = apiKeyService.validateApiKey(userAccountJdbcRepository, apiKey); 
    if (accessToken == null) { 
     throw new InvalidApiKeyException(); 
    } 
    return accessToken; 
} 

Моя другая идея была иметь локальной переменной в класс контроллера, который сохранит значение apiKey, а затем я буду ss, что значение для другого метода с использованием геттера. Например, в классе контроллера:

private static String apiKey; 

public static String getApiKey() { return apiKey; } 

@RequestMapping(path = "/api/foo", method = RequestMethod.GET) 
public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey{ 
    ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey); 
    apiKey = this.apiKey; 
    //Etc 
} 

И тогда в классе, где я представляемого сведения об исключении в Raygun:

String apiKey = Controller.getApiKey(); 
ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey); 
username = accessToken.getUsername(); 
database = accessToken.getDatabaseName(); 

Но это просто возвращает NullPointerException и не отправляет ничего Лучевая пушка.

Любая помощь будет принята с благодарностью, поскольку я не совсем уверен, что еще попробовать. Дайте мне знать, есть ли что-то, что я забыл, что вы думаете, что я должен включить. Еще раз, я все еще довольно новичок в Spring MVC, и разработчик, который написал большую часть этого, больше не работает с нами.

Спасибо,

Cale B

+1

'((ApiAccessToken) SecurityContextHolder.getContext(). GetAuthentication(). GetPrincipal()). GetName()' работает? В любом случае пользователь должен быть «SecurityContextHolder.getContext(). GetAuthe ntication(). GetPrinc ipal()' – fantaghirocco

+0

@fantaghirocco К сожалению, нет. Использование '((ApiAccessToken) SecurityContextHolder.getContext(). GetAuthentication(). GetPrincipal()). GetUsername()', я получаю ошибку "Не удалось вызвать метод @ExceptionHandler: public org.springframework.web.servlet.ModelAndView au. com.pdsonline.sync.integration.exception.RaygunUnhandledExceptionHandler.defaultErrorHandler (javax.servlet.http.HttpServletRequest, java.lang.Exception) throws java.lang.Exception java.lang.ClassCastException: org.springframework.security.core. userdetails.User не может быть передан в ApiAccessToken « –

+0

oops ... sorry:' UserDetails userDetail = (UserDetails) SecurityContextHolder.getContext(). getAuthe ntication(). get Princ ipal(); 'и' userDetail.getUsername (); ' – fantaghirocco

ответ

0

С предложением от Минь Хоанг, я был в состоянии решить эту проблему.

я добавил глобальную переменную класса RaygunUnhandledExceptionHandler:

private static ApiAccessToken accessToken = new ApiAccessToken(); 

Я тогда написал этот метод в RaygunUnhandledExceptionHandler, чтобы получить accessToken и установить его в переменную I, упомянутых выше:

public static void getAccessTokenFromController(ApiAccessToken accessTokenFromController) { accessToken = accessTokenFromController; } 

I затем добавили эту строку в/api/foo в контроллере, чтобы он отправил accesstoken в RaygunUnhandledExceptionHandler:

// Sends the API Key to RaygunUnhandledExceptionHandler 
RaygunUnhandledExceptionHandler.getAccessTokenFromController(accessToken); 

А потом в defaultErrorHandler() в RaygunUnhandledExceptionHandler:

ArrayList tags = new ArrayList<String>(); 
tags.add("username: " + accessToken.getUsername()); 
tags.add("database: " + accessToken.getDatabaseName()); 


снова Благодаря Минь Хоанг и fantaghirocco за вашу помощь, помогая мне разобраться в этом.

Пожалуйста, дайте мне знать, если вы видите какие-либо проблемы с этой реализацией.

1

Как api_key является параметром запроса, единственным способом, вы можете получить его через контроллер.

class Controller { 

    @RequestMapping(path = "/api/foo", method = RequestMethod.GET) 
    public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey) { 
     ... 

     Raygun.sendException(apiKey) 
     ... 
    } 
} 

class Raygun { 
    public static sendException(String apiKey) { 
     ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey); 
     username = accessToken.getUsername(); 
     database = accessToken.getDatabaseName(); 
     ... 
    } 
} 

Если вы хотите получить информацию о пользователе, используя ключ API в нескольких местах, посмотрите на Interceptor

+0

Большое вам спасибо, хотя вам не нужна правильная реализация, вы меня на правильном пути и смогли решить эту проблему :) Я включу ответ, чтобы показать, что я сделал по-другому .. –

Смежные вопросы