注解获取参数
- 常用注解
- @PathVariable:获取restful方式的请求参数
- @RequestHeader:获取http请求的header部分信息
- @RequestAttribute:获取域中数据
- @RequestParam:获取请求体的key-value 参数
- @MatrixVariable:请求路径中,分号前为路径,获取分号后的请求参数
- @CookieValue:获取cookie信息
- @RequestBody:获取整个请求体中的数据
- 更多可查看参数解析器-HandlerMethodArgumentResolver
java
复制代码
@RestController
public class ParameterTestController {
// car/2/owner/zhangsan
//cookie的key值在控制台查看请求头
@GetMapping("/car/{id}/owner/{username}")
public Map<String,Object> getCar(@PathVariable("id") Integer id,
@PathVariable("username") String name,
@PathVariable Map<String,String> pv,
@RequestHeader("User-Agent") String userAgent,
@RequestHeader Map<String,String> header,
@RequestParam("age") Integer age,
@RequestParam("inters") List<String> inters,
@RequestParam Map<String,String> params,
@CookieValue("_ga") String _ga,
@CookieValue("_ga") Cookie cookie){
Map<String,Object> map = new HashMap<>();
map.put("_ga",_ga);
return map;
}
@PostMapping("/save")
public Map postMethod(@RequestBody String content){
Map<String,Object> map = new HashMap<>();
map.put("content",content);
return map;
}
//1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd
//2、SpringBoot默认是禁用了矩阵变量的功能
// 手动开启:原理。对于路径的处理。UrlPathHelper进行解析。
// removeSemicolonContent(移除分号请求内容)
//3、矩阵变量必须有url路径变量才能被解析
@GetMapping("/cars/{path}")
public Map carsSell(@MatrixVariable("low") Integer low,
@MatrixVariable("brand") List<String> brand,
@PathVariable("path") String path){
Map<String,Object> map = new HashMap<>();
map.put("low",low);
map.put("brand",brand);
map.put("path",path);
return map;
}
// /boss/1;age=20/2;age=10
@GetMapping("/boss/{bossId}/{empId}")
public Map boss(
@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
@MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
Map<String,Object> map = new HashMap<>();
map.put("bossAge",bossAge);
map.put("empAge",empAge);
return map;
}
}
@Controller
public class RequestController {
@GetMapping("/goto")
public String goToPage(HttpServletRequest request){
request.setAttribute("msg","成功了...");
request.setAttribute("code",200);
return "forward:/success"; //转发到 /success请求
}
@ResponseBody
@GetMapping("/success")
public Map success(
@RequestAttribute(value = "msg",required = false) String msg,
@RequestAttribute(value = "code",required = false)Integer code,
HttpServletRequest request){
Object msg1 = request.getAttribute("msg");
Map<String,Object> map = new HashMap<>();
return map;
}
}
- 开启矩阵变量功能
- 方法一:配置类实现接口WebMvcConfigurer,重写方法configurePathMatch
java
复制代码
@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
//默认true移除支持矩阵变量,故需设为false
// 不移除;后面的内容。矩阵变量功能就可以生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
- 方法二:自定义WebMvcConfigurer的组件
java
复制代码
//WebMvcConfigurer定制化SpringMVC的功能
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
// 不移除;使矩阵变量功能生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
Servlet API获取参数
- WebRequest、ServletRequest、MultipartRequest、 HttpSession 等等......
- ServletRequestMethodArgumentResolver类
- 也是存在参数解析器-HandlerMethodArgumentResolver中
java
复制代码
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
return (WebRequest.class.isAssignableFrom(paramType) ||
ServletRequest.class.isAssignableFrom(paramType) ||
MultipartRequest.class.isAssignableFrom(paramType) ||
HttpSession.class.isAssignableFrom(paramType) ||
(pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) ||
Principal.class.isAssignableFrom(paramType) ||
InputStream.class.isAssignableFrom(paramType) ||
Reader.class.isAssignableFrom(paramType) ||
HttpMethod.class == paramType ||
Locale.class == paramType ||
TimeZone.class == paramType ||
ZoneId.class == paramType);
}
复杂参数
- Map、Model(map、model里面的数据会被放在request的请求域==request.setAttribute)
- Errors/BindingResult
- RedirectAttributes( 重定向携带数据)
- ServletResponse(response)
java
复制代码
@GetMapping("/params")
public String testParam(Map<String,Object> map,
Model model,
HttpServletRequest request,
HttpServletResponse response){
map.put("hello","world666");
model.addAttribute("world","hello666");
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)Integer code,
HttpServletRequest request){
Object msg1 = request.getAttribute("msg");
Map<String,Object> map = new HashMap<>();
Object hello = request.getAttribute("hello");
Object world = request.getAttribute("world");
Object message = request.getAttribute("message");
return map;
}
参数处理过程
- 从DispatcherServlet类中doDispatch()开始
- HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler())
- HandlerMapping中找到能处理请求的Handler(Controller.method())
- 为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
- 适配器执行目标方法并确定方法参数的每一个值
- mv = ha.handle(processedRequest, response, mappedHandler.getHandler())
- 执行目标方法,RequestMappingHandlerAdapter类的handleInternal()
- mav = this.invokeHandlerMethod(request, response, handlerMethod)
- 参数解析器-HandlerMethodArgumentResolver
- RequestMappingHandlerAdapter类的invokeHandlerMethod()
- 确定将要执行的目标方法的每一个参数的值是什么
- SpringMVC目标方法能写多少种参数类型。取决于参数解析器,当前2.3.4版本查看26种。
- 当前解析器是否支持解析这种参数,支持就调用 resolveArgument()
- 返回值处理器
- RequestMappingHandlerAdapter类的invokeHandlerMethod()
- 当前2.3.4版本查看15种
- RequestMappingHandlerAdapter类的invokeHandlerMethod()
- invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0])
- 进入方法,ServletInvocableHandlerMethod类的invokeAndHandle()
- 进入方法,InvocableHandlerMethod类的invokeForRequest()
- InvocableHandlerMethod类的getMethodArgumentValues()
- 获取到Controller方法上的每一个参数信息
- 使用的参数注解,参数类型等等
- 循环所有参数解析器判断Controller参数的注解是否有对应解析器
- HandlerMethodArgumentResolverComposite类的getArgumentResolver()
- 循环解析获取每一个参数的值
- AbstractNamedValueMethodArgumentResolver类的resolveArgument()
- 自定义类型参数,封装的POJO
- ServletModelAttributeMethodProcessor ,这个参数处理器支持解析
- 会判断当前类型是否为简单类型
- WebDataBinder:web数据绑定器,利用它里面的 Converters 将请求数据转成指定的数据类型,封装到JavaBean中
- GenericConversionService:在设置每一个值的时候,找它里面的所有converter将这个数据类型(request带来参数的字符串)转换到指定的类型
- 自定义 Converter作类型转换用
- 只能针对form表单提交数据,不能在restfulApi下生效
java
复制代码
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void addFormatters(FormatterRegistry registry) {
//自定义转换类型
registry.addConverter(new Converter<String, Pet>() {
@Override
public Pet convert(String source) {
// source获取到的请求内容
if(!StringUtils.isEmpty(source)){
Pet pet = new Pet();
String[] split = source.split(",");
pet.setName(split[0]);
pet.setAge(Integer.parseInt(split[1]));
return pet;
}
return null;
}
});
}
};
}