四种方式
1)注解7个
@PathVariable @RequestHandler @MethodAttribute @RequestParam @MatrixVariable
@CookieValue @RequestBody
例1:@RequestParam
@RestController
public class HelloController {
@RequestMapping("/1.png")
public String hello(@RequestParam String userName){
return "静态请求"+userName;
}
页面请求 http://localhost:8080/1.png?userName=libai 注意?后面的大小写很重要
2)ServletAPI
WebRequest ServletRequest MultipartRequest HttpSession javax.servlet.http.PushBuilder
Principal InputStream Reader HttpMethod Local TimeZone ZoneId
举例
@RequestMapping("/1.png")
public String hello(HttpSession httpSession){
return "静态请求"+httpSession;
}
3)复杂参数
Map Errors/BindingResult Model RedirectAttributes ServletResponse
SessionStatus UriComponentsBuilder ServletUriComponentsBuilder
举例
@RequestMapping("/1.png")
public String hello(Model model){
return "静态请求"+model; //model 是页面可以拿到请求域中的数据
}
4)自定义对象参数
可以自动类型转换与格式化,可以级联封装
举例:页面提交过来的k v键值对都会被封装到person
@RequestMapping("/1.png")
public String hello(Person person){
return "静态请求"+person; //model 是页面可以拿到请求域中的数据
}
举例
1.例1 @PathVariable
用@PathVariable Map<String,String> pv 会自动把请求参数封装到pv
@RestController
public class ParameterTestController {
// @GetMapping("/car?id=1") //获取id为1的car,这样比较麻烦,改为以下
@GetMapping("/car/{id}/owner/{username}") //请求方式为car/1 就是获取1号汽车,可能有多个参数第二个就是username
public Map<String,Object> getCar(@PathVariable("id") Integer id, //获取路径上的id
@PathVariable("username") String name,
@PathVariable Map<String,String> pv){ //除了以上两个方式,还可以把路径上所有key value提取
Map<String,Object> map=new HashMap<>();
map.put("id",id);//把获得的id值放到map
map.put("name",name);
map.put("pv",pv);
return map;
}
}
浏览器请求
http://localhost:8080/car/1/owner/%E6%9D%9C%E7%94%AB
输出,可见
2.例2 获取请求头里面的参数
打算获取如下信息
Response Header中的Host User-Agent:
在controller请求参数中增加
@RequestHeader("User-Agent") String userAgent, //获取请求头 @RequestHeader Map<String,String> header //把请求头都放到一个Map<String,String>
@RestController
public class ParameterTestController {
// @GetMapping("/car?id=1") //获取id为1的car,这样比较麻烦,改为以下
@GetMapping("/car/{id}/owner/{username}") //请求方式为car/1 就是获取1号汽车,可能有多个参数第二个就是username
public Map<String,Object> getCar(@PathVariable("id") Integer id, //获取路径上的id
@PathVariable("username") String name,
@PathVariable Map<String,String> pv, //把路径参数自动封装到Map pv,注意必须是string,string
@RequestHeader("User-Agent") String userAgent, //获取请求头
@RequestHeader Map<String,String> header
){ //除了以上两个方式,还可以把路径上所有key value提取
Map<String,Object> map=new HashMap<>();
map.put("id",id);//把获得的id值放到map
map.put("name",name);
map.put("pv",pv);
map.put("userAgent",userAgent);
map.put("header",header);
return map;
}
}
执行
例3 获取请求参数
html: ?后面的就是请求参数 索多个用&分开
<a href="car/3/owner/白居易?age=18&interest=basketball&interest=football">/car/{id}/owner/{username}</a>
controller方法请求参数增加
@RestController
public class ParameterTestController {
// @GetMapping("/car?id=1") //获取id为1的car,这样比较麻烦,改为以下
@GetMapping("/car/{id}/owner/{username}") //请求方式为car/1 就是获取1号汽车,可能有多个参数第二个就是username
public Map<String,Object> getCar(@PathVariable("id") Integer id, //获取路径上的id
@PathVariable("username") String name,
@PathVariable Map<String,String> pv, //把路径参数自动封装到Map pv,注意必须是string,string
@RequestHeader("User-Agent") String userAgent, //获取请求头
@RequestHeader Map<String,String> header,
@RequestParam("age") Integer age,
@RequestParam("interest") List<String> interest,
@RequestParam Map<String,String> params
){ //除了以上两个方式,还可以把路径上所有key value提取
Map<String,Object> map=new HashMap<>();
map.put("id",id);//把获得的id值放到map
map.put("name",name);
map.put("pv",pv); //pv是map
map.put("userAgent",userAgent);
map.put("header",header);//header是map
map.put("age",age);
map.put("interest",interest);
map.put("params",params);//params是map
return map;
}
}
输出
例4 获取cookie
也就是要获取
修改controller方法参数
注意可以使用Cookie这个对象 ,实现response回传cookie
// @CookieValue("_ga") String _ga
@CookieValue("JSESSIONID") String sessionId,//一般方式获取cookievalue,JSESSIONID是页面上实际存在的cookie name
@CookieValue("JSESSIONID") Cookie cookie //定义Cookie对象,
map.put("sessionId",sessionId);
map.put("cookie",cookie);
System.out.println(cookie.getName()+"---->"+cookie.getValue()); //证明把cookie想发回去,可以用response
--------------------------以上是 Get请求-----------
------------------------------------以下是Post请求--------------------------------
例5 获取表单提交内容@RequestBody
(获取请求体,只有POST请求才有,比如表单)
修改html
<form action="/save" method="post">
测试@RequestBody获取数据<br/>
用户名:<input name="userName" /><br/>
邮箱:<input name="email" />
<input type="submit" value="提交">
</form>
新建一个PostMapping controller
@PostMapping("/save")
public Map<String,Object> postVerify(@RequestBody String content){
Map<String,Object> map=new HashMap<>();
map.put("content",content);
return map;
}
表单提交后
发现表单Request请求会有Payload带过来
例6 请求属性@RequestAttribute
获取Request域中保存的属性,主要用于页面转发
新建2个controller:第1个RequestController 第2个 Success
当页面请求http://localhost:8080/goto时会使用 return "forward:/success" 进行转发
注意冒号后面不要有空格,不然出现white Page
@Controller
public class RequestController {
@GetMapping("/goto")
public String goToPage(HttpServletRequest request){ //参数是原生Request
request.setAttribute("msg","成功了");
request.setAttribute("code","200");
return "forward:/success"; //转发到本项目下success目录
}
@ResponseBody
@GetMapping("/success") //下文用map主要是为了打印方便
public Map Success(@RequestAttribute("msg") String msg2,//方法一,可以取出request.setAttribute内容
@RequestAttribute("code") Integer code2,
HttpServletRequest request //第二种方法,这是把原生请求再拿过来,里面自然也包含其属性
){
Object msg1=request.getAttribute("msg"); //原生请求
Map<String,Object> map=new HashMap<>();
map.put("reqMethod",msg1);
map.put("annotation_msg",msg2);
return map;
}
}
验证结果
例6 @MatrixVariable(获取矩阵变量:绑定在路径中)
页面阿请求路径带参数有两种方式
1)链接中用? &这些来,使用@PathVariable来处理
<a href="car/3/owner/白居易?age=18&interest=basketball&interest=football">/car/{id}/owner/{username}</a>
2)矩阵变量绑定在路径中,以分号隔开
<a href="/cars/sell;low=33; brand=Panda,Aodi,BaoMa">@MatrixVariable(矩阵变量)</a>
或者
<a href="/cars/sell;low=33;brand=Changcheng;brand=Wuling;brand=Jialing">@MatrixVariable(矩阵变量)</a>
3)或者层级关系的
如果使用正常路径写法 /boss/1/2 这个代表1号老板下的2号员工
可以写为如下方式1号老板age比如大于30的2号员工比如age大于15;两层都有age属性
<a href="/boss/1;age=30/2;age=15">@MatrixVariable(矩阵变量)/boss/{bossId}/{empId}</a>
1;age=30 是一个整体,分号前面是访问路径,分号后面是矩阵变量,多个变量又以分号区分
2;age=15也是一个整体
4)适用场景:cookie被禁用,如何找到session里面的内容
session保存原理:
session.set(a,b)-->生成一个jssesionId-->保存在cookie-->每次发请求都会携带cookie
一旦cookie被禁用,找不到jessionid也就找不到seesion对象
这时候可以这样访问 : /abc;jessionid=xxxxx 这就是url重写,把原来cookie的内容使用矩阵变量的方式传递过来;主要是用请求参数的方式和正常的就无法区分,所以专门用矩阵变量方式传递
所以分号后面的都是矩阵变量内容
5)
测试点击页面链接
<a href="/cars/sell;low=33; brand=Panda,Aodi,BaoMa">@MatrixVariable(矩阵变量)</a></br>
出现
报错没有找到 low变量,原因在于springboot默认禁用矩阵变量,路径中出现了%20
springboot底层是Spring MVC,搜索到
以下用于配置映射
UrlPathHelper 是url 路径帮助器,进入发现
private boolean removeSemicolonContent = true; 用于移除分号
进入removeSemicolonContent
下面有方法:如果分号被移除,分号后面的参数会被截掉
public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
this.checkReadOnly();
this.removeSemicolonContent = removeSemicolonContent;
}
总之对于路径处理都是使用UrlPathHelper进行解析的
removeSemicolonContent移除分号内容就是决定要不要支持矩阵变量,因为矩阵变量要用分号
修改配置,原理参照 下面单独一级目录: 如何更改SpringMVC自动配置,三种方法
package com.i7i8i9.boot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;
@Configuration(proxyBeanMethods = false) //false代表组件之间没有依赖,可以快速编译
public class WebConfig /* implements WebMvcConfigurer */{
@Bean
public HiddenHttpMethodFilter HiddenHttpMethodFilter(){
HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
hiddenHttpMethodFilter.setMethodParam("_mm");
return hiddenHttpMethodFilter;
}
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override //new的时候实现一个需要的方法
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper=new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
// @Override //重写需要的WebMvcConfigurer方法,jdk8不许要全部重写
// public void configurePathMatch(PathMatchConfigurer configurer) {
// UrlPathHelper urlPathHelper=new UrlPathHelper();
// urlPathHelper.setRemoveSemicolonContent(false); //默认的去除分号RemoveSemicolonContent是true,所以此处要new一个新的urlPathHelper
// configurer.setUrlPathHelper(urlPathHelper);
// }
}
更改cotroller
package com.i7i8i9.boot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
public class RequestController {
@GetMapping("/goto")
public String goToPage(HttpServletRequest request){ //参数是原生Request
request.setAttribute("msg","成功了");
request.setAttribute("code","200");
return "forward:/success"; //转发到本项目下success目录
}
@ResponseBody
@GetMapping("/success") //下文用map主要是为了打印方便
public Map Success(@RequestAttribute("msg") String msg2,//方法一,可以取出request.setAttribute内容
@RequestAttribute("code") Integer code2,
HttpServletRequest request //第二种方法,这是把原生请求再拿过来,里面自然也包含其属性
){
Object msg1=request.getAttribute("msg"); //原生请求
Map<String,Object> map=new HashMap<>();
map.put("reqMethod",msg1);
map.put("annotation_msg",msg2);
return map;
}
// a href="/cars/sell;low=33;brand=Panda,Aodi,BaoMa"
// @GetMapping("/cars/sell") // /cars/sell会带很多矩阵变量而不是请求参数
@GetMapping("/cars/{path}")
public Map carSell(@MatrixVariable("low") Integer low,
//@MatrixVariable("brand") List<String> brand,
@PathVariable("path") String path){ //主要是为了看看path究竟是什么
System.out.println(path);
Map<String,Object> map=new HashMap<>();
map.put("low",low);
// map.put("brand",brand);
map.put("path",path);
return map;
}
}
重新运行,打开网页
,去除缓存页面 Whitelabel Error Page
百思不得其解,
1)验证1:在controller打印path,发现输出是正确的:
去掉分号后面的,则出现
看上去是没有解析到分号后面的参数,怀疑是urlPathHelper问题,但是搜索
@GetMapping("/cars/{path}") urlPathHelper都没有看出异常,一晚无解
有的时候带第一个分号是有效的http://localhost:8080/cars/sell;low=33;加上brand=panda,aodi,baoma则不再提示low找不到,而是提示list brand找不到,怀疑是list不对,controller去掉该变量,则又返回提示404
2)早晨重启电脑,还是404,打算再搜索MatrixVariable寻找完整代码,发现
尝试改成@RestController后重新运行问题解决
如何更改SpringMVC自动配置,三种方法
1)不使用@EnableWebMVC
使用@Configuration+WebMvcConfigurer自定义规则
@Configuration代表在容器中
搜索WebMvcConfigurer,其是一个接口。里面定义了configurePathMatch方法
其实在自动配置WebMvcAutoConfiguration类,中也是实现了该接口
我们自己可以写一个配置类实现
方法1:直接使配置类继承WebMvcConfigurer ,同时由于jdk8只需改写要实现的方法
package com.i7i8i9.boot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;
@Configuration(proxyBeanMethods = false) //false代表组件之间没有依赖,可以快速编译
public class WebConfig implements WebMvcConfigurer {
@Bean
public HiddenHttpMethodFilter HiddenHttpMethodFilter(){
HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
hiddenHttpMethodFilter.setMethodParam("_mm");
return hiddenHttpMethodFilter;
}
@Override //重写需要的WebMvcConfigurer方法,jdk8不许要全部重写
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper=new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false); //默认的去除分号RemoveSemicolonContent是true,所以此处要new一个新的urlPathHelper
configurer.setUrlPathHelper(urlPathHelper);
}
}
方法2在配置类里面加@Bean WebMvcConfigure
package com.i7i8i9.boot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;
@Configuration(proxyBeanMethods = false) //false代表组件之间没有依赖,可以快速编译
public class WebConfig /* implements WebMvcConfigurer */{
@Bean
public HiddenHttpMethodFilter HiddenHttpMethodFilter(){
HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
hiddenHttpMethodFilter.setMethodParam("_mm");
return hiddenHttpMethodFilter;
}
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override //new的时候实现一个需要的方法
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper=new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
// @Override //重写需要的WebMvcConfigurer方法,jdk8不许要全部重写
// public void configurePathMatch(PathMatchConfigurer configurer) {
// UrlPathHelper urlPathHelper=new UrlPathHelper();
// urlPathHelper.setRemoveSemicolonContent(false); //默认的去除分号RemoveSemicolonContent是true,所以此处要new一个新的urlPathHelper
// configurer.setUrlPathHelper(urlPathHelper);
// }
}
2)urlhepler很有用
进入其类,
ctrl+F12查看其方法