Spring MVC 策略模式之 MethodArgumentResolver 源码解析
在 Spring MVC 中,MethodArgumentResolver 是一个非常重要的组件,它用于将请求参数转换为控制器方法的参数。MethodArgumentResolver 是 Spring MVC 策略模式的一部分,它通过实现 resolveArgument 方法来实现参数解析。本文将详细讲解 Spring MVC 策略模式之 MethodArgumentResolver 的源码解析,包括 MethodArgumentResolver 的定义、MethodArgumentResolver 的使用方法、MethodArgumentResolver 的实现原理等。
MethodArgumentResolver 的定义
MethodArgumentResolver 是一个接口,它定义了一个 resolveArgument 方法,用于将请求参数转换为控制器方法的参数。下面是 MethodArgumentResolver 接口的定义:
public interface MethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}
在上面的代码中,MethodArgumentResolver 接口包含了两个方法:
- supportsParameter:用于判断该 MethodArgumentResolver 是否支持当前参数类型。
- resolveArgument:用于将请求参数转换为控制器方法的参数。
MethodArgumentResolver 的使用方法
在 Spring MVC 中,我们可以通过实现 MethodArgumentResolver 接口来自定义参数解析器。下面是一个简单的示例,演示了如何自定义参数解析器:
public class UserArgumentResolver implements MethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
User user = new User();
user.setName(webRequest.getParameter("name"));
user.setAge(Integer.parseInt(webRequest.getParameter("age")));
return user;
}
}
在上面的代码中,我们创建了一个 UserArgumentResolver 类,并实现了 MethodArgumentResolver 接口。在 supportsParameter 方法中,我们判断该参数解析器是否支持 User 类型的参数。在 resolveArgument 方法中,我们将请求参数转换为 User 对象,并返回该对象。
在使用自定义参数解析器时,我们需要将其注册到 RequestMappingHandlerAdapter 中。下面是一个简单的示例,演示了如何注册自定义参数解析器:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<MethodArgumentResolver> resolvers) {
resolvers.add(new UserArgumentResolver());
}
}
在上面的代码中,我们创建了一个 WebMvcConfig 类,并实现了 WebMvcConfigurer 接口。在 addArgumentResolvers 方法中,我们将自定义参数解析器 UserArgumentResolver 添加到 resolvers 列表中。
MethodArgumentResolver 的实现原理
在 Spring MVC 中,参数解析器是通过 RequestMappingHandlerAdapter 来调用的。RequestMappingHandlerAdapter 会遍历所有的参数解析器,找到支持当前参数类型的参数解析器,并调用其 resolveArgument 方法来解析参数。下面是 RequestMappingHandlerAdapter 的源码片段:
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {
private List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>();
public RequestMappingHandlerAdapter() {
this.argumentResolvers.add(new RequestParamMethodArgumentResolver());
this.argumentResolvers.add(new RequestResponseBodyMethodProcessor());
// ...
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// ...
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
if (resolver.supportsParameter(parameter)) {
Object arg = resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
args[i] = arg;
break;
}
}
// ...
}
}
在上面的代码中,我们可以看到 RequestMappingHandlerAdapter 中包含了一个 argumentResolvers 列表,该列表包含了所有的参数解析器。在 handle 方法中,RequestMappingHandlerAdapter 会遍历所有的参数解析器,找到支持当前参数类型的参数解析器,并调用其 resolveArgument 方法来解析参数。
示例说明
下面是两个示例,演示了如何使用 MethodArgumentResolver 自定义参数解析器:
示例一:使用 MethodArgumentResolver 解析自定义参数类型
public class UserArgumentResolver implements MethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
User user = new User();
user.setName(webRequest.getParameter("name"));
user.setAge(Integer.parseInt(webRequest.getParameter("age")));
return user;
}
}
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.POST)
public String addUser(User user) {
// 处理用户添加逻辑
return "success";
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<MethodArgumentResolver> resolvers) {
resolvers.add(new UserArgumentResolver());
}
}
在上面的代码中,我们创建了一个 UserArgumentResolver 类,并实现了 MethodArgumentResolver 接口。在 supportsParameter 方法中,我们判断该参数解析器是否支持 User 类型的参数。在 resolveArgument 方法中,我们将请求参数转换为 User 对象,并返回该对象。在 UserController 中,我们使用 User 类型的参数来接收请求参数。在 WebMvcConfig 中,我们将自定义参数解析器 UserArgumentResolver 添加到 resolvers 列表中。
示例二:使用 MethodArgumentResolver 解析 JSON 数据
public class JsonArgumentResolver implements MethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestBody.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String json = webRequest.getNativeRequest(HttpServletRequest.class).getReader().lines().collect(Collectors.joining(System.lineSeparator()));
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, parameter.getParameterType());
}
}
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/add")
public String addUser(@RequestBody User user) {
// 处理用户添加逻辑
return "success";
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<MethodArgumentResolver> resolvers) {
resolvers.add(new JsonArgumentResolver());
}
}
在上面的代码中,我们创建了一个 JsonArgumentResolver 类,并实现了 MethodArgumentResolver 接口。在 supportsParameter 方法中,我们判断该参数解析器是否支持 RequestBody 注解的参数。在 resolveArgument 方法中,我们将 JSON 数据转换为参数类型的对象,并返回该对象。在 UserController 中,我们使用 @RequestBody 注解来接收 JSON 数据。在 WebMvcConfig 中,我们将自定义参数解析器 JsonArgumentResolver 添加到 resolvers 列表中。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring MVC策略模式之MethodArgumentResolver源码解析 - Python技术站