(7)SprintBoot 2.X 自定义参数解析器

(7)SprintBoot 2.X 自定义参数解析器

    • 1.为什么引入参数解析器
    • 2.代码实现
        • 2.1 HandlerMethodArgumentResolver接口
        • 2.2 创建一个UserArgumentResolver类
        • 2.3 注册解析器
        • 2.4 业务逻辑代码的使用

1.为什么引入参数解析器

  • 想办法在直接在controller的请求的方法上面直接注入MiaoshaUser(用户的信息),直接通过方法的参数就可以将获取用户的信息,从而简化代码。就像SpringMVC中的controller 方法中可以有很多参数可以直接使用(例如request和response对象),有些参数不需要传值,就可以直接获取到一样
  • 避免在GoodsController中的每个@RequestMapping(“to_list”,“detail”)等等重复下述与业务逻辑无关的代码
if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)){
	return "login";
}
String token = StringUtils.isEmpty(paramToken) ? cookieToken : paramToken;
MiaoshaUser user = userService.getByToken(response,token);

2.代码实现

2.1 HandlerMethodArgumentResolver接口

  • HandlerMethodArgumentResolver接口,通过实现这个接口的类,就是解析器。按照我们的期望,它中间的函数应该能得到必要信息,从而按照自定义逻辑计算并返回一个值。
  • MethodParameter 是spring对被注解修饰过参数的包装,从其中能拿到参数的反射相关信息。
  • supportsParameter() 传入一个参数,用以判断此参数是否能够使用该解析器。
  • resolveArgument() 就是之前讨论的解析函数,传入必要信息,计算并返回一个值。
  • 综合来看,框架会将每一个MethodParameter传入supportsParameter测试是否能够被处理,如果能够,就使用resolveArgument处理。
 public interface HandlerMethodArgumentResolver {
    boolean supportsParameter(MethodParameter parameter); 
    Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, 
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}

2.2 创建一个UserArgumentResolver类

  • 实现接口HandlerMethodArgumentResolver,然后重写里面的方法resolveArgument和supportsParameter方法
  • 实现思路: 先获取到已有参数HttpServletRequest,从中获取到token,再用token作为key从redis拿到User,而HttpServletResponse作用是为了延迟有效期
@Service
	public class UserArgumentResolver implements HandlerMethodArgumentResolver{
	@Autowired					
	MiaoshaUserService miaoshaUserService;	
	public boolean supportsParameter(MethodParameter parameter) {
		//返回参数的类型
		Class<?> clazz=parameter.getParameterType();
		return clazz==MiaoshaUser.class;
	}	
	
	public Object resolveArgument(MethodParameter arg0, ModelAndViewContainer arg1, NativeWebRequest webRequest,
			WebDataBinderFactory arg3) throws Exception {
		HttpServletRequest request=webRequest.getNativeRequest(HttpServletRequest.class);
		HttpServletResponse response=webRequest.getNativeResponse(HttpServletResponse.class);
		String paramToken=request.getParameter(MiaoshaUserService.COOKIE1_NAME_TOKEN);	
		//获取cookie
		String cookieToken=getCookieValue(request,MiaoshaUserService.COOKIE1_NAME_TOKEN);		
		if(StringUtils.isEmpty(cookieToken)&&StringUtils.isEmpty(paramToken))
		{
			return null;
		}
		String token=StringUtils.isEmpty(paramToken)?cookieToken:paramToken;		
		MiaoshaUser user=miaoshaUserService.getByToken(token,response);			
		//去取得已经保存的user,因为在用户登录的时候,user已经保存到threadLocal里面了,因为拦截器首先执行,然后才是取得参数
		//MiaoshaUser user=UserContext.getUser();
		return user;
	}
	public String getCookieValue(HttpServletRequest request, String cookie1NameToken) {//COOKIE1_NAME_TOKEN-->"token"
		//遍历request里面所有的cookie
		Cookie[] cookies=request.getCookies();
		if(cookies!=null) {
			for(Cookie cookie :cookies) {
				if(cookie.getName().equals(cookie1NameToken)) {
					System.out.println("getCookieValue:"+cookie.getValue());
					return cookie.getValue();
				}
			}
		}
		return null;
	}
}

2.3 注册解析器

/**
 * @description:自定参数解析器,
 * 作用:改变SpringMVC的Controller传入参数,实现可以User替换Token做为参数从登陆页面传到商品列表页面
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{

    @Autowired
    UserArgumentResolver userArgumentResolver;

    @Autowired
    AccessInterceptor accessInterceptor;

    /**
     * SpringMVC框架回调addArgumentResolvers,然后给Controller的参数赋值
     * @param argumentResolvers
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(userArgumentResolver);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(accessInterceptor);
    }
}

2.4 业务逻辑代码的使用

  • 改变SpringMVC的Controller传入参数,实现可以User替换Token做为参数从登陆页面传到商品列表页面
	@RequestMapping("/to_list")
	public String toList(Model model,MiaoshaUser user) {
		model.addAttribute("user", user);
		List<GoodsVo> goodsList= goodsService.getGoodsVoList();
		model.addAttribute("goodsList", goodsList);
		return "goods_list";//返回页面login
	}

你可能感兴趣的:(SpringBoot,SpringBoot实战,Java框架)