自定义解析器
springmvc中所有的映射方法中形式参数的值的注入都是springmvc自带的参数解析器
现在想要springmvc将对象登陆用户对象注入,需要自定义参数解析器
简化后的代码代码底层实现原理 : 需要自定义springmvc参数解析器
将请求映射方法声明形式参数的userInfo类型的参数 ,解析成当前登陆用户对象并注入
1. 自定义解析器类 并实现HandlerMethodArgumentResolver接口
2. 实现接口中的二个方法 : 方法一 : 是判断该解析器能解析的参数类型
方法二 : 执行解析逻辑 , 此处例题是将当前登陆用户对象 ,注入userinfo类型的参数中
3. 容器配置类实现webmvcConfigurer 如 public class App implements WebMvcConfigurer
4. @bean 自定义方法得到自定义解析器类的对象 , 然后add到解析器容器中去
如: 当我们需要在游记中添加一个userId的值 ;
更改之前:
@RequireLogin
@PostMapping("/saveOrUpdate")
public Object saveOrUpdate(Travel param,HttpServletRequest request){
String token = request.getHeader("token");
UserInfo user = userInfoRedisService.getUserByToken(token);
if(user!=null){
System.out.println(user.getId());
param.setUserId(user.getId());
}
String id = travelService.saveOrUpdate(param);
return JsonResult.success(id);
}
-------------------------------------------------------
更改之后
@RequireLogin
@PostMapping("/saveOrUpdate")
public Object saveOrUpdate(Travel param,@UserParam UserInfo userInfo){
param.setUserId(userInfo.getId());
String id = travelService.saveOrUpdate(param);
return JsonResult.success(id);
}
如果当我们自定义的对象如登陆对象封装的UserInfo 和我们要修改保存时候封装的UserInfo时候是有区别的
因此这个时候就要我们区分对象 : 可以使用贴参数注解的形式来区分
注意 : 如果进行用户编辑操作 ,映射方法接收参数也是UserInfo , 此时怎么区分???
定义一个参数级别的注解 , 当参数贴有这个注解时, 自定义解析器才执行解析逻辑
如下 :
@GetMapping("/info")
public Object getUserInfo(@UserParam UserInfo user) {
return JsonResult.success(user);
}
@GetMapping("/update")
public Object update(UserInfo user){
return JsonResult.success(user);
}
自定义解析器类
package cn.wolfcode.wolf2w.resolver;
import cn.wolfcode.wolf2w.annontation.UserParam;
import cn.wolfcode.wolf2w.domain.UserInfo;
import cn.wolfcode.wolf2w.redis.service.IUserInfoRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private IUserInfoRedisService userInfoRedisService;
@Override
//指定该解析器能解析参数类型
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.getParameterType()==UserInfo.class && methodParameter.hasParameterAnnotation(UserParam.class); //判断是否需要解析的类型是UserInfo 同时判断是否贴有注解
}
@Override
// 方法二 : 执行解析逻辑 , 此处例题是将当前登陆用户对象 ,注入userinfo类型的参数中
public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest,
WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
String token = request.getHeader("token");
UserInfo user = userInfoRedisService.getUserByToken(token);
return user;
}
}
配置加入容器
@SpringBootApplication
public class App implements WebMvcConfigurer{
//创建用户解析器
@Bean
public UserArgumentResolver getUserArgumentResolver(){
return new UserArgumentResolver();
}
//添加至容器
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(getUserArgumentResolver());
}
}
自定义注解
package cn.wolfcode.wolf2w.annontation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*用户参数解析注解
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserParam {
}
实际使用
如下 :
@GetMapping("/info")
public Object getUserInfo(@UserParam UserInfo user) {
return JsonResult.success(user);
}
@GetMapping("/update")
public Object update(UserInfo user){
return JsonResult.success(user);
}
操作原理
操作原理 :
1. 请求进入映射方法之后 , 发现映射方法声明的形式参数
2. springmvc马上遍历所有参数解析器 , 一个个执行supportParamenter方法 ,一旦返回true , 停止循环,表示当前解析器能解析马上调用该解析器resolverArgument方法 , 将该方法的返回值注入到形式参数变量中
回顾 :