本篇文章介绍响应相关的知识, 通过 spring 来设置响应中的值, 向客户端返回设置好的响应.
1. 返回静态页面
我们首先使用 html 写一个前端页面, 再通过 spring 方法, 将这个 html 页面作为响应的内容, 展示给用户.
显然, 方法返回的只是一个字符串, 并非 html 展示的页面.
如何将 html 页面返回给客户端呢?? 这需要修改 类注解.
若方法返回的是一个页面, 则需要将原来的类注解 @restcontroller 修改为 @controller.
接下来, 对涉及到的几个注解逐个进行解释.
1.1 spring 默认扫描路径
我们知道, 每一个路径, 都对应了一个方法. 当服务器收到客户端的请求时, spring 就会根据请求中的资源路径, 寻找该路径对应的方法, 进而计算响应结果, 最后返回响应.
而 spring 中有大量的方法存在, 包括使用 maven 引入的第三方库, 都存在于 spring 中. 若 spring 要扫描所有的方法, 一个一个的去进行比对, 确定哪个是资源路径所对应的方法的话, 那工作量是巨大的.
因此, spring 有一个默认扫描路径: 只扫描启动类所在的目录, 及其子目录.
若请求中资源路径对应的方法, 属于启动类所在目录或子目录时, 会被 spring 扫描到:
而当请求中资源路径所对应的方法, 不属于启动类所在目录或子目录时, 则 spring 不会扫描, 客户端就会显示错误:
因此, spring 也当然不会扫描 maven 中第三方库中的方法.
有了默认的扫描路径, 大大降低了 spring 的工作量, 提升了开发效率.
1.2 @restcontroller
虽然 spring 有默认的扫描路径, 但是当项目很大时, 这个路径下也是会有很多的方法存在的.
于是, 可以使用 @restcontroller 对类进行标记, spring 只需扫描被 @restcontroller 标记的类.
因此, spring 的扫描对象为: 默认扫描路径中的类 && 使用 @restcontroller 进行标记的类
当默认路径下的类没有使用 @restcontroller 进行标记时, 那么 spring 也不会进行扫描, 进一步减少了 spring 的工作量.
@restcontroller 的特性如下:
- 类注解. 只能对类进行使用
- 存活于运行阶段. (整个项目运行时, 都存在)
- 包含 @controller 和 @responsebody
其中, @controller 表示返回的是页面. @responsebody 表示返回的是数据.
@restcontroller 也表示返回的是数据.
由于 @restcontroller = @controller + @responsebody, 因此, 左右两侧的注解效果相同:
1.2.1 @controller => 返回页面
@controller 是一个类注解(只能给类使用), 并且使用此注解标记类时, 表示该类中的所有方法(@responsebody 标记的方法除外, 见下文), 返回的均是页面.
因此, 我们将类的注释修改为 @controller, 就可以返回静态页面了:
spring 会以 resources.static 为该 html 文件的基准路径, 扫描指定路径下的 html 文件, 并返回该 html 构造的页面. 并且, html 文件的路径前要加上 /
不过, 现在后端已经基本不会返回页面了.
@requestmapping("/resp") @controller // 表示类中的方法只能返回页面 public class respcontroller { @responsebody // 该方法可以返回数据 @requestmapping("/r1") public string returnpage() { // 返回页面时, 一定要加上 / return "/index.html"; } }
1.2.2 @responsebody
@responsebody 既是一个类注解, 也是一个方法注解, 表示返回的是数据.
当类注解为 @controller 时, 类中的方法只能返回页面, 若此时我们想返回数据, 可以对方法使用 @responsebody 进行标记, 被标记的方法可以返回数据.
综上, @restcontroller, @controller, @responsebody 的使用场景如下:
- 一个类中, 既有返回页面的方法, 也有返回数据的方法 ==> 使用 @controller 对类标记, 对返回数据的方法使用 @responsebody 标记.
- 如果一个类中所有的方法, 返回的都是数据 ==> 使用 @restcontroller 或者 @controller + @responsebody 对类标记
- 如果一个类中所有的方法, 返回的都是页面 ==> 使用 @controller 对类标记
- 类必须有 @controller 注解才能被 spring 扫描到(@restcontroller 包含了 @controller)
2. 返回 html
默认情况下, 响应中的 content-type 都是 test/html, 因此, 浏览器收到数据后, 都会按照 html 的格式来解析, 最终展示在页面上.
因此, 如果我们想要给客户端返回一个 html 片段, 那我们无需任何操作, 直接返回 html 代码即可.
// 返回 html 片段 @responsebody @requestmapping("/r3") public string returnhtml() { return "<h1>这是一个一级标题</h1>"; }
2.1 @requestmapping
@requestmapping 是一个类注解, 也是一个方法注解, 既可以对类设置路径, 也可以对方法设置路径.
此外, @requestmapping 还有一些属性.
2.1.1 produces(修改响应的 content-type)
但是, 如果我们想要把这个 html 代码, 当做一个普通的字符串去返回, 该怎么办呢?
显然, 我们将响应的 content-type 类型修改为纯文本格式即可, 即: test/plain
我们可以通过修改 @requestmapping 中的 produces 属性, 来修改 content-type:
这样, 浏览器接收响应后, 就会将 body 中的内容, 以纯文本的格式来解析, 而不是当做 html .
// 返回纯文本 @responsebody @requestmapping(value = "/r4", produces = "text/plain") // 修改 content-type 为纯文本格式 public string returntext() { // 当成普通字符串返回 return "<h1>这是一个一级标题</h1>"; }
2.1.2 其他属性
@requestmapping 中不仅有 produces 这一属性, 还有其他属性. 通过设置这些属性值, 可以对请求或者响应中的内容做出要求:
method
: 要求请求的方法必须是什么(如:get, post, ....), 否则不处理params
: 要求请求中必须包含哪些参数, 否则不处理headers
: 要求请求的 header 中必须包含哪些 header 信息, 否则不处理consumes
: 要求请求的 content-type 必须是什么, 否则不处理produces
: 设置响应的 content-type
3. 返回 json
spring 会根据返回数据的类型, 自动对 content-type 进行类型的转换.
上文提到, 当返回的数据是字符串时, 默认的 content-type 是 text/html; 若想改成其他类型, 还需要手动进行转换.
但是当我们返回的数据是一个对象时, spring 会自动将这个对象序列化为 json 格式, 并自动将 content-type 转换为 application/json:
// 返回 json @responsebody @requestmapping("/r5") public userinfo returnjson() { // 若返回的数据是一个对象 // spring 会自动将响应中的 content-type 转换为 json 格式 return new userinfo("dings", "aaa", 1); }
4. 设置状态码
4.1 httpservletresponse
在后端的 spring 项目中, 我们既可以通过 httpservletrequest 来获取请求中的信息, 同样也可以通过 httpservletresponse 来设置响应中的信息.
因此, 我们可以拿到 httpservletresponse 对象, 进而通过 setstatus 方法修改响应中的状态码:
// 设置状态码 @responsebody @requestmapping("/r6") public string setstatus(httpservletresponse response) { // 手动将响应中的状态码设置为 404 response.setstatus(404); return "设置状态码成功!!"; }
注意: 状态码不影响页面的展示!!
不管状态码是什么, 都可以返回我们自定义的内容. 至于为什么有些网站的 404 页面是一些提示内容, 因为那个界面也是维护那个网站的程序员自己代码写的.
程序员当然也可以将 404 页面打扮的很漂亮!! 比如 bilibili:
5. 设置 header
后端可以设置响应中的 header, 通过 header 来向客户端传递一些信息.
仍然是通过 httpservletresponse 设置响应中的 header:
(header 是以键值对的形式存储数据的)
// 设置 header @responsebody @requestmapping("/r7") public string setheader(httpservletresponse response) { response.setheader("myheader", "hahaha"); return "设置 header 成功!!"; }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论