Spring的HandlerMethodArgumentResolver

前言

我们做项目都有这样类似的情景:用户登录成功过后,前端会得到一个 Token(一个用户一个token)
后面假设后端的接口逻辑需要用到这个 token 去交互一个用户身份,然后完成逻辑。

当然我们可以封装写好一个方法,通过传参 token 再加上我们自己的一些代码逻辑去拿到这个用户的身份。不过我们作为优质的程序员,还是尽量精简自己的代码。

能否有一个方法,在我们进行参数绑定的时候,就注入我们封装的 User 这个实体中呢?

于是:Spring 提供了这么一个接口: HandlerMethodArgumentResolver

看一下这个东西的位置:
在这里插入图片描述

HandlerMethodArgumentResolver是什么?

翻译是处理方法参数的解析器。可以通过它,在前端只传一个 token 的时候交换到用户信息,封装到
User 实体里面

看一下这个接口的源码:

public interface HandlerMethodArgumentResolver {
    boolean supportsParameter(MethodParameter var1);

    @Nullable
    Object resolveArgument(MethodParameter var1, @Nullable ModelAndViewContainer var2, NativeWebRequest var3, @Nullable WebDataBinderFactory var4) throws Exception;
}

接口里面只提供了两个抽象方法:

boolean supportsParameter(MethodParameter var1) 

是否支持此方法参数的解析,如果返回false,则不调用resolveArgument方法

 Object resolveArgument(MethodParameter var1, @Nullable ModelAndViewContainer var2, NativeWebRequest var3, @Nullable WebDataBinderFactory var4) throws Exception;

解析参数的方法,如果前端将 token 放入请求头,则我们从NativeWebRequest中获取 token 参数。该方法的返回值将自动注入到被注解标记的 User 实体中。

怎么使用?

步骤一:

需要先写一个自定义注解(可以用 @CurrentUser ),后面就可以通过这个自定义的注解标识,被它注解过的参数的值都需要由方法参数解析器CurrentUserMethodArgumentResolver 来“注入”

@Target(ElementType.PARAMETER)       
@Retention(RetentionPolicy.RUNTIME)    
public @interface CurrentUser {
}

步骤二:
创建参数解析器类,实现HandlerMethodArgumentResolver接口,重写接口的两个方法:


import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
 
import edp.core.annotation.CurrentUser;
import edp.core.consts.Consts;
import edp.davinci.model.User;
 
/**
 * @CurrentUser 注解 解析器
 */
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().isAssignableFrom(User.class)
                && parameter.hasParameterAnnotation(CurrentUser.class);
    }
 
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
      //写点儿伪代码...
      1. //从请求头中获取sessionId
        String token = webRequest.getHeader("token");
        
      2.  //根据token从通过自己的逻辑获取到用户信息(你可以通过Redis 获取)
     
      3. //记得最后返回拿到的这个 user 对象
    }

在上面的 supportsParameter() 方法中,我们指定了用哪个实体来装我们的用户信息,而且也指定了用哪个注解来标识

步骤三:(也是最后一步)

上面都准备好之后,其实我们发现这个东西还没交给Spring.

定义MVC配置类,实现 WebMvcConfigurer 这个接口,在 addArgumentResolvers 方法中,添加自定义参数解析器,如下:

/**
 * WebMvcConfigurer加入自定义的参数解析器
 */
@Configuration
public class WebForMallMvcConfig implements WebMvcConfigurer {

    /**
     * 允许访问的域
     */
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 仅允许指定域名使用
        if (!StringUtils.isBlank(allowCorsOrigin)) {
            String[] origin = allowCorsOrigin.split(",");
            for (String s : origin) {
                corsConfiguration.addAllowedOrigin(s);
            }
        }
        // 2允许任何头
        corsConfiguration.addAllowedHeader("*");
        // 3允许任何方法(post、get等)
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        return corsConfiguration;
    }

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(currentUserMethodArgumentResolver());
    }

    /**
     * 用户参数解析
     * @return CurrentUserMethodArgumentResolver 
     */
    @Bean
    public CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver() {
        return new CurrentUserMethodArgumentResolver ();
    }

}

Over了…

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值