可以扩展 Spring MVC,自定义参数解析器,解析所需要的参数,这里模拟一个自定义注解,获取当前登录用户的逻辑
自定义注解
定义了一个自定义注解 @LoginUser 用于获取当前登录用户
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
自定义参数解析器
自定义一个参数解析器,用于解析 @LoginUser 的注解,并赋值
@Component
public class LoginUserResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// 从 request 或 redis 中获取用户逻辑...
System.out.println("---从 request 或 redis 中获取用户逻辑---");
Map<String, Object> map = new HashMap<>();
map.put("sessionId", webRequest.getSessionId());
map.put("id", "123456");
map.put("name", "eric");
return map;
}
}
添加参数解析器
将自定义的参数解析器添加到 argumentResolvers 列表中,我们可以通过重写 addArgumentResolvers 方法来实现
注意:
如果自定义的参数是一个 Map,List 这样的对象,很可能就会被 Spring 自带的参数解析器所解析,这样就不会使用到我们自定义的参数解析器了,所以我们要想办法,让我们的参数解析器优先级高于 Spring 自带的一系列参数解析器
@Configuration
@ComponentScan("org.wesoft.mvc")
@EnableWebMvc // 相当于 XML 中的 <mvc:annotation-driven/>
public class AppConfig implements WebMvcConfigurer {
/**
* 添加参数解析器
*
* @param resolvers initially an empty list
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
// 这里其实是传过来一个空集合,对应着 customArgumentResolvers
// 也就是我们其实是在 customArgumentResolvers 里添加自定义方法
// 然后 spring mvc 会将这个集合合并到 argumentResolvers 中,所以并不能保证执行顺序
resolvers.add(new LoginUserResolver());
}
// 会在 Spring mvc 环境初始化完成之后,加载这个方法
@Autowired
public void iniArgumentsResolvers(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(requestMappingHandlerAdapter.getArgumentResolvers());
// 获取自定义的参数解析器
List<HandlerMethodArgumentResolver> customArgumentResolvers = requestMappingHandlerAdapter.getCustomArgumentResolvers();
// 删除原来集合中的自定义参数解析器
argumentResolvers.removeAll(customArgumentResolvers);
// 重新加入到最前面
argumentResolvers.addAll(0, customArgumentResolvers);
// 重新设置参数解析器
requestMappingHandlerAdapter.setArgumentResolvers(argumentResolvers);
}
}
使用自定义注解获取当前登录用户
@RequestMapping("/test.do")
@ResponseBody
public Object test(@LoginUser Map loginUser) {
System.out.println("loginUser = " + loginUser);
Map<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("userEntity", userEntity);
return map;
}