一个网站最基本的功能就是匹配请求,获取请求数据,处理请求(业务处理),请求响应,我们今天来看SpringBoot中怎么进行请求匹配和请求响应。
文章包含的内容如下:
- 简单示例
- 请求映射
- 请求响应
- 视图渲染(JSP)
1 SpringBoot web的一个简单示例
1.1 新建项目
在https://start.spring.io/初始化一个空项目,添加WEB模块依赖。
1.2 新建一个Java类
@Controller
public class HelloController {
@RequestMapping(value="hello")
@ResponseBody
public String hello(){
return "hello friends";
}
}
1.3 启动项目,查看日志
只保留我们需要关注点的部分。
[main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hello]}" onto public java.lang.String com.liuawei.spring.web.controller.HelloController.hello()
[main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)Started SpringbootWebSampleApplication in 14.005 seconds (JVM running for 15.384)
看日志可以发现我们/hello的路径已经被匹配,还有默认使用的是SpringBoot默认的内置容器端口号是8080
1.4 查看结果
我们在浏览器输入http://localhost:8080/hello 查看页面结果。
我们看到上面代码有三个注解@Controller,@RequestMapping,@ResponseBody
@Controller:标记在一个类上,使用它标记的类就是一个SpringMVCController对象,分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。
@RequestMapping:标记在类或者方法上,处理请求地址映射。
@ResponseBody:标记在方法的返回对象上面,通过HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
2 请求映射
涉及到XML解析POM文件添加对应的依赖:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
2.1 @RequestMapping注解源码分析
// 请求映射的名字
String name() default "";
// 和path请求一样
@AliasFor("path")
String[] value() default {};
// 匹配请求路径
@AliasFor("value")
String[] path() default {};
// 请求允许的方法 GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
RequestMethod[] method() default {};
// 匹配请求参数 请求参数有这些参数,没有这些参数,包括这些参数,不包括这些参数 等再能匹配
String[] params() default {};
// 匹配请求头 如上
String[] headers() default {};
// 匹配请求类型 eg:Accept: text/html,application/xhtml+xml,application/xml;
String[] consumes() default {};
// 匹配请求响应类型 eg:Content-Type: text/html;charset=UTF-8
String[] produces() default {};
2.2 请求匹配
2.2.1 请求路径匹配 value
/**
* 路径匹配
* @return
*/
@RequestMapping(value="path",method=RequestMethod.GET)
public String byPath(){
return "匹配路径 GET请求";
}
/**
* 路径模式匹配 path/pattern/下面的路径
* @return
*/
@RequestMapping(value="path/pattern/*",method=RequestMethod.GET)
public String byPathPattern1(HttpServletRequest request){
return "路径模式匹配"+request.getRequestURI();
}
/**
* 路径模式匹配2 path/pattern/下面的路径并且结尾是do
* @return
*/
@RequestMapping(value="path/pattern/*.do",method=RequestMethod.GET)
public String byPathPattern2(HttpServletRequest request){
return "路径模式匹配"+request.getRequestURI();
}
模拟请求:
- http://localhost:8080/mapping/path/pattern/123.do
- http://localhost:8080/mapping/path/pattern/abc
- http://localhost:8080/mapping/path/pattern/123.do
2.2.2 请求方法匹配 method
/**
* 方法匹配 指定的方法可以访问
* @return
*/
@RequestMapping(value="method",method={RequestMethod.POST,RequestMethod.DELETE})
public String byMethod(HttpServletRequest request){
return "方法过滤请求"+request.getMethod();
}
模拟请求:
2.2.3 请求参数匹配
/**
* 有相对应的参数才可以访问
* @return
*/
@RequestMapping(value="params/v1",method=RequestMethod.GET,params="name")
public String byParams(HttpServletRequest request){
return "请求参数必须包含name才可以访问"+request.getParameterMap();
}
/**
* 不包含相对应的参数才可以访问
* @return
*/
@RequestMapping(value="params/v2",method=RequestMethod.GET,params="!name")
public String byParams2(HttpServletRequest request){
return "请求参数不包含name才可以访问"+request.getParameterMap();
}
模拟请求:
- http://localhost:8080/mapping/params/v1?name=shuage
- http://localhost:8080/mapping/params/v2?name=shuage
2.2.4 请求头匹配
/**
* 有相对应的请求头才可以访问
* @return
*/
@RequestMapping(value="headers",method=RequestMethod.GET,headers={"token","userid"})
public String byHeaders(HttpServletRequest request){
return "请求头必须包含token,userid才可以访问"+request.getHeaderNames();
}
2.2.5 请求类型匹配
/**
* 只接受application/json;charset=UTF-8的请求头
* @param json
* @return
*/
@PostMapping(value="consume/json",consumes=MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String consumeJson(@RequestBody String json){
return "consumeJson请求参数:"+json;
}
/**
* 只接受application/xml的请求头
* @param xml
* @return
*/
@PostMapping(value="consume/xml",consumes=MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public String consumeXml(@RequestBody String xml){
return "consumeXml请求参数:"+xml;
}
2.2.6 响应类型匹配
/**
* 响应JSON格式
* @return
*/
@GetMapping(value="produce/json",produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Map<String, Object> byProduceJson(){
Map<String, Object> result = new HashMap<>();
result.put("name", "json");
result.put("age", 27);
return result;
}
/**
* 响应XML格式
* @return
*/
@GetMapping(value="produce/xml",produces=MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public Map<String, Object> produceXml(){
Map<String, Object> result = new HashMap<>();
result.put("name", "xml");
result.put("age", 27);
return result;
}
/**
* 响应图片文件流
* @param response
* @throws IOException
*/
@GetMapping(value="produce/jpeg",produces=MediaType.IMAGE_JPEG_VALUE)
@ResponseBody
public void produceJpeg(HttpServletResponse response) throws IOException{
File file = new File(
"D:\\liuawei\\springbootbucket\\resources\\zuixihuandewangfei.jpeg");
FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream();
byte [] data = new byte[1024];
while (fis.read(data)!=-1) {
os.write(data);
}
os.flush();
os.close();
}
模拟请求:
- http://localhost:8080/mapping/produce/json
- http://localhost:8080/mapping/produce/xml
- http://localhost:8080/mapping/produce/jpeg
为了方便大家看到效果:我把我测试的请求postman测试上传到github,大家可以下载下来导入到自己本地的postman进行测试。用例地址
3 请求响应
3.1 ResponseBody
@ResponseBody+ResponseEntity
/**
* 响应内容
* @return
*/
@RequestMapping(value="/toContent")
@ResponseBody
public String toStr(){
return "响应文本内容";
}
/**
* 响应内容 并设置响应码
* @return
*/
@RequestMapping(value="/entity/status")
public ResponseEntity<String> entityStatus(){
ResponseEntity<String> responseEntity =new ResponseEntity<>("401未授权!",HttpStatus.UNAUTHORIZED);
return responseEntity;
}
/**
* 响应内容 设置响应吗 设置响应头
* @return
*/
@RequestMapping(value="/entity/header")
public ResponseEntity<String> entityHeader(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.setExpires(System.currentTimeMillis()+1000);
ResponseEntity<String> responseEntity =new ResponseEntity<>("哎呀成功了!",headers,HttpStatus.OK);
return responseEntity;
}
3.2 请求重定向
第一种:"redirect:"
第二种:RedirectView
@GetMapping(value="/tobaidu")
public String toBaidu(){
return "redirect:https://www.baidu.com";
}
@GetMapping(value="/tosina")
public RedirectView toSina(){
RedirectView rv = new RedirectView();
rv.setUrl("https://www.sina.com.cn/");
return rv;
}
3.3 请求转发
第一种:""
第二种:ModelAndView
@GetMapping(value="/toUser1")
public String toUser1(){
return "user";
}
@GetMapping(value="/toUser2")
public ModelAndView toUser2(){
ModelAndView mv = new ModelAndView();
mv.addObject("name", "姓名");
mv.addObject("age","28");
mv.setViewName("user");
return mv;
}
4 视图渲染
4.1 在application.properties添加配置
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
4.2 添加POM文件添加对应的依赖:
<!--用于编译jsp-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
4.3 新建JSP页面
添加如下内容:
歡迎你!${name},${age}
4.4 新建Controller
@GetMapping("user")
public String toUser(HttpServletRequest request){
request.setAttribute("name", "shuaige");
request.setAttribute("age", "18");
return "user";
}
模拟请求:
5 参考资料
https://github.com/spring-projects/spring-boot/tree/v1.3.2.RELEASE/spring-boot-samples/spring-boot-sample-web-jsp
https://github.com/liu-a-wei/spring-mvc-showcase/
补充一下:
@GetMapping===@RequestMapping(method=RequestMethod.GET)
@PostMapping===@RequestMapping(method=RequestMethod.POST)
@RestController===@Controller+@ResponseBody
网友评论