请求参数处理
请求映射
- 做所有web开发之前最想要做的就是请求映射
编写一个controller,在每一个方法上注解@RequestMapping("/..."),来声明方法处理什么请求。这个声明过程就叫做请求映射 - Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
- 以前:对用户的增删改查操作定义的url路径是/getUser获取用户、/deleteUser删除用户、/editUser修改用户、/saveUser保存用户
- 现在:/user(路径) GET-获取用户、DELETE-删除用户、PUT-修改用户、POST-保存用户
- 核心Filter;HiddenHttpMethodFilter(在springMVC中配置)
- 用法:表单method=post,隐藏域_method=put
这个就是书写方式,担当运用到表单中时,我们会发现,提示中只有get和post请求
哪怕将method的属性值修改为DELETE或PUT都是没有用的,被转化为get请求
所以如果想要发送DELETE或PUT请求,就必须在springMVC中配置。在springMVC中已经进行了自动配置,但这个功能是默认关闭的,所以要手动打开。想要这两个请求可以生效,就必须将method定义为post,而后,在表单上提交一个“_method”的值,也就是
- 手动开启hiddenmethod.filter。在配置文件中,hiddenmethod.filter.enabled:true
- 用法:表单method=post,隐藏域_method=put
Rest原理:(表单提交要使用Rest的时候)
- 1.表单提交会带上_method=PUT(这是在表单上声明的),_method可以自自定义修改,如_m,下面会提到
- 2.因为配置了filter,所以请求会被filter拦截
- 请求是否正常,并且是POST
- 获取_method的值
- 除了GET和POST外还兼容以下请求:PUT/DELETE/PATCH
- 原生request(post),包装模式requestWrapper重写了getMethod方法,返回传入的值,也就是_method的值
- 过滤器链放行的时候就用wrapper。以后的方法调用getMethod时调用requesWrapper的。
- 请求是否正常,并且是POST
一句话:先声明_method,然后发送请求之后filter回拦截请求,将请求里的数据拆分判断,符合条件后,将你定义的请求方式,在利用方法重写的方式做成一个请求,然后放行
Rest使用客户端工具
就可以直接选择请求方式,不用向上面再多写别的步骤(也就是不在进入到转换流程,其实根本就不需要转换流程)
spring:
mvc:
hiddenmethod:
filter:
enabled: true//选择性开启
前面提到的映射书写方式:
@RequestMapping(value = "/user",method = RequestMethod.PUT)
@RequestMapping(value = "/user",method = RequestMethod.GET)
现在都可以用注解的方式代替(只用写路径即可):
@PutMapping("/user")
@GETMapping("/user")
如何修改默认的_method,修改为自定义的名字如-m
- 1.创建配置类(由于接下来用到的组件之间没有依赖,所以设定@Configuration(proxyBeanMethods = false))
- 2.利用@Bean将方法放到容器当中
- 3.实例化HiddenHttpMethodFilter的实例对象
- 4.利用对象.操作符,即:对象.setMethodParam("自定义名"),进行自定义修改_method
- 5.renturn对象
请求映射的原理
每一个请求都会调用doDispatch这个方法
HandlerMapping用于保存每一个请求有哪个对应的handler来处理的关系
所有的请求都映射在了HandlerMapping中
- SpringBoot自动配置欢迎页的WelcomePageHandlerMapping。访问/能访问到index.html;
- SpringBoot自动配置默认的RequestMappingHandlerMapping
- 请求进来以后,挨个尝试所有的HandlerMapping看是否有请求信息
- 如果有就找到这个请求对应的handler
- 如果没有就是下一个HandlerMapping
- 如果需要一些自定义的映射处理,也可以自行在容器中放置HandlerMapping
普通参数与基本注解
注解
- @PathVariable获取路径变量
以前发送rest风格的请求,如@GetMapping()或者@PutMapping()等等请求,当需要传参数是都是以@GetMapping("/car?id=1?username='李四'")这样的形式,这种形式不方便;
为了简便,使用rest风格的传参语句@GetMapping("/car/{id}/owner/{username}"),意为,获取一辆汽车,这个汽车的id是{id},汽车owner(所有者)的名字是{username};
所以请求的路径就可以写为car/3/owner/李四。
现在,我们需要获取页面上展示的一个汽车的信息,需要获取汽车的id以及所有者的姓名;
那我们就要写一个方法,用于获取这些信息,这个方法有自己的属性,这个属性用于存储汽车的信息,二汽车的信息从何而来?
所以需要为这个方法定义形参列表,然后将形参的值赋值给方法中的属性,那么形参的值从何而来?
通过在形参列表中的@PathVariable()来获取,这个注解用于获取访问路径上的k-v键值对,不仅能获取指定key的值,还能获取路径上所有的k-v值(这个需要用指定的map接收)
具体的操作、注解位置、注解用法如下展示:
- @RequestHander获取请求头
请求头中包含了很多有用的信息,将来项目中可能需要获取请求的来源地址,或者获取浏览器的信息
@RequestHander注解的使用依然是在@GetMapping()或者@PutMapping()等等请求的括号当中,与上面的格式相同,(@RequestHander("User-Agent") String userAgent),前面是注解以及要获取的请求头内容,后面是接收数据的形参;
并且,@RequestHander()也可以获取请求头中所有的内容,同上面一样,是将数据全部放在了Map键值对中,需要用map全部接受,语句同上面一样,(@RequestHander Map<String, String> header),演示如下:
- @RequestParam获取请求参数
比如我们的路径中传递了一些参数,按着上面演示的使用方式、使用位置来利用@RequestParam()获取路径上传递的参数
注意:在params列表中缺少了一个inters的值,即足球,原因是,Map<String, String>中k-v不能重复,只能取一个键值对,所以多余的值被去除掉了,可以通过MultiValueMap<String, String>来解决这个问题
- @CookieValue获取cookie值(Cookie虽然也是请求头中的内容,但其有多个值)
比如获取Idea-aca92183的值,按着上面演示的使用方式、使用位置来利用@CookieValue()获取Idea-aca92183的值
获取Idea-aca92183的整个Cookie信息,与之前的语句有所不同,用于接收数据的数据类型必须是Cookie类型
- @RequestBody获取请求体(只有POST请求才有请求体)
1.首先定义一个表单
注意,表单要放在标签中,并且在action属性中标明是什么请求,再提交按钮中,声明提交方式为post
2.在springboot中改变注解为@PostMapping()请求方式
3.在方法中定义形参,用于接收表单提的内容;利用注解@RequestBody来获取表单内容
具体操作、操作位置等如下:
- @RequestAttribute获取request域属性
需要进行页面跳转的测试,用于页面转发的时候,可以取出当前的数据
场景:有goto页面跳转到success页面,在这里先不做具体跳转,而是由goto页面转发到success页面;在转发时,success接收goto页面的域属性
success接受的方法就是利用@RequestAttribute(),括号内填写要获取的属性名,在方法中书写参数列表,这是获取指定属性名的值;
也可以利用HttpServletRequest request;(request是自定义的对象名)将原生的请求全部获取过来,而后通过对象调用方法来获取属性值
- @MatrixVariable矩阵变量
什么是矩阵变量?首先,矩阵变量应该绑定在路径中,并且是路径变量中,示例如下
有一个请求携带请求参数:/cars/{path}?xxx=...&yyy=...;这种方式被称为queryString查询字符串。是利用获取请求参数注解(@RequestParam())的方式获取的
还有另外的方式携带请求参数:/cars/path;low=34;brand=byd,audi,yd 这种以分号来分割k-v的方式就是矩阵
面试题:做页面开发,Cookie仅用了,session里面的内容怎么使用;
session.set(a,b)在session中保存了一个东西,比如set一个a,a的值是b,每一个session都有一个id,这个id叫做jsessionid,这个id会被保存在Cookie里面,每次发请求都会携带这个id,服务器根据这个id找到session的对象,然后调用session对象的get方法找到session当中的内容。而Cookie被禁用后,就无法找到session对象。
解决方案:
以矩阵变量的方式携带jsessionid,/abc;jsessionid=xxx 这样的方式叫做路径重写,把Cookie的值使用矩阵变量的方式进行传递
原本要访问的路径:/boss/1/2
以矩阵方式携带参数变量:/boss/1;age=20/2;age=20 要将矩阵作为一个整体来看,分号前面是访问路径,分号后面是矩阵变量
获取矩阵变量的方式:
依然是在方法中利用注解@MatrixVariable()来获取;注意:SpringBoot默认禁用矩阵变量的功能,需要手动开启:定制化mvc组件
原理:
1.对于路径的处理。UrlPathHelper进行解析。
2.removeSemicolonContent(意思是:移除分号内容)支持矩阵
3.步骤:- 1.实现WebMvcConfigurer接口
2.重写路径映射规则
3.重新设置removeSemicolonContent的属性值为false
- 1.实现WebMvcConfigurer接口
推荐使用:
注意:发送的请求,访问流经要写成语法格式,不能直接写路径
错误示范:@GetMapping("/cars/sell")
正确写法:@GetMapping("/cars/{path}"),具体如下:
当两个路径携带矩阵参数名相同时:
如/boss/1;age=20/2;age=20
那么当变量名相同时,就容易混淆变量值获取来源
所以这时候就要用到一个属性:pathVar,使用方法如下:
测试: