我们都知道SpringMvc的Controller的方法上可以接收各种各样的参数,比如HttpServletRequest
或HttpServletResponse
,各种注解@RequestParam
、@RequestHeader
、@RequestBody
、@PathVariable
、@ModelAttribute
,这些参数是从哪里获取的?
这些参数都是由不同的参数解析器为我们解析出来的,可以解析类也可以解析带注解的类
我们可以利用解析器解析自定义的参数(类、注解),在我们需要的传入的controller方法上传入它(不需要每次都要在方法内部通过request
、response
等参数做一系列操作来获取该类对象)
1、编写注解类
@Target(value = ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginUser {
}
2、添加解析器配置类
我们想要解析参数的时候我们就需要通过更改SpringBoot的配置来添加自己实现的解析类自定义配置类实现WebMvcConfigurer
接口,重写其中的addArgumentResolvers
方法来添加自己的解析类(通过自动注入的方法注入)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
SpringSSOInterceptor springSSOInterceptor;
@Autowired
LoginUserPinArgumentResolver loginUserPinArgumentResolver;
@Autowired
UserAuthCheckInterceptor userAuthCheckInterceptor ;
/**
*
* 单点登录拦截器、用户权限拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(springSSOInterceptor).addPathPatterns("/**");
registry.addInterceptor(userAuthCheckInterceptor).addPathPatterns("/**");
}
/**
*
* 登录用户参数解析登录
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(loginUserPinArgumentResolver);
}
}
3、实现解析器
我们自定义解析器需要实现HandlerMethodArgumentResolver处理器方法解析器
接口,并实现其中的supportsParameter
和resolveArgument
方法
HandlerMethodArgumentResolver
的接口定义如下:
(1)supportsParameter
用于判断是否支持对某种参数的解析(支持则返回true)
(2)resolveArgument
将请求中的参数值解析为某种对象(具体的操作获取解析对象)
下面这个解析器用于获取User对象(通过token获取保存在redis中的user),无需每次使用resquest和response在controller方法内部获取,可以直接获取到作为参数传入
/**
* 自定义参数解析器
* 解析每次都要获取的user自动传入,无需每次获取
*/
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private UserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
assert request != null;
//COOKIE_NAME_TOKEN="token"
String paramToken = request.getParameter(UserServiceImpl.COOKIE_NAME_TOKEN);
String cookieToken = getCookieValue(request);
//通过两种方式获取,如果都获取失败则返回null
if(StringUtils.isEmpty(cookieToken)&&StringUtils.isEmpty(paramToken)){
return null;
}else {
String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
return userService.getUserByToken(response,token);
}
}
//遍历cookie获取名称相同的那个cookie的值
private String getCookieValue(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for(Cookie cookie:cookies){
if(cookie.getName().equals(Constant.COOKIE_NAME_TOKEN)){
return cookie.getValue();
}
}
return null;
}
}
到此,一个注解参数解析器就实现好了,我们可以通过传入参数的形式直接通过解析器帮我们获取到