• HandlerMethodArgumentResolver 接口的用法


      之前获取登录用户的方法是BaseController中封装统一的方法或者封装一个UserContextHolder的工具类,然后代码中用工具类获取。最近项目中看到Controller中获取当前用户直接参数上标记一下。

    1. 用户类和获取登录用户的工具类

    package com.xm.ggn.utils;
    
    import lombok.Data;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 18:43 2021/1/2
     */
    @Data
    public class User {
    
        private String username;
    
        private String fullname;
    }

    获取登录用户的工具类:

    package com.xm.ggn.utils;
    
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 12:52 2021/1/2
     */
    public class UserCeontextHolder {
    
        /**
         * 模拟获取用户工具的方式,可以从session获取;前后端分离可以根据token获取
         *
         * @return
         */
        public static User getCurrentUser() {
            User user = new User();
            user.setUsername("zs");
            user.setFullname("张三");
            // 权限以及其他相关等信息
            return user;
        }
    }

    2. 自定义注解以及Controller做标记

    package com.xm.ggn.utils;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 19:29 2021/1/2
     */
    @Target({ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginUser {
    }

    测试Controller:

    package com.xm.ggn.controller.common;
    
    import com.xm.ggn.utils.LoginUser;
    import com.xm.ggn.utils.User;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 0:23 2020/12/12
     */
    @RestController
    @Slf4j
    public class TestController {
    
        @RequestMapping("/test")
        public User test(User user) {
            log.debug("user: {}", user);
            return user;
        }
    
        @RequestMapping("/test2")
        public User test2(@LoginUser User user) {
            log.debug("user: {}", user);
            return user;
        }
    }

    3.自定义参数解析器

    package com.xm.ggn.utils;
    
    import org.springframework.core.MethodParameter;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 18:48 2021/1/2
     */
    @Component
    public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver {
        @Override
        public boolean supportsParameter(MethodParameter parameter) {return parameter.getParameterType().isAssignableFrom(User.class) && parameter.hasParameterAnnotation(LoginUser.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
            return UserCeontextHolder.getCurrentUser();
        }
    }

    4.添加到Spring中

    package com.xm.ggn.config;
    
    
    import com.xm.ggn.utils.UserMethodArgumentResolver;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.servlet.DispatcherServlet;
    import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
    
    import java.util.List;
    
    /**
     * 设置匹配指定后缀*.action *.do的路径(导致静态资源文件失败,没有解决)
     *
     * @author Administrator
     */
    @Configuration
    public class UrlMatchConfig extends WebMvcConfigurationSupport {
    
        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
            // setUseSuffixPatternMatch 后缀模式匹配
            configurer.setUseSuffixPatternMatch(true);
            // setUseTrailingSlashMatch 自动后缀路径模式匹配
            configurer.setUseTrailingSlashMatch(true);
        }
    
        /**
         * 设置匹配*.action后缀请求
         *
         * @param dispatcherServlet
         * @return
         */
        @Bean
        public ServletRegistrationBean servletRegistrationBean(DispatcherServlet dispatcherServlet) {
            ServletRegistrationBean servletServletRegistrationBean = new ServletRegistrationBean(dispatcherServlet);
            // 参数接受可变类型的多个参数支持多种后缀的匹配
            servletServletRegistrationBean.addUrlMappings("*.action", "*.do");
            return servletServletRegistrationBean;
        }
    
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        }
    
        @Autowired
        private UserMethodArgumentResolver userMethodArgumentResolver;
    
        /**
         * 参数解析器
         *
         * @param argumentResolvers
         */
        @Override
        protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(userMethodArgumentResolver);
            super.addArgumentResolvers(argumentResolvers);
        }
    }

    5.测试

    liqiang@root MINGW64 /e/xiangmu/bs-media/media-server (master)
    $ curl http://localhost:8088/test.do
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-100    33    0    33    0     0     39      0 --:--:-100    33    0    33    0     0     38      0 --:--:-- --:--:-- --:--:--    39{"username":null,"fullname":null}
    
    liqiang@root MINGW64 /e/xiangmu/bs-media/media-server (master)
    $ curl http://localhost:8088/test2.do
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-100    37    0    37    0     0    787      0 --:--:-- --:--:-- --:--:--  2312{"username":"zs","fullname":"张三"}

      如果Controller所有的User方法都是获取当前登录的用户,可以去掉自定义注解,然后修改UserMethodArgumentResolver为:

    package com.xm.ggn.utils;
    
    import org.springframework.core.MethodParameter;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 18:48 2021/1/2
     */
    @Component
    public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver {
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            return parameter.getParameterType().isAssignableFrom(User.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
            return UserCeontextHolder.getCurrentUser();
        }
    }

    补充:class1.isAssignableFrom(class2)  和 instanceof 的区别 

    instanceof  关键字判断某个对象是否是某个类的实例,子类的对象也是父类的对象

    class1.isAssignableFrom(class2) 方法用于判定此 class1对象所表示的类或接口与指定的 class2参数所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回 true;否则返回 false。

        public static void main(String[] args) {
            List<String> result = new ArrayList<>();
            result.add("1");
            System.out.println(result instanceof ArrayList);
            System.out.println(result instanceof List);
            // 测试
            System.out.println("====");
            System.out.println(List.class.isAssignableFrom(ArrayList.class));
            System.out.println(List.class.isAssignableFrom(List.class));
            System.out.println(ArrayList.class.isAssignableFrom(ArrayList.class));
            System.out.println(ArrayList.class.isAssignableFrom(List.class));
        }

    结果:

    true
    true
    ====
    true
    true
    true
    false

  • 相关阅读:
    mysql(二)数据类型
    mysql(一)
    MySQL8 安装官方示例 employees 数据库
    Elasticsearch入门
    redis入门
    git 基本使用
    vue-cli4环境变量配置和代理跨域配置
    nginx配置
    彻底搞清浏览器和服务器跨域
    File文件过滤器
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/14223798.html
Copyright © 2020-2023  润新知