一、SpringMVC 基于方法参数解析器自定义注入参数
在 SpringMVC
Web
项目开发中,我们可能需要经常获取一些公共的信息,比如用户信息、请求的 Token
等等,这种情况下我们可以封装一个工具类进行统一获取,也可以通过本篇文章讲解的方法参数解析器进行自动注入。
例如:这里以User
信息和Token
为例 ,我们可以以下面这种方式注入到 Controller
层,其中业务开发人员无需关注数据从何而来,直接开箱使用即可:
下面看下实践的过程:
1. 声明自定义注解
注解中也可以加上一些参数进行更灵活的注入信息。
@Target({
ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Token {
}
@Target({
ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface User {
}
2. 声明 User 信息类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo {
private Long id;
private String userName;
// 省略其他字段
}
3. 在拦截器中获取相关信息
@Component
@Slf4j
public class UserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
response.setContentType("text/json;charset=utf-8");
request.setAttribute("CURRENT_USER_INFO", getUserInfo(token));
request.setAttribute("TOKEN",token);
return true;
}
/**
* 获取用户信息
* @param token token
* @return 用户信息
*/
private UserInfo getUserInfo(String token){
// 查询用户逻辑.....
// 具体逻辑省略
// 这里仅演示方法参数解析器效果,先以固定值返回。
return new UserInfo(1L,"张三");
}
}
4. 方法参数解析器注入参数
@Component
public class UserAndTokenMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 如果参数类型是UserInfo并且有User注解,或者有Token注解则支持
if ((parameter.getParameterType().isAssignableFrom(UserInfo.class) && parameter.hasParameterAnnotation(User.class))
|| parameter.hasParameterAnnotation(Token.class)) {
return true;
}
return false;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
if (parameter.getParameterType().isAssignableFrom(UserInfo.class) && parameter.hasParameterAnnotation(User.class)) {
return webRequest.getAttribute("CURRENT_USER_INFO",
RequestAttributes.SCOPE_REQUEST);
} else if (parameter.hasParameterAnnotation(Token.class)) {
return webRequest.getAttribute("TOKEN",
RequestAttributes.SCOPE_REQUEST);
}
return null;
}
}
5. 注册拦截器和参数解析器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Resource
UserInterceptor userInterceptor;
@Resource
UserAndTokenMethodArgumentResolver userAndTokenMethodArgumentResolver;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userInterceptor).addPathPatterns("/**");
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userAndTokenMethodArgumentResolver);
}
}
6. 使用
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/test")
public void test(@User UserInfo user, @Token String token) {
log.info("用户信息:{}",user.toString());
log.info("Token: {}", token);
}
}
访问测试接口:
查看日志打印情况: