Spring MVC入门
做web开发,首先对web有一个大体的了解,下图第一部分是网页的组成成分,我们看到的各式各样的网页就是浏览器根据这些文件渲染出来的,第二部分http协议,是应用层的协议,用来传输上方的这些文件,再下面是传输层和网络层的相关内容,具体的自行学习。
HTTP协议
首先了解http协议,这里提供Mozilla的官方文档进行学习
- HyperText Transfer Protocol
- 用于传输HTML等内容的应用层协议
- 规定了浏览器和服务器之间如何通信,以及通信时的数据格式。
在这里截取一段了解一下
HTTP 流
当客户端想要和服务端进行信息交互时(服务端是指最终服务器,或者是一个中间代理),过程表现为下面几步:
打开一个TCP连接:TCP连接被用来发送一条或多条请求,以及接受响应消息。客户端可能打开一条新的连接,或重用一个已经存在的连接,或者也可能开几个新的TCP连接连向服务端。
发送一个HTTP报文:HTTP报文(在HTTP/2之前)是语义可读的。在HTTP/2中,这些简单的消息被封装在了帧中,这使得报文不能被直接读取,但是原理仍是相同的。
html
1
2
3 GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr读取服务端返回的报文信息:
html
1
2
3
4
5
6
7
8
9
10 HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html
... ( 29769 )关闭连接或者为后续请求重用连接。
当HTTP流水线启动时,后续请求都可以不用等待第一个请求的成功响应就被发送。然而HTTP流水线已被证明很难在现有的网络中实现,因为现有网络中有很多老旧的软件与现代版本的软件共存。因此,HTTP流水线已被在有多请求下表现得更稳健的HTTP/2的帧所取代。
我们在浏览器实际操作来查看一下,以上面推荐的网站为例,用谷歌浏览器打开,在页面上右键-检查,然后刷新一下,就可以看到右边出现了一堆请求,我们随便点一个就可以看到它的header,cookies之类的信息。那为什么有这么多请求呢,因为在浏览器解析的过程中,会发现html里面引用了其它资源,那么就会再请求这个资源文件。
Spring MVC
- 三层架构
- 表现层、业务层、数据访问层
- MVC
- Model:模型层
- View:视图层
- Controller:控制层
- 核心组件
- 前端控制器:DispatcherServlet
要注意,服务端三层架构和MVC三层不是一一对应关系。可以从上图看到大致的关系,Controller接收请求中的数据,调用业务层去处理,得到的数据封装到model传给视图层,视图层生成html返回给浏览器。在这个过程中,有一个核心组件,前端控制器DispatcherServlet。从spring最新版本的文档找了一个图来解释,大体结构如下。
上面这个图不够具体,在老版的文档找到这个图,可以结合来看,大体流程就是请求来了由前端控制器解析,handlerMapping根据我们的注解找到相应的controller去处理,返回model给前端控制器,前端控制器再调用试图解析器处理,然后然会响应。解释得不够准确,深入了解建议spring官网查看文档
Thymeleaf模板引擎
在前面我们写了简单的示例,都是返回了字符串给浏览器,没有返回过网页,我们需要借用一个工具-模板引擎,那么比较流行的就是thymeleaf。
- 模板引擎
- 生成动态的HTML
- Thymeleaf
- 倡导自然模板,即以HTML文件为模板
- 常用语法
- 标准表达式,判断与循环,模板的布局
案例演示
我们首先在application.properties里面关掉thymeleaf的缓存。
1 | #ThymeleafProperties |
那么上面这句话是什么意思呢,ctrl+n我们搜索一下thymeleaf的配置类也就是ThymeleafProperties。我截取了前面的一段代码,可以看到这个类使用了@ConfigurationProperties注解配置了前缀,我们使用这个前缀加上.cache实际是修改了ThymeleafProperties的cache属性,在我截取的代码最后一行可以看到。
1 | ( |
同理,我们修改服务器启动端口,也可以查看对应的配置类,还可以修改其它参数,这里不做演示,可以查阅spring文档。
1 | # ServerProperties |
案例一
这个案例我们演示如何获取请求和返回响应,具体每一行的意思我在注释里写好。在http方法里面,传入了servlet的request和response,我们对这两个对象进行操作。
1 | package com.neu.langsam.nowcoder.controller; |
启动项目,在浏览器中访问,可以看到页面显示了我们写入的html,同样可以打开检查,查看我们这一次的请求情况,查看idea控制台,可以看到输出了我们想要获取的数据,还可以在链接后接问号传参,传参的不做演示。
http://localhost:8080/alpha/http?code=test
案例二
案例一演示了比较基础的方法去操作,但实际上已经封装好了简单的方法,接下来演示如何更加简单的去处理。现在假设查询学生数据,学生比较多采用分页显示,那么就需要传入current参数告诉后端现在需要第几页以及limit参数规定每页多少条数据。那么怎么处理这样的请求呢。
GET 方法
- 首先还是使用注解进行配置
- @RequestMapping配置了访问路径和访问方法,这里我们规定了只接受GET方法,相应的还有POST,DELETE等方法自行了解。GET方法通常用来查询数据,POST通常添加或者修改数据。
- @ResponseBody注解表示将方法返回的java对象转换为json或者xml格式的数据,直接写入响应的body区而不走视图解析器。
- 在第一个getStudents方法中,我们使用了@RequestParam注解规定了请求参数,对于current参数,我们规定了不是必须的,默认值设置为1。我们就可以在地址栏传入参数,/students?current=2&limit=20
- 在第二个getStudent方法中,使用了@PathVariable注解,同时路径中使用了{id},这样就可以直接/student/112传入id参数
这两种方法根据不同的需求,使用相应的方法。
1 | //GET请求 |
POST方法
上面说到post方法通常用于增加或者修改数据,那么我们就需要有一个表单去填写数据。在static目录下新建html目录,在html目录下新建一个html文件。这是一个简单的网页,两个输入框加上一个提交按钮,规定了提交的路径是/alpha/student。
1 | > |
然后我们在controller里写处理这个访问路径的方法,这里需要注意一点,前面我们写了/student/{id}路径,比我们这里访问的/student多了一层,所以要另外写一个处理/student的方法。要获取浏览器提交的参数,我们只需要传入和浏览器表单里每一项一样名字的参数就行,spring会帮我们自动匹配。比如html里input年龄的参数名我们规定为age,那么处理请求时传入一个名为age的参数就可以接收到。
1 | //POST请求 |
案例三
演示了这么多,thymeleaf模板引擎怎么用呢。首先创建一个模板,在templates下创建demo目录,然后创建一个view.html,那可能会问和前面的静态html有啥区别呢。在html标签里使用xmlns规定了模板的来源,在p标签里使用thymeleaf的语法,意思是让页面的文字等于我们传入的那么和age的值。
1 | > |
再在controller里写相应方法处理。返回数据类型设为ModelAndView,也就是把模型和视图作为一个对象返回,为了简单直接给了一个固定数据,并设置了模板的路径,demo路径下的view.html,这里就不用写后缀了,在浏览器中访问相应地址就行。
1 | //响应HTML数据 |
同样,我们在检查里查看这次请求,可以看到响应的内容是一个html文件。
还有另外一种方式,效果一样。这个方法是从容器中获取模型的引用,修改模型的值,并直接返回视图的路径。对比来看第二种方式简洁一点。
1 | "/school",method = RequestMethod.GET) (path = |
案例四
还有一种比较常见的情况,我们需要给浏览器返回JSON数据,通常是在一个异步请求中,实际上在前面我们已经使用过了。异步请求是什么呢,比如注册bilibili,当我输入一个昵称时,网页会提醒我昵称被占用,但是网页其它部分时没有刷新变动。
1 | //响应JSON数据(异步请求) |
返回JSON实际就是使用了前面提到的@ResponseBody注解。
同样,也可以返回一组数据。
1 | "/emps",method = RequestMethod.GET) (path = |