响应
在我们前面的代码例子中, 都已经设置了响应数据Http响应结果可以是数据, 也可以是静态页面, 也可以针对响应设置状态码, Header信息等.
返回静态页面
创建前端页面index.html(注意路径)
html代码如下:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>Hello, Spring MVC,我是index页面.
</body>
</html>
后台代码如下:
@RestController
public class IndexController {@RequestMapping("/index")public Object index() {//返回index.htmlreturn "/index.html";}
}
运行结果:
结果却发现, 页面未正确返回, http响应把"/index.html"当作http响应正文的数据. 那么Spring MVC如何才能识别出来index.html是一个静态页面, 并进行返回呢?
我们需要把@RestController 改为 @Controller.
正确代码如下:
@Controller
public class IndexController {@RequestMapping("/index")public Object index() {//返回index.htmlreturn "/index.html";}
}
再次运行得到结果:
发现页面正确展示了.
@RestController和@Controller的关系
我们之前讲过了MVC模式, 后端会返回视图, 这是早期时的概念
随着互联网的发展, 目前项目流行"前后端分离模式" , Java主要是用来做后端项目的开发, 所以就不再处理前端相关内容了.
MVC的概念也逐渐发生了变化, View不再返回视图, 而是返回显示视图时所需要的数据.
所以前面的@RestController其实是返回的数据, 是作为一个复合注解.
@RestController = @Controller(默认返回视图) + @ResponseBody(返回数据).
@Controller:定义一个控制器, Spring框架启动时加载, 把这个对象交给Spring管理.
@ResponseBody: 定义返回的数据为非视图, 返回一个text/html信息. 它既可以修饰类, 又可以修饰方法. (修饰类时:表示当前类的所有方法, 全部返回数据, 和@Controller可以合并为@RestController; 修饰方法时, 表示当前方法返回数据).
如果想返回视图的话, 只需要把@ResponseBody去掉就可以了, 也就是@Controller.
返回数据@ResponseBody
上面我们讲到, @ResponseBody表示返回数据.
@Controller
@ResponseBody
public class IndexController {@RequestMapping("/index")public Object index() {//返回index.htmlreturn "/index.html";}
}
加上@ResponseBody注解, 该方法就会把"/index.html"当作一个数据返回给前端.
@ResponseBody既是类注解, 又是方法注解
如果作用在类上, 表示该类的所有方法, 返回的就是数据, 如果作用在方法上, 表示该方法返回的就是数据.
当你在一个类中既想让一些方法返回视图, 又想让一些方法返回数据, 那么就可以给类加@Controller注解, 给想返回数据的方法加上@ResponseBody注解, 返回视图的方法不处理即可.
同样, 如果类上有@RestController注解时:表示所有方法上添加了@ResponseBody注解, 也就是当前类下所有方法返回值作为响应数据.
@Controller
public class IndexController {@RequestMapping("/index")public Object index() {//返回index.htmlreturn "/index.html";}@RequestMapping("/returnData")@ResponseBodypublic String returnData() {return "该方法返回数据";}
}
多个注解时, 没有先后顺序, 先写哪个都可以.
如果给第二个方法去掉@Responsebody, 程序就会报404错误.
因为程序会认为返回的应该是视图, 就会根据内容去查找文件, 但是文件查找不到, 路径不存在, 就报404.
返回HTML代码片段
后端返回数据的时候, 如果数据中有HTML代码, 也会被浏览器解析.
@RequestMapping("/returnHtml")@ResponseBodypublic String returnHtml() {return "<h1>hello HTML~</h1>";}
运行结果:
通过Fiddler观察结果, Content-Type为 text/html.
响应中的Content-Type常见取值有以下几种:
text/html:body数据格式是HTML
text/css:body数据格式是CSS
application/javascript:body数据格式是JavaScript
application/json:body数据格式是JSON.
返回JSON
Spring MVC也可以返回JSON
后端方法返回结果为对象.
@RequestMapping("/returnJson")@ResponseBodypublic HashMap<String, String> returnJson() {HashMap<String, String> map = new HashMap<>();map.put("Java", "Java value");map.put("MySQL", "MySQL value");map.put("Redis", "Redis value");return map;}
运行结果:
通过Fiddler观察响应结果, Content-Type为application/json.
设置状态码
Spring MVC会根据我们方法的返回结果自动设置响应状态码, 程序员也可以手动指定状态码.
通过Spring MVC的内置对象HttpServletResponse提供的方法来进行设置.
@RequestMapping("/setStatus")@ResponseBodypublic String setStatus(HttpServletResponse response) {response.setStatus(418);return "设置状态码成功";}
运行结果:
通过Fiddler观察设置的结果:
设置Header
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值, 才能让该方法处理请求.
设置Content-Type
我们通过设置produces属性的值, 设置响应的报头Content-Type.
@RequestMapping(value = "/returnJson2", produces = "application/json")@ResponseBodypublic String returnJson2() {return "{\"sucess\":true}";}
运行结果:
Fidder抓包结果:
如果不设置produces, 方法返回的结果为String时, Spring MVC默认返回类型, 是text/html.
设置其他Header
设置其它Header的话, 需使用Spring MVC内置对象HttpServletResponse提供的方法来进行设置.
@RequestMapping("/setHeader")@ResponseBodypublic String setHeader(HttpServletResponse response) {response.setHeader("MyHeader", "MyHeaderValue");return "设置Header成功";}
void setHeader(String name, String value)设置一个带有给定的名称和值的Header. 如果name已经存在, 则覆盖旧的值.
运行成功后查看Fidder抓包结果: