4. 响应
在我们前⾯的代码例⼦中,都已经设置了响应数据, Http响应结果可以是数据, 也可以是静态⻚⾯,也可以针对响应设置状态码, Header信息等.
返回静态页面
用到@Controller
创建前端⻚⾯ index.html(注意路径)
找到启动类,启动
带
@SpringBootApplication
就是启动类
后端代码
@RequestMapping("/return")
@RestController
public class ReturnController {
@RequestMapping("/index")
public String returnIndex(){
return "/index.html";
}
}
如果只是这样写
结果却发现, ⻚⾯未正确返回, http响应把 "/index.html"
当做了http响应正⽂的数据
那Spring MVC如何才能识别出来 index.html 是⼀个静态⻚⾯, 并进⾏返回呢?
我们需要把 @RestController
改为 @Controller
@RequestMapping("/return")
//@RestController
@Controller
public class ReturnController {
@RequestMapping("/index")
public String returnIndex(){
return "/index.html";
}
}
改成这样,把@RestController
改成@Controller
后
此时返回的就是页面了
@RestController
和 @Controller
有着什么样的关联和区别呢?
前⾯讲了MVC模式, 后端会返回视图, 这是早期时的概念
随着互联⽹的发展, ⽬前项⽬开发流⾏"前后端分离"模式, Java主要是⽤来做后端项⽬的开发, 所以也就不再处理前端相关的内容了
MVC的概念也逐渐发⽣了变化, View不再返回视图, ⽽是返回显⽰视图时需要的数据
所以前⾯使⽤的 @RestController
其实是返回的数据.
@RestController = @Controller + @ResponseBody
@Controller
: 定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理.
@ResponseBody
: 定义返回的数据格式为⾮视图, 返回⼀个 text/html 信息
@RestController
源码:@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { @AliasFor( annotation = Controller.class ) String value() default ""; }
如果想返回视图的话, 只需要把
@ResponseBody
去掉就可以了, 也就是@Controller
上面三个注解:
@Target({ElementType.TYPE})
,表示注解修饰的是什么,这里的TYPE
表示就是可以修饰类、接口@Retention(RetentionPolicy.RUNTIME)
,表示注解的生命周期,这里的RUNTIME
表示运行阶段,还有SOURCE
、CLASS
,前者表示源代码活在代码阶段,编译之后就消失了、后者表示编译阶段@Documented
,表示文档要不要保留,比如注释这些这三个称为元注解:可以被其他注解使用的注解称为元注解
返回数据
@ResponseBody
表⽰返回数据
@ResponseBody
@RequestMapping("/returnData")
public String returnData(){
return "返回视图需要的数据";
}
加上 @ResponseBody
注解, 该⽅法就会把 “返回视图需要的数据” 当做⼀个数据返回给前端
如果去掉 @ResponseBody
注解, 程序会报404错误.
程序会认为需要返回的是视图, 根据内容去查找⽂件, 但是查询不到, 路径不存在, 报404
运行http://127.0.0.1:8080/return/returnData
@ResponseBody
既是类注解, ⼜是⽅法注解
如果作⽤在类上, 表⽰该类的所有⽅法, 返回的都是数据, 如果作⽤在⽅法上, 表⽰该⽅法返回的是数据.
也就是说: 在类上添加 @ResponseBody
就相当于在所有的⽅法上添加了 @ResponseBody
注解
同样, 如果类上有
@RestController
注解时:表⽰所有的⽅法上添加了@ResponseBody
注解, 也就是当前类下所有的⽅法返回值做为响应数据
如果⼀个类的⽅法⾥, 既有返回数据的, ⼜有返回⻚⾯的, 就把 @ResponseBody
注解添加到对应的⽅法上即可.
多个注解时, 没有先后顺序, 先写哪个都可以
返回HTML代码片段
后端返回数据时, 如果数据中有HTML代码, 也会被浏览器解析
@ResponseBody
@RequestMapping("/returnHtml")
public String returnHtml(){
return "<h1>返回HTML片段<h1>";
}
运行http://127.0.0.1:8080/return/returnHtml
响应中的 Content-Type 常⻅取值有以下⼏种:
text/html
: body 数据格式是 HTMLtext/css
: body 数据格式是 CSSapplication/javascript
: body 数据格式是 JavaScriptapplication/json
: body 数据格式是 JSON
如果请求的是js⽂件, Spring MVC会⾃动设置Content-Type为
application/javascript
如果请求的是css⽂件, Spring MVC会⾃动设置Content-Type为
text/css
返回JSON
Spring MVC 也可以返回JSON
后端⽅法返回结果为对象
@ResponseBody
@RequestMapping("/returnJson")
public Person returnJson(){
Person person=new Person();
person.setId(1);
person.setName("zhangsan");
person.setAge(7);
return person;
}
运行http://127.0.0.1:8080/return/returnJson
通过fiddler观察
当我们的接口返回的是String时,content-Type是text/html
当我们的接口返回的是对象时,content-Type自动设置为application/json
当我们的接口返回的是Map时,content-Type也自动设置为application/json
设置状态码
Spring MVC会根据我们⽅法的返回结果⾃动设置响应状态码, 程序员也可以⼿动指定状态码
通过Spring MVC的内置对象 HttpServletResponse
提供的⽅法来进⾏设置
@ResponseBody
@RequestMapping("/setStatus")
public String setStatus(HttpServletResponse response){
response.setStatus(401);//通常表示没有登录
return "设置状态码";
}
运行http://127.0.0.1:8080/return/setStatus
状态码不影响页面的展示
上面的是Http状态码
设置Header
这部分了解即可,这部分是响应的Header
Http响应报头也会向客⼾端传递⼀些附加信息, ⽐如服务程序的名称,请求的资源已移动到新地址等, 如:Content-Type, Local等
这些信息通过 @RequestMapping
注解的属性来实现:
先来看 @RequestMapping
的源码:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
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 {};
}
-
value: 指定映射的URL
-
method: 指定请求的method类型, 如GET, POST等
-
consumes: 限制处理请求(request)的提交内容类型(Content-Type),例如application/json,text/html;
-
produces: 设置返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
-
Params: 指定request中必须包含某些参数值时,才让该⽅法处理
-
headers: 指定request中必须包含某些指定的header值,才能让该⽅法处理请求
了解即可, 更多说明参考
https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-requestmapping.html#mvc-ann-requestmapping-consumes
设置Content-Type
我们通过设置 produces 属性的值, 设置响应的报头Content-Type
@ResponseBody
@RequestMapping(value = "/r1")
public String r1(HttpServletResponse response){
return "{'OK':1}";
}
如果是这么写的话,通过fiddler观察仍是text/html
@ResponseBody
@RequestMapping(value = "/r1",produces = "application/json;charset=utf8")
public String r1(HttpServletResponse response){
return "{'OK':1}";
}
如果是这么写的话就可以修改了,但要注意也是要匹配了才能修改,不能乱改
设置其他Header
设置其他Header的话, 需要使⽤Spring MVC的内置对象HttpServletResponse
提供的⽅法来进⾏设置
@ResponseBody
@RequestMapping(value = "/r2",produces = "application/json;charset=utf8")
public String r2(HttpServletResponse response){
response.setHeader("myheader","123456");
return "{'OK':1}";
}