SpringBoot自定义参数解析
SpringBoot自定义参数解析
2020-09-10 2603 ℃
说明
我们都知道,在SpringMVC中,如果想要获取request,直接在方法上添加HttpServletRequest参数就可以获取到,有时候,我们也希望能将一些参数通过类似的方式很便捷的获取到。
例如获取当前登录用户的信息时,我们以前常用的做法是在每个Controller里调用获取用户信息的方法来手动获取(如从session中获取或通过token获取),这种方式不够优雅。
通过实现HandlerMethodArgumentResolver
接口就可以做到直接在方法中注入参数。
方法参数解析器
HandlerMethodArgumentResolver
是用来处理方法参数的解析器,包含以下2个方法:
- supportsParameter:用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。
- resolveArgument:真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。
SpringMVC自带了一些实现,如有需要,我们可以根据业务进行接口重写
- ServletRequestMethodArgumentResolver和ServletResponseMethodArgumentResolver处理了自动绑定HttpServletRequest和HttpServletResponse
- RequestParamMapMethodArgumentResolver处理了@RequestParam
- RequestHeaderMapMethodArgumentResolver处理了@RequestHeader
- PathVariableMapMethodArgumentResolver处理了@PathVariable
- ModelAttributeMethodProcessor处理了@ModelAttribute
- RequestResponseBodyMethodProcessor处理了@RequestBody
注入当前登录用户
1.实现HandlerMethodArgumentResolver接口
这里是从session中获取用户信息,需确保session中已存在登录信息注入才有效。若想从request中获取,可通过在SpringMVC拦截器中的preHandle
方法中将数据存在request对象中。
public class CustomAugmentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(User.class)
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
if (methodParameter.getParameterType().equals(User.class)) {
return nativeWebRequest.getAttribute(Const.USER_SESSION_KEY, RequestAttributes.SCOPE_SESSION);
}
return null;
}
}
2.配置MVC
定义MVC配置类,需继承WebMvcConfigurationSupport
或实现WebMvcConfigurer
。在addArgumentResolvers方法中,添加自定义的参数解析器
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new CustomAugmentResolver());
}
3.Controller中使用
通过上面的简单配置,就可以直接在controller
中注入参数了,非常方便。
@GetMapping("userInfo")
public User userInfo(User user) {
return user;
}
4.存在的问题
如果有这样一种情况,我们接收前端传递的参数用的刚好也是User
对象,那么,就会导致参数无法传递进来,会被注入成session
中的user
对象。
解决方案大概有两种:
- 注入时过滤掉这个方法。如利用注解区分
- 不适用同一对象。如User对象用于注入,另外新建一个类叫UserParam用于接收参数
我们可以自定义一个注解,用于绑定当前登录用户信息。
/**
* 绑定当前登录的用户
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {
/**
* 当前用户在session中的名字
*
* @return
*/
String value() default Const.USER_SESSION_KEY;
}
然后修改CustomAugmentResolver
中的supportsParameter
方法,加上一个注解判断的条件。
public class CustomAugmentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(User.class) && parameter.hasParameterAnnotation(CurrentUser.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
if (methodParameter.getParameterType().equals(User.class)) {
return nativeWebRequest.getAttribute(Const.USER_SESSION_KEY, RequestAttributes.SCOPE_SESSION);
}
return null;
}
}
在需要注入的地方加上这个注解,就像@RequestBody
一样,就能进行区分了。
@GetMapping("userList")
public void userList(User user, @CurrentUser User currentUser) {
//略
}
文章链接:http://www.iszhouhua.com/custom-augment-resolver.html
发表时间:2020-09-10 11:32
最后更新时间:2020-09-10 12:54
1
1
挺好的
test
test