Featured image of post Spring MVC扩展点——控制层参数的解析映射

Spring MVC扩展点——控制层参数的解析映射

Spring MVC扩展点——控制层参数的解析映射HandlerMethodArgumentResolver

HandlerMethodArgumentResolver是SpringMVC中非常重要的一个角色,负责将请求中的信息转换成处理器方法所需的参数类型。

最近做的一个项目是需要对某个参数进行解密操作,我不像在每个方法中单独对参数进行解析。原本打算在AOP中实现,将参数解析之后放ThreadLocal中,在方法完成后释放ThreadLocal。但是后来了解到这个扩展点,觉得这个扩展点来实现这个参数的解析过程更好。

允许开发者将请求参数直接映射到处理器方法的参数上,而无需手动解析请求。 也就是是允许在请求进入控制层的方法之前,对一些参数进行修改,可以实现对某些数据的加解密操作等,这样统一处理就能够,不用在后面的流程中再进行数据的处理。同时配合自定义的参数注解,可以实现按需设置是否开启参数的解析。

接口源码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public interface HandlerMethodArgumentResolver {

    //判断该参数是否支持用该自定义解析器进行解析
    boolean supportsParameter(MethodParameter parameter);
    
    @Nullable
    Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
          NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

}

使用示例:

自定义注解:

1
2
3
4
5
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Addr {

}

HandlerMethodArgumentResolver:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class AddrResolver implements HandlerMethodArgumentResolver {
//只有含有上述注解的参数才会执行下面参数解析
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Addr.class);
    }
    
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        String remoteHost = request.getRemoteHost();
        int remotePort = request.getRemotePort();
        String re=remoteHost+":"+remotePort;
        return re;
    }
}

上述代码的参数解析只是简单模拟了从请求中获取到请求地址和端口封装成一个字符串,Controller层的方法参数address将会获得解析处理后的结果。

将自定义的参数注册到Spring容器中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public AddrResolver currUserArgumentResolver(){
        return new AddrResolver();
    }

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

使用示例

1
2
3
4
@GetMapping("/getAddr")
public String getAddr(@Addr() String address  ) {
    return address;
}

实验结果:

image-20240521151654740