参数处理原理
HandlerMapping中找到能处理请求的Handler(Controller.method())
为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
适配器执行目标方法并确定方法参数的每一个值
- HandlerAdapter
0-支持方法标注@RequestMapping
1-支持函数编程
… - 执行目标方法
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// No synchronization on session demanded at all...
//执行目标方法
mav = invokeHandlerMethod(request, response, handlerMethod);
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);//真正执行目标方法
//获取每一个参数的值
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
- 参数解析器
确定将要执行的目标方法的每一个参数值是什么
SpringMvc目标方法能写多少种参数类型,取决于参数解析器
当前解析器支持解析哪种参数
如果支持调用resolveArgument - 返回值处理器
- 如何确定目标方法每一个参数的值
============InvocableHandlerMethod==========================
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
if (!this.resolvers.supportsParameter(parameter)) { //判断是否支持
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);//解析这个参数
}
catch (Exception ex) {
// Leave stack trace for later, exception may actually be resolved and handled...
if (logger.isDebugEnabled()) {
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
throw ex;
}
}
return args;
}
挨个判断所有参数解析器那个支持解析这个参数
解析这个参数的值
复杂参数
Map<String,Object> map, Model model, HttpServletRequest request 都是可以给request域中放数据,
request.getAttribute();来获取
@GetMapping("/params")
public String testParam(Map<String,Object> map,
Model model,
HttpServletRequest request,
HttpServletResponse response) {
map.put("hello","6666");
model.addAttribute("world","7777");
request.setAttribute("message","helloWorld");
Cookie cookie = new Cookie("c1","v1");
response.addCookie(cookie);
return "forward:/success";
}
@ResponseBody
@GetMapping("/success")
public Map success(@RequestAttribute(value = "msg",required = false) String msg,
@RequestAttribute(value = "code",required = false) String code,
HttpServletRequest request) {
Object hello = request.getAttribute("hello");
Object world = request.getAttribute("world");
Object message = request.getAttribute("message");
Object msg1 = request.getAttribute("msg");
Map<String,Object> map = new HashMap<>();
map.put("reqMethod_msg",msg1);
map.put("annotation_msg",msg);
map.put("hello",hello);
map.put("world",world);
map.put("message",message);
return map;
}
@Configuration(proxyBeanMethods = false)
public class WebConfig /*implements WebMvcConfigurer */ {
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
methodFilter.setMethodParam("_m");
return methodFilter;
}
// @Override
// public void configurePathMatch(PathMatchConfigurer configurer) {
// UrlPathHelper urlPathHelper = new UrlPathHelper();
// //不移除分号
// urlPathHelper.setRemoveSemicolonContent(false);
// configurer.setUrlPathHelper(urlPathHelper);
// }
@Bean //WebMvcConfigurer
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
//自定义参数类型----改用lambda表达式写法
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new Converter<String, Pet>() {
@Override
public Pet convert(String source) {
//fsf,sf
if (!StringUtils.isEmpty(source)) {
Pet pet = new Pet();
String[] split = source.split(",");
pet.setName(split[0]);
pet.setAge(Integer.valueOf(split[1]));
return pet;
}
return null;
}
});
}
// @Override
// public void addFormatters(FormatterRegistry registry) {
// registry.addConverter((String source) -> {
// if (!StringUtils.isEmpty(source)) {
// Pet pet = new Pet();
// String[] split = source.split(",");
// pet.setName(split[0]);
// pet.setAge(Integer.valueOf(split[1]));
// return pet;
// }
// return null;
//
// });
// }
};
}
}