1.需求场景
- 在实际开发中,经常会遇到一下场景:
- controller 方法中拿到header中的userId,然后需要根据用户id去取到User的完整信息。在多个controller就会存在同样的重复代码--根据用户id取得user对象。
- 统一对请求json报文进行解密等操作。
- …
类似这样的操作,可以通过自定义注解统一处理。
2.Talk is poor.
以场景1为基础,写一个demo。首先要给出环境:
- Spring Boot 2.1.0.RELEASE.版本很重要1.x和2.x还是有区别的。
- 自定义注解
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CurrentUser { /** * 当前用户在request中的名字 * * @return */ String value() default "user"; }
- 定义实体类
public class UserBean implements Serializable { private String id; private String username; public UserBean(String id, String username) { this.id = id; this.username = username; } public UserBean() { } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
- 定义注解解析类,其中HandlerMethodArgumentResolver是springframework提供的接口,实现即可
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { if (parameter.getParameterType().isAssignableFrom(UserBean.class) && parameter.hasParameterAnnotation(CurrentUser.class)) { return true; } return false; } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { CurrentUser currentUserAnnotation = parameter.getParameterAnnotation(CurrentUser.class); String userId = webRequest.getHeader("userId"); //从数据库中根据用户id取用户信息,此处直接写死了。 UserBean user = null; if("1001".equals(userId)){ user = new UserBean(userId,"hendy"); } if(user == null){ throw new RuntimeException("用户不存在"); } return user; } }
- 定义controller 方法,使用注解
@RequestMapping(value = "/user/detail", method = RequestMethod.GET) @ResponseBody public Object test(@CurrentUser UserBean userBean) { String username = userBean.getUsername(); System.out.println(username); return userBean; }
网上有很多博客都是这样,到这一步就完成了。开始我也是按照网上那些来写,结果日常踩坑,比如:这篇,还有这篇,都没有把自定义的resolver接入到spring框架中,导致根本无效,还有一些是1.x版本的过时的配置方法。
- 关键的一步,addArgumentResolvers
@Configuration public class WebAppConfig extends WebMvcConfigurationSupport { @Override protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new CurrentUserMethodArgumentResolver()); } }
- Test
把自己踩的坑记录一下,demo给出的也未必是时间的应用需求,学习交流,仅此。有问题欢迎留言。