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

 

posted @ 2021-01-02 20:37  QiaoZhi  阅读(441)  评论(0编辑  收藏  举报