HandlerMethodArgumentResolver(参数解析器)的作用+使用小案例

前言

今天在做项目时遇到了一个有关参数解析HandlerMethodArgumentResolver的使用疑惑。我想作为新手的我在此和大家一起交流并记录。接下来开始发车......
正文

 

首先先来认识一下这个接口,HandlerMethodArgumentResolver。

    public interface HandlerMethodArgumentResolver {
        boolean supportsParameter(MethodParameter var1);
     
        Object resolveArgument(MethodParameter var1, ModelAndViewContainer var2, NativeWebRequest var3, WebDataBinderFactory var4) throws Exception;
    }

大家可以看到,这个接口有两个方法,supportsParameter和resolveArgument。

方法supportsParameter很好理解,返回值是boolean类型,它的作用是判断Controller层中的参数,是否满足条件,满足条件则执行resolveArgument方法,不满足则跳过。

而resolveArgument方法呢,它只有在supportsParameter方法返回true的情况下才会被调用。用于处理一些业务,将返回值赋值给Controller层中的这个参数。

因此呢,我们可以将HandlerMethodArgumentResolver理解为是一个参数解析器,我们可以通过写一个类实现HandlerMethodArgumentResolver接口来实现对Controller层中方法参数的修改。
项目代码举例

未使用参数解析器时的Controller控制器:

    @Controller
    @RequestMapping("/goods")
    public class GoodsController {
        private static Logger logger = LoggerFactory.getLogger(GoodsController.class);
        @Autowired
        UserService userService;
        @RequestMapping("/to_list")
        public String to_login(Model model,HttpServletResponse response,
                            @CookieValue(value=UserService.TOKEN,required = false)String cookieToken,
                            @RequestParam(value = UserService.TOKEN,required = false) String paramToken) {
            if(StringUtils.isEmpty(cookieToken)&&StringUtils.isEmpty(paramToken)){
                return "login";
            }
            String token = StringUtils.isEmpty(cookieToken) ? paramToken : cookieToken;
            User user=userService.getByToken(response,token);
            logger.info(user.toString());
            model.addAttribute("user",user);
            return "goods_list";
        }
    }

请大家仔细看to_login方法的这两个参数  cookieToken和paramToken,再仔细看一下方法体。不难看出,这两个参数和方法体中的语句代码就是为了,通过cookie或request其中的token这一变量来查询用户user的信息。

但是大家发没发现,这一个方法,就为了简简单单的这一个小功能,就写了这么多代码。是不是有点过分臃肿呢?而且假如还有其他方法会用到用户user这一信息变量呢?

好的,这个时候我们就可以使用HandlerMethodArgumentResolver接口来进行一下小小的优化。

使用HandlerMethodArgumentResolver解析器后:

写一个类实现HandlerMethodArgumentResolver接口

     
    @Service
    public class UserArgumentResolver implements HandlerMethodArgumentResolver {
        @Autowired
        MiaoshaUserService userService;
        public boolean supportsParameter(MethodParameter parameter) {
            Class<?> clazz = parameter.getParameterType();
            return clazz==MiaoshaUser.class;
        }
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
     
            HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
            HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
     
            String paramToken = request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN);
            String cookieToken = getCookieValue(request, MiaoshaUserService.COOKI_NAME_TOKEN);
            if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
                return null;
            }
            String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
            return userService.getByToken(response, token);
        }
        private String getCookieValue(HttpServletRequest request, String cookiName) {
            Cookie[]  cookies = request.getCookies();
            for(Cookie cookie : cookies) {
                if(cookie.getName().equals(cookiName)) {
                    return cookie.getValue();
                }
            }
            return null;
        }
    }

把我们编写的这个类,注册到配置文件中去

    @Configuration
    public class WebConfig  extends WebMvcConfigurerAdapter{
        @Autowired
        UserArgumentResolver userArgumentResolver;
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(userArgumentResolver);
        }
    }

最后,我们的控制类就可以这样写了

        @RequestMapping("/to_list")
        public String list(Model model,MiaoshaUser user) {
            model.addAttribute("user", user);
            //查询商品列表
            List<GoodsVo> goodsList = goodsService.listGoodsVo();
            model.addAttribute("goodsList", goodsList);
            return "goods_list";
        }

 

原文链接:https://blog.csdn.net/qq_36408229/article/details/104436508
posted @ 2023-03-03 15:14  甜菜波波  阅读(264)  评论(0编辑  收藏  举报