赞
踩
目录
@RestController 和 @Controller之间的关联和区别
创建前端页面,要创建路径的路径如下:
前端代码:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Index页面</title>
- </head>
- <body>
- Hello,Spring MVC,我是Index⻚⾯
- </body>
- </html>
后端代码:
- @RestController
- @RequestMapping("/res")
- public class ResponseController {
- @RequestMapping("/index")
- public String index() {
- return "/index.html";
- }
浏览器访问:http:127.0.0.1:8080/res/index ,页面如下:
结果发现,页面不是我们想要的,而是直接返回了一个字符串,那么就说明,Spring MVC没有识别我们返回的是一个前端页面,那么怎么让它识别出来是 /index.html 文件,而不是字符串呢?那就需要把注解@RestController改为@Controller,正确代码如下:
- @Controller
- @RequestMapping("/res")
- public class ResponseController {
- @RequestMapping("/index")
- public String index() {
- return "/index.html";
- }
- }
浏览器再访问一次:http:127.0.0.1:8080/res/index ,页面如下:
就是我们想要的页面了。
前面讲的MVC模式,后端会返回视图,这是早期的概念,但随着互联网的发展,项目流行 “前后端分离” 模式,Java主要用来做后端项目,所以也就不再处理前端相关的内容了。
如上图,MVC也随之发生改变,View不再返回视图,而是返回显示视图所需要的数据,所以前面使用的@RestController返回的就是数据。
@RestController = @Controller + @ResponseBody
@Controller:定义了一个控制器,Spring框架启动时加载,把这个对象交给Spring管理。
@ResponseBody:定义返回数据格式为非视图,返回一个text / html信息。
源码:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { @AliasFor( annotation = Controller.class ) String value() default ""; }
也就是说 @RestController 或 (@Controller + @ResponseBody)注解返回的是前端所需要的数据,@Controller 返回的是视图。
上面说到,@ResponseBody 表示返回数据,代码如下:
- @Controller
- @RequestMapping("/res")
- public class ResponseController {
- @ResponseBody
- @RequestMapping("/index")
- public String index() {
- return "/index.html";
- }
- }
因为加上了@ResponseBody注解,所以index方法就会把 “/index.html” 当做一个数据返回给前端,浏览器页面如下:
@ResponseBody作用在类上,表示该类上的所有方法,返回的都是数据。
@ResponseBody作用在方法上,表面该方法返回的是数据。
1、也就是说明在类上添加注解@ResponseBody,相当于该类上所有的方法都添加了注解@ResponseBody。
2、因为@RestController = @Controller + @ResponseBody,所以如果类上添加了注解@RestController,相当于该类的所有方法都添加了注解@RestController。
3、如果一个类里面,既要返回数据,又要返回视图,那么就使用注解@Controller添加在该类上,然后需要返回数据的方法添加注解@ResponseBody,返回视图的方法就不同管它。
一个方法是返回视图,一个方法是返回数据,代码如下:
- @Controller
- @RequestMapping("/res")
- public class ResponseController {
- @RequestMapping("/index")
- public String index() {
- return "/index.html";
- }
-
- @ResponseBody
- @RequestMapping("returnData")
- public String returnData() {
- return "该方法返回数据";
- }
- }
多个注解修饰 类 / 方法,没有先后顺序,谁先谁后都行,
浏览器分别访问http:127.0.0.1:8080/res/index 和http:127.0.0.1:8080/res/returnData,页面分别如下:
如果returnData方法删去注解@ResponseBody,代码如下:
- @Controller
- @RequestMapping("/res")
- public class ResponseController {
- @RequestMapping("/index")
- public String index() {
- return "/index.html";
- }
-
- @RequestMapping("returnData")
- public String returnData() {
- return "该方法返回数据";
- }
- }
在访问一下:http:127.0.0.1:8080/res/returnData ,页面如下:
404错误码,因为该类是注解@Controller修饰的,访问该类的方法默认返回的是视图,程序就会认为需要返回视图(returnData方法没加@ResponseBody注解),然后根据内容进行查找文件,但查询不到,也就是路径不存在,所以报错404。
后端返回数据时,如果数据有HTML代码,也会被浏览器解析,代码如下:
- @ResponseBody
- @RequestMapping("/returnHtml")
- public String returnHtml() {
- return "<h1> Hello, HTML</h1>";
- }
浏览器访问:http:127.0.0.1:8080/res/returnHtml ,页面如下:
通过fiddler观察Content-Type,如图:
1、text / html:body数据格式是 HTML。
2、text / css:body数据格式是 CSS。
3、application / Javascript:body数据格式是 JavaScript。
4、application / json:body数据格式是 JSON。
如果请求的是js文件,Spring MVC会自动设置Content-Type为 application / Javascript。
如果请求是css文件,Spring MVC会自动设置Content-Type为 text / css。
Spring MVC也可以返回JSON,后端方法返回结果为对象(下面使用Hash对象),代码如下:
- @ResponseBody
- @RequestMapping("/returnJson")
- public HashMap<String, String> returnJson() {
- HashMap<String, String> map = new HashMap<>();
- map.put("key1", "value1");
- map.put("key2", "value2");
- map.put("key3", "value3");
- return map;
- }
浏览器访问:http:127.0.0.1:8080/res/returnJson ,页面如下:
使用fiddler抓包观察:
Spring MVC会根据我们方法的返回结果自动设置响应状态码,程序员也可以手动指定状态码,通过Spring MVC的内置对象HttpServletResponse提供的方法来进行设置。
代码如下:
- @ResponseBody
- @RequestMapping("/setStatus")
- public String setStatus(HttpServletResponse response) {
- response.setStatus(418);
- return "设置状态码成功";
- }
浏览器访问:http:127.0.0.1:8080/res/setStatus ,页面如下:
可以看到,状态码并不影响页面的展示。
通过fiddler抓包看看,如图:
Http响应报头也会向客户端传递一些附加信息,比如服务程序的名称,请求的资源已移动到新地址等,如:Content-Type、Local等。
这些信息通过@RequestMapping注解的属性来实现,如下是@RequestMapping的源码:
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Mapping
- @Reflective({ControllerMappingReflectiveProcessor.class})
- public @interface RequestMapping {
- String name() default "";
-
- @AliasFor("path")
- String[] value() default {};
-
- @AliasFor("value")
- String[] path() default {};
-
- RequestMethod[] method() default {};
-
- String[] params() default {};
-
- String[] headers() default {};
-
- String[] consumes() default {};
-
- String[] produces() default {};
- }
(1)value:指定映射的URL。
(2)method:指定请求的method类型,如GET,POST等。
(3)consumes:指定处理请求(request)的提交内容类型(Content-Type),例如application/json,text/html等。
(4)produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。
(5)Params:指定request中必须包含某些参数时,才让该方法处理。
(6)headers:指定request中必须包含某些指定的header值,才让该方法处理请求。
了解即可,更多说明参考:Mapping Requests :: Spring Framework
通过设置produces属性的值,可以设置响应的报头Content-Type,代码如下:
- @ResponseBody
- @RequestMapping(value = "/setContentType", produces = "application/json")
- public String returnJson2() {
- return "{\"ok\":1}";
- }
浏览器访问:http:127.0.0.1:8080/res/setContentType ,页面如下:
通过Postman测试,页面如下:
可以看到Postman识别出来了响应的报头Content-Type是JSON。
通过fiddler抓包观察:
也是JSON格式,如果不进行设置produces,方法返回结果为String时,Spring MVC默认返回的text/html。
设置返回类型时,也可以同步设置响应编码,代码如下:
- @ResponseBody
- @RequestMapping(value = "/setContentType", produces = "application/json;charset=utf-8")
- public String returnJson2() {
- return "{\"ok\":1}";
- }
fiddler抓包结果:
设置其他Header的话,需要使用 Spring MVC的内置对象HttpServletResponse提供的方法来进行设置。代码如下:
- @ResponseBody
- @RequestMapping("/setHeader")
- public String setHeader(HttpServletResponse response) {
- response.setHeader("MyHeader", "MyHeaderValue");
- return "设置成功";
- }
void setHeader(String name, String value) 设置一个带有给定的名称和值的header。如果name已经存在,则覆盖旧的值。
浏览器访问:http:127.0.0.1:8080/res/setHeader ,页面如下:
通过Postman抓包,如图:
确实设置成功了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。