├── .springBeans
├── pom.xml
├── src
├── main
│ ├── java
│ │ └── com
│ │ │ └── woniuxy
│ │ │ ├── a_hello
│ │ │ ├── 1.感性的springmvc运行原理图.png
│ │ │ ├── 2.springmvc架构图.png
│ │ │ ├── UserController.java
│ │ │ ├── readme.txt
│ │ │ └── spring-servlet.xml
│ │ │ ├── b_replace
│ │ │ ├── MyView.java
│ │ │ ├── UserController.java
│ │ │ ├── UserController2.java
│ │ │ ├── readme.txt
│ │ │ └── spring-servlet.xml
│ │ │ ├── c_default
│ │ │ ├── UserController.java
│ │ │ └── spring-servlet.xml
│ │ │ ├── d_annotation
│ │ │ ├── 1.根据注解生成的内存模型.png
│ │ │ ├── 2.客户端请求注解控制器的原理.png
│ │ │ ├── CarController.java
│ │ │ ├── UserController.java
│ │ │ └── spring-servlet.xml
│ │ │ ├── e_simple
│ │ │ ├── CarController.java
│ │ │ ├── UserController.java
│ │ │ └── spring-servlet.xml
│ │ │ ├── f_parameter
│ │ │ ├── MyDateConverter.java
│ │ │ ├── User.java
│ │ │ ├── UserController.java
│ │ │ ├── readme.txt
│ │ │ └── spring-servlet.xml
│ │ │ ├── g_httpmessageconverter
│ │ │ ├── Test.java
│ │ │ ├── a
│ │ │ │ └── AppTest.java
│ │ │ ├── b
│ │ │ │ ├── MyHttpMessageConverter.java
│ │ │ │ ├── User.java
│ │ │ │ └── UserController.java
│ │ │ ├── readme.txt
│ │ │ └── spring-servlet.xml
│ │ │ ├── h_controller
│ │ │ ├── User.java
│ │ │ ├── UserController.java
│ │ │ └── spring-servlet.xml
│ │ │ ├── i_upload
│ │ │ ├── UploadController.java
│ │ │ ├── readme.txt
│ │ │ └── spring-servlet.xml
│ │ │ ├── j_interceptor
│ │ │ ├── A.java
│ │ │ ├── B.java
│ │ │ ├── UserController.java
│ │ │ ├── spring-servlet.xml
│ │ │ ├── 拦截器图解1.png
│ │ │ ├── 拦截器图解2.jpg
│ │ │ └── 拦截器图解3.jpg
│ │ │ ├── k_exception
│ │ │ ├── MyExceptionHandler.java
│ │ │ ├── UserController.java
│ │ │ ├── spring-servlet.xml
│ │ │ └── 异常处理器工作流程.png
│ │ │ ├── l_validation
│ │ │ ├── A.java
│ │ │ ├── B.java
│ │ │ ├── Prime.java
│ │ │ ├── PrimeValidator.java
│ │ │ ├── User.java
│ │ │ ├── UserController.java
│ │ │ ├── readme.txt
│ │ │ └── spring-servlet.xml
│ │ │ └── m_restful
│ │ │ ├── User.java
│ │ │ ├── UserController.java
│ │ │ ├── readme.txt
│ │ │ └── spring-servlet.xml
│ ├── resources
│ │ ├── gao.properties
│ │ ├── gao_en_US.properties
│ │ ├── gao_ja.properties
│ │ ├── gao_ja_JP.properties
│ │ ├── gao_zh_CN.properties
│ │ └── log4j2.properties
│ └── webapp
│ │ ├── WEB-INF
│ │ └── web.xml
│ │ ├── a.jsp
│ │ ├── e.jsp
│ │ ├── f.jsp
│ │ ├── g.jsp
│ │ ├── h.jsp
│ │ ├── html
│ │ └── m2.html
│ │ ├── i.jsp
│ │ ├── images
│ │ ├── 1.gif
│ │ ├── 1.jpg
│ │ └── 2.jpg
│ │ ├── index.jsp
│ │ ├── j.jsp
│ │ ├── k_error.jsp
│ │ ├── l.jsp
│ │ ├── l2.jsp
│ │ ├── l_success.jsp
│ │ └── m.jsp
└── test
│ └── java
│ └── com
│ └── woniuxy
│ └── test
│ └── AppTest.java
└── target
├── classes
├── com
│ └── woniuxy
│ │ ├── a_hello
│ │ ├── 1.感性的springmvc运行原理图.png
│ │ ├── 2.springmvc架构图.png
│ │ ├── readme.txt
│ │ └── spring-servlet.xml
│ │ ├── b_replace
│ │ ├── readme.txt
│ │ └── spring-servlet.xml
│ │ ├── c_default
│ │ └── spring-servlet.xml
│ │ ├── d_annotation
│ │ ├── 1.根据注解生成的内存模型.png
│ │ ├── 2.客户端请求注解控制器的原理.png
│ │ └── spring-servlet.xml
│ │ ├── e_simple
│ │ └── spring-servlet.xml
│ │ ├── f_parameter
│ │ ├── readme.txt
│ │ └── spring-servlet.xml
│ │ ├── g_httpmessageconverter
│ │ ├── readme.txt
│ │ └── spring-servlet.xml
│ │ ├── h_controller
│ │ └── spring-servlet.xml
│ │ ├── i_upload
│ │ ├── readme.txt
│ │ └── spring-servlet.xml
│ │ ├── j_interceptor
│ │ ├── spring-servlet.xml
│ │ ├── 拦截器图解1.png
│ │ ├── 拦截器图解2.jpg
│ │ └── 拦截器图解3.jpg
│ │ ├── k_exception
│ │ └── spring-servlet.xml
│ │ ├── l_validation
│ │ ├── readme.txt
│ │ └── spring-servlet.xml
│ │ └── m_restful
│ │ ├── readme.txt
│ │ └── spring-servlet.xml
├── gao.properties
├── gao_en_US.properties
├── gao_ja.properties
├── gao_ja_JP.properties
├── gao_zh_CN.properties
└── log4j2.properties
└── m2e-wtp
└── web-resources
└── META-INF
└── maven
└── com.woniuxy
└── springmvc
├── pom.properties
└── pom.xml
/.springBeans:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1
4 |
5 |
6 |
7 |
8 |
9 |
10 | src/main/java/com/woniuxy/a_hello/spring-servlet.xml
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.woniuxy
4 | springmvc
5 | 0.0.1-SNAPSHOT
6 | war
7 |
8 |
9 |
10 |
11 | org.springframework
12 | spring-webmvc
13 | 4.3.23.RELEASE
14 |
15 |
16 | junit
17 | junit
18 | 4.12
19 |
20 |
21 | javax.servlet
22 | javax.servlet-api
23 | 3.1.0
24 |
25 |
26 | javax.servlet
27 | jstl
28 | 1.2
29 |
30 |
31 | log4j
32 | log4j
33 | 1.2.12
34 |
35 |
36 | com.fasterxml.jackson.core
37 | jackson-databind
38 | 2.9.9
39 |
40 |
41 |
42 | commons-fileupload
43 | commons-fileupload
44 | 1.4
45 |
46 |
47 | org.hibernate.validator
48 | hibernate-validator
49 | 6.0.7.Final
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/a_hello/1.感性的springmvc运行原理图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/a_hello/1.感性的springmvc运行原理图.png
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/a_hello/2.springmvc架构图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/a_hello/2.springmvc架构图.png
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/a_hello/UserController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/a_hello/UserController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/a_hello/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/a_hello/readme.txt
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/a_hello/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/b_replace/MyView.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.b_replace;
2 |
3 | import java.util.Map;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 |
8 | import org.springframework.web.servlet.View;
9 |
10 | public class MyView implements View {
11 |
12 | @Override
13 | public String getContentType() {
14 | return null;
15 | }
16 |
17 | @Override
18 | public void render(Map model, HttpServletRequest request, HttpServletResponse response)
19 | throws Exception {
20 | request.getRequestDispatcher("/b.jsp").forward(request, response);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/b_replace/UserController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/b_replace/UserController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/b_replace/UserController2.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.b_replace;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.ServletException;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 |
9 | import org.springframework.web.HttpRequestHandler;
10 |
11 | public class UserController2 implements HttpRequestHandler {
12 |
13 | @Override
14 | public void handleRequest(HttpServletRequest request, HttpServletResponse response)
15 | throws ServletException, IOException {
16 | System.out.println("qwerty!!!");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/b_replace/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/b_replace/readme.txt
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/b_replace/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
22 |
23 |
24 |
25 | kk
26 | qq
27 |
28 |
29 |
30 |
31 |
39 |
40 |
41 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/c_default/UserController.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.c_default;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 |
6 | import org.springframework.web.servlet.ModelAndView;
7 | import org.springframework.web.servlet.mvc.Controller;
8 |
9 | public class UserController implements Controller {
10 | @Override
11 | public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
12 | System.out.println("xixixixix...");
13 | ModelAndView mav = new ModelAndView();
14 | mav.setViewName("b");
15 | return mav;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/c_default/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/d_annotation/1.根据注解生成的内存模型.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/d_annotation/1.根据注解生成的内存模型.png
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/d_annotation/2.客户端请求注解控制器的原理.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/d_annotation/2.客户端请求注解控制器的原理.png
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/d_annotation/CarController.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.d_annotation;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.servlet.ModelAndView;
6 |
7 | @Controller
8 | @RequestMapping("car")
9 | public class CarController {
10 |
11 | @RequestMapping("save")
12 | public ModelAndView save() {
13 | return null;
14 | }
15 | @RequestMapping("delete")
16 | public ModelAndView f2() {
17 | return null;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/d_annotation/UserController.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.d_annotation;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.servlet.ModelAndView;
6 |
7 | @Controller
8 | @RequestMapping("user")
9 | public class UserController {
10 |
11 | @RequestMapping("save")
12 | public ModelAndView save() {
13 | System.out.println("save...");
14 | return null;
15 | }
16 | @RequestMapping("delete")
17 | public ModelAndView delete() {
18 | System.out.println("delete...");
19 | return null;
20 | }
21 | @RequestMapping("update")
22 | public ModelAndView update() {
23 | System.out.println("update...");
24 | return null;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/d_annotation/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/e_simple/CarController.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.e_simple;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.servlet.ModelAndView;
6 |
7 | @Controller
8 | @RequestMapping("car")
9 | public class CarController {
10 |
11 | @RequestMapping("save")
12 | public ModelAndView save() {
13 | System.out.println("car save");
14 | ModelAndView mav = new ModelAndView("e");
15 | return mav;
16 | }
17 | @RequestMapping("delete")
18 | public ModelAndView f2() {
19 | System.out.println("car delete");
20 | return null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/e_simple/UserController.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.e_simple;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.servlet.ModelAndView;
6 |
7 | @Controller
8 | @RequestMapping("user")
9 | public class UserController {
10 |
11 | @RequestMapping("save")
12 | public ModelAndView save() {
13 | System.out.println("save...");
14 | return null;
15 | }
16 | @RequestMapping("delete")
17 | public ModelAndView delete() {
18 | System.out.println("delete...");
19 | return null;
20 | }
21 | @RequestMapping("update")
22 | public ModelAndView update() {
23 | System.out.println("update...");
24 | return null;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/e_simple/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/f_parameter/MyDateConverter.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/f_parameter/MyDateConverter.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/f_parameter/User.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.f_parameter;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | public class User implements Serializable {
7 | private Integer uid;
8 | private String name;
9 | private Date birthday;
10 | private Double money;
11 | public User() {
12 | }
13 | public Integer getUid() {
14 | return uid;
15 | }
16 | public void setUid(Integer uid) {
17 | this.uid = uid;
18 | }
19 | public String getName() {
20 | return name;
21 | }
22 | public void setName(String name) {
23 | this.name = name;
24 | }
25 | public Date getBirthday() {
26 | return birthday;
27 | }
28 | public void setBirthday(Date birthday) {
29 | this.birthday = birthday;
30 | }
31 | public Double getMoney() {
32 | return money;
33 | }
34 | public void setMoney(Double money) {
35 | this.money = money;
36 | }
37 | @Override
38 | public String toString() {
39 | return "User [uid=" + uid + ", name=" + name + ", birthday=" + birthday + ", money=" + money + "]";
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/f_parameter/UserController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/f_parameter/UserController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/f_parameter/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/f_parameter/readme.txt
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/f_parameter/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/g_httpmessageconverter/Test.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/g_httpmessageconverter/Test.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/g_httpmessageconverter/a/AppTest.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/g_httpmessageconverter/a/AppTest.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/g_httpmessageconverter/b/MyHttpMessageConverter.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/g_httpmessageconverter/b/MyHttpMessageConverter.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/g_httpmessageconverter/b/User.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.g_httpmessageconverter.b;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | public class User implements Serializable {
7 | private Integer uid;
8 | private String name;
9 | private Date birthday;
10 | public User() {
11 | }
12 | public Integer getUid() {
13 | return uid;
14 | }
15 | public void setUid(Integer uid) {
16 | this.uid = uid;
17 | }
18 | public String getName() {
19 | return name;
20 | }
21 | public void setName(String name) {
22 | this.name = name;
23 | }
24 | public Date getBirthday() {
25 | return birthday;
26 | }
27 | public void setBirthday(Date birthday) {
28 | this.birthday = birthday;
29 | }
30 | @Override
31 | public String toString() {
32 | return "User [uid=" + uid + ", name=" + name + ", birthday=" + birthday + "]";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/g_httpmessageconverter/b/UserController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/g_httpmessageconverter/b/UserController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/g_httpmessageconverter/readme.txt:
--------------------------------------------------------------------------------
1 | 0.http请求由几部分组成?
2 | a. 请求行
3 | b. 请求头
4 | c. 请求体
5 |
6 | 1. http协议中的请求头:
7 | content-type,客户端告诉服务器,我客户端给你发送的是什么格式的数据。
8 | accept,客户端告诉服务器,我客户端想要什么格式的数据。
9 |
10 | 2. 客户端要什么格式的数据,服务器未必就会给什么格式的数据,因为这只是一个http规范而已,
11 | 服务器最终返回什么格式的数据,取决于你所编写的代码。
12 |
13 | 3. 我们都知道,springmvc框架是如何为控制器的参数注入值的:按照名称注入值(也就是拿着请求参数的名字,与目标方法的参数名匹配)。
14 |
15 | 4. 当我们在控制器的方法参数上添加了@RequestBody注解,springmvc框架就不再按照名称自动注入参数的值,
16 | 而是使用HttpMessageConverter来为参数注入值。
17 |
18 | 5. SpringMVC中HttpMessageConverter的工作原理:
19 | a. 客户端发起请求,并携带请求参数
20 | b. SpringMVC根据映射器找到对应的handler,再把handler交给适配器
21 | c. 适配器检测方法的参数上是否有@RequestBody
22 | 如果没有,则按照名称注入参数的值,然后流程就直接结束了。
23 | 如果有,则使用HttpMessageConverter注入参数的值,进入第4步
24 | d. SpringMVC框架读取出请求头中的content-type的值,比如为text/html(也就是客户端告诉服务器我给你发的是html格式的数据)
25 | SpringMVC根据获取到的content-type的值,去找出所有与此content-type的值匹配的HttpMessageConverter对象。
26 |
27 | 如果一个都找不到,则抛出异常:HttpMediaTypeNotSupportedException
28 | 如果找到一个或一个以上,则进入第5步 (多个HttpMessageConveter的顺序就是配置的顺序)
29 |
30 | e. SpringMVC拿着已经找到的一个或多个HttpMessageConverter对象,一一调用其canRead方法(canRead方法又回调了supports方法),
31 | canRead方法中判断目标参数的类型是否归当前HttpMessageConverter管理:
32 |
33 |
34 | 如果不是,则继续判断下一个;
35 | 如果是,则就确定了这唯一的一个HttpMessageConverter对象,然后进入第6步;(第一匹配者优先)
36 | 如果最终一个都找不到,则抛出异常: HttpMediaTypeNotSupportedException
37 |
38 | f. SpringMVC调用HttpMessageConverter的read方法: StringHttpMessageConverter
39 | // 参数clazz是要返回的对象的类型,也就是目标参数的类型
40 | // 参数inputMessage中封装了请求参数,可以通过该inputMessage获取到请求中的参数信息
41 | public final T read(Class extends T> clazz, HttpInputMessage inputMessage) throws IOException
42 |
43 | g. HttpMessageConverter的read方法执行完毕,把返回的对象注入给目标参数。
44 | 完成!
45 |
46 | h. 自定义HttpMessageConverter, 需要继承AbstractHttpMessageConverter,并实现相关方法。
47 | 然后需要在spring配置文件中,添加以下配置:
48 |
49 |
50 |
51 |
52 | text/user
53 |
54 |
55 |
56 |
57 | 其中register-defaults用于告诉springmvc框架是否加载默认的HttpMessageConverter(包括StringHttpMessageConverter)
58 |
59 | i. 可以查看AnnotationDrivenBeanDefinitionParser源码来分析HttpMessageConveter的底层原理。
60 |
61 | j. 通过阅读AnnotationDrivenBeanDefinitionParser源码,我们得知,如果register-defaults的取值为ture,且当前项目的classpath中有
62 | com.fasterxml.jackson.databind.ObjectMapper
63 | com.fasterxml.jackson.core.JsonGenerator
64 | 这两个类的话,springmvc就会自动加载用于处理json格式的HttpMessageConverter。 只需要导入jackson-databind jar包即可
65 |
66 | k. 参数配置代码如下:
67 |
68 |
69 |
70 |
71 |
72 | text/user
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | ============================================================================================================================
93 |
94 | 1. 我们已经知道,控制器的返回值是String的时候,视图解析器会把这个返回值当做逻辑视图,然后再把逻辑视图解析为物理视图。
95 |
96 | 2. 当我们在控制器的方法上添加@ResponseBody的时候,视图解析器就不会出来工作了。也就是说此时就没有视图解析器的什么事情了。
97 |
98 | 3. 当我们在控制器的方法上添加@ResponseBody的时候,SpringMVC框架会先根据客户端请求头中的 "返回值类型",再根据 "Accept的值" 来寻找一个最合适的HttpMessageConverter对象!
99 |
100 | accept: "a/b": StringHttpMessageConverter
101 |
102 | supports: String.class = c
103 |
104 | write, 最终write方法中的输入流写了什么,就会给客户端响应什么
105 |
106 |
107 | 4. SpringMVC会调用最合适的HttpMessageConverter对象的write方法:
108 | public final void write(final T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException
109 |
110 | 完成。
111 |
112 | ============================================================================================================================
113 |
114 | 注意
115 | 1.并不是使用了某一个HttpMessageConverter对象的read方法后,就一定会使用同一个HttpMessageConverter对象的write方法。
116 | 2.注意本例的Jackson-databind的使用,以及其中的ObjectMapper的使用(在Test类中有演示)
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/g_httpmessageconverter/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | woniu/gao
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/h_controller/User.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.h_controller;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | public class User implements Serializable {
7 | private Integer uid;
8 | private String name;
9 | private Date birthday;
10 | public User() {
11 | }
12 | public Integer getUid() {
13 | return uid;
14 | }
15 | public void setUid(Integer uid) {
16 | this.uid = uid;
17 | }
18 | public String getName() {
19 | return name;
20 | }
21 | public void setName(String name) {
22 | this.name = name;
23 | }
24 | public Date getBirthday() {
25 | return birthday;
26 | }
27 | public void setBirthday(Date birthday) {
28 | this.birthday = birthday;
29 | }
30 | @Override
31 | public String toString() {
32 | return "User [uid=" + uid + ", name=" + name + ", birthday=" + birthday + "]";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/h_controller/UserController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/h_controller/UserController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/h_controller/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/i_upload/UploadController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/i_upload/UploadController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/i_upload/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/i_upload/readme.txt
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/i_upload/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/j_interceptor/A.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/j_interceptor/A.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/j_interceptor/B.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/j_interceptor/B.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/j_interceptor/UserController.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.j_interceptor;
2 |
3 | import org.springframework.stereotype.Component;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 |
6 | @Component
7 | @RequestMapping("user")
8 | public class UserController {
9 |
10 | @RequestMapping("save")
11 | public String save() {
12 | System.out.println("UserController.save()");
13 | return "j";
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/j_interceptor/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/j_interceptor/拦截器图解1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/j_interceptor/拦截器图解1.png
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/j_interceptor/拦截器图解2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/j_interceptor/拦截器图解2.jpg
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/j_interceptor/拦截器图解3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/j_interceptor/拦截器图解3.jpg
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/k_exception/MyExceptionHandler.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/k_exception/MyExceptionHandler.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/k_exception/UserController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/k_exception/UserController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/k_exception/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/k_exception/异常处理器工作流程.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/k_exception/异常处理器工作流程.png
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/A.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.l_validation;
2 |
3 | public interface A {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/B.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.l_validation;
2 |
3 | public interface B {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/Prime.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/l_validation/Prime.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/PrimeValidator.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.l_validation;
2 |
3 | import javax.validation.ConstraintValidator;
4 | import javax.validation.ConstraintValidatorContext;
5 |
6 | public class PrimeValidator implements ConstraintValidator {
7 |
8 | private int min;
9 | private int max;
10 |
11 | @Override
12 | public void initialize(Prime p) {
13 | this.min = p.min();
14 | this.max = p.max();
15 | }
16 |
17 | @Override
18 | public boolean isValid(Integer value, ConstraintValidatorContext context) {
19 |
20 | if(value == null) {
21 | return false;
22 | }
23 |
24 | if(value >= min && value <= max) {
25 |
26 | int i;
27 | for(i = 2; i <= value/2; i++) {
28 | if(value % i == 0) {
29 | break;
30 | }
31 | }
32 | return i >= value/2;
33 | }
34 |
35 | return false;
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/User.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/l_validation/User.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/UserController.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.l_validation;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.ui.Model;
7 | import org.springframework.validation.Errors;
8 | import org.springframework.validation.FieldError;
9 | import org.springframework.validation.annotation.Validated;
10 | import org.springframework.web.bind.annotation.ModelAttribute;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 |
13 | @Controller
14 | @RequestMapping("user")
15 | public class UserController {
16 | @RequestMapping("save")
17 | public String save(@Validated(A.class) User user, Errors errors, Model model) {
18 | if(errors.hasErrors()) {
19 | List list = errors.getFieldErrors();
20 | for (FieldError fe : list) {
21 | model.addAttribute(fe.getField()+"Error", fe.getDefaultMessage());
22 | }
23 | return "l";
24 | } else {
25 | return "l_success";
26 | }
27 | }
28 |
29 |
30 | @RequestMapping("update")
31 | public String update(@Validated(B.class) User user, Errors errors, Model model) {
32 | if(errors.hasErrors()) {
33 | List list = errors.getFieldErrors();
34 | for (FieldError fe : list) {
35 | model.addAttribute(fe.getField()+"Error", fe.getDefaultMessage());
36 | }
37 | return "l";
38 | } else {
39 | return "l_success";
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/l_validation/readme.txt
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/l_validation/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/m_restful/User.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.m_restful;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | public class User implements Serializable {
7 | private Integer uid;
8 | private String name;
9 | private Date birthday;
10 | public User() {
11 | }
12 |
13 | public User(Integer uid, String name, Date birthday) {
14 | this.uid = uid;
15 | this.name = name;
16 | this.birthday = birthday;
17 | }
18 |
19 | public Integer getUid() {
20 | return uid;
21 | }
22 | public void setUid(Integer uid) {
23 | this.uid = uid;
24 | }
25 | public String getName() {
26 | return name;
27 | }
28 | public void setName(String name) {
29 | this.name = name;
30 | }
31 | public Date getBirthday() {
32 | return birthday;
33 | }
34 | public void setBirthday(Date birthday) {
35 | this.birthday = birthday;
36 | }
37 | @Override
38 | public String toString() {
39 | return "User [uid=" + uid + ", name=" + name + ", birthday=" + birthday + "]";
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/m_restful/UserController.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/java/com/woniuxy/m_restful/UserController.java
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/m_restful/readme.txt:
--------------------------------------------------------------------------------
1 | springmvc对restful风格的支持
2 |
3 | 0. 预备知识:
4 | a. 默认Servlet
5 |
6 | b. 资源 什么是资源?
7 | 1). 图片
8 | 2). 文本
9 | 3). 歌曲
10 | 4). 视频
11 | 所谓“资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。
12 | “但凡有利用价值的,都可以称之为资源”
13 |
14 | c. http协议复习
15 | 略
16 |
17 | 1. 什么是rest
18 | a. representational state transfer 表现性状态转换
19 | b. rest是一种设计风格,是一种思想,而不是一种标准。
20 | c. rest的核心是面向资源
21 | d. rest架构的主要原则
22 | 1) 网络上的所有事物都被抽象为资源
23 | 2) 每一个资源都有唯一的资源标识,对资源的操作不会改变这些标识。
24 | 比如,你根据资源标识删除了某个资源以后,这个资源标识还是有效的,只不过该资源标识代表的资源不存在而已。
25 | 3) 对资源做不同的操作时,总是通过相同的资源标识符来访问资源的
26 | 4) 所有操作都是无状态的
27 | 因为rest是基于http协议的一种设计风格,http就是无状态的连接协议
28 | 5) 同一个资源具有多种表现形式(xml, json)
29 | 6) 符合rest原则的架构方式即可称为RESTFUL
30 |
31 | 2. 为什么使用restful
32 | 不符合RESTFUL的URL
33 | 增 http://127.0.0.1:8080/user/save.do 请求方式:post
34 | 删 http://127.0.0.1:8080/user/delete.do?id=1 请求方式:post
35 | 改 http://127.0.0.1:8080/user/update.do 请求方式:post
36 | 查 http://127.0.0.1:8080/user/findOne.do?id=1 请求方式:post
37 | 查 http://127.0.0.1:8080/user/findAll.do 请求方式:post
38 |
39 | 符合RESTFUL的URL(资源+谓词)
40 | 增 http://127.0.0.1:8080/users 请求方式:post
41 | 删 http://127.0.0.1:8080/users 请求方式:delete
42 | 改 http://127.0.0.1:8080/users 请求方式:put
43 | 查 http://127.0.0.1:8080/users/1 请求方式:get
44 | 查 http://127.0.0.1:8080/users 请求方式:get
45 |
46 | 其实,不符合RESTFUL的URL也是没有什么问题的,但是大神认为是有问题的,有什么问题呢?
47 | 非RESTFUL的URL,查询的时候用了findOne或findAll,新增的时候用了save,其实完全
48 | 没有这个必要! 这样会导致api显得很杂乱。
49 |
50 | 因为http协议中已经提供了post、delete、put、get请求方式,程序员使
51 | 用不同请求方式的意图很明显,完全没有必要做额外的描述,这就是为什么有了RESTFUL
52 |
53 | 3. springmvc中如何使用restful
54 | a. 前端控制器DispatcherServlet的映射路径改为/
55 |
56 | springDispatcherServlet
57 | org.springframework.web.servlet.DispatcherServlet
58 |
59 | contextConfigLocation
60 | classpath:com/feicui/m_restful/applicationContext.xml
61 |
62 | 1
63 |
64 |
65 | springDispatcherServlet
66 | /
67 |
68 |
69 | 把前段控制器的映射路径该成“/”的目的是,保证请求地址中,没有后缀! 这恰恰是restful最佳实践所要求。
70 |
71 | 注意/*与/的
72 | 1)区别:/ 不拦截对jsp资源发起的请求,而 /* 会拦截对jsp发起的请求
73 | 2)相同:除了对jsp资源的访问外,/* 与 / 都会拦截所有请求,这样,当访问静态资源时,它们都会把静态资源当做映射来处理的。
74 | 比如在访问http://localhost:8080/images/2.jpg时,springmvc框架会直接把images/2.jpg交给映射器处理器,如果映射器处理器根据这个url找不到
75 | 对应的handler,则也不会把这个请求交给默认Serlvet,导致最终找不到这个资源。
76 | 3)注意,因为/*也会拦截jsp资源,所以此时springmvc框架也会把jsp资源当做映射来处理的..
77 |
78 | 在使用/*的大前提下:
79 | 1)访问jsp:拦截,且当做映射,404
80 | 2)访问jpg:拦截,且当做映射,404
81 | 3)访问users(get方式),拦截,且当做映射,200
82 |
83 | 在使用/的大前提下:
84 | 1)访问jsp:不拦截,交给servlet容器处理,200
85 | 2)访问jpg:拦截,且当做映射,404
86 | 3)访问users(get方式),拦截,且当做映射,200
87 |
88 | 在使用*.do的大前提下:
89 | 1)访问jsp:不拦截,200
90 | 2)访问jpg:不拦截,交给默认拦截器处理,200
91 | 3)访问users(get方式),拦截,且当做映射,200
92 |
93 | b. 静态资源映射(经常搭配前端控制器DispatcherServlet的映射路径为/)
94 |
95 | 或者直接配置默认servlet,该配置会自动找name为default的servlet作为默认servlet
96 |
97 |
98 | c. 编写controller,注意:
99 | 1) 在findOne方法中@PathVariable注解的使用,
100 | 2) 且为了响应json格式的数据给客户端,需要完成以下两个步骤:
101 | a.导入jackjson-databind.jar
102 | b.在控制器方法加上@ResponseBody注解!
103 |
104 | d. 先完成一个简单的restful风格的crud(只要能利用“资源标识+http谓词”分发请求即可)
105 | 1) 控制器的方法上需要使用RequestMapping的method属性来指定处理的http请求
106 |
107 | 2) 本来form只支持get和post请求方式,并不支持put和delete请求方式
108 | 幸好springmvc框架提供了 "HiddenHttpMethodFilter过滤器" 来间接让表单支持put/delete请求
109 |
110 | HiddenHttpMethodFilter
111 | org.springframework.web.filter.HiddenHttpMethodFilter
112 |
113 |
114 |
115 | HiddenHttpMethodFilter
116 | /*
117 |
118 | 此时,需要在表单中添加一个隐藏域,名字必须叫 "_method" ,其值可以是PUT/DELETE
119 | 如此,form表单就可以发起get、post、put、delete请求了!
120 |
121 | 表单代码,见m.jsp
122 |
123 | e. 利用"RESTful API设计6要素"改善api接口
124 | 1). 资源路径(URI)
125 | 在RESTful架构中,每个网址都代表一个资源,所以网址中不能有动词,只能有名词。
126 | API中的名词应该使用复数。
127 |
128 | eg. 有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样:
129 | 动物园资源:http://www.gao.com/zoos
130 | 动物资源:http://www.gao.com/animals
131 | 雇员资源:http://www.gao.com/employees
132 |
133 | 2). HTTP动词
134 | 对于资源的操作(CRUD),是由HTTP动词(谓词)表示的。
135 | GET:获取资源(一项或多项)
136 | POST:新建一个资源
137 | PUT:更新资源(整体)
138 | PATCH:更新资源(部分)
139 | DELETE:删除资源
140 |
141 | eg.
142 | 新建一个动物园:POST /zoos
143 | 获取某个动物园:GET /zoos/ID
144 | 更新某个动物园:PUT /zoos/ID
145 | 删除某个动物园:DELETE /zoos/ID
146 |
147 | 3). 过滤信息
148 | 如果记录数量很多,服务器不能都将它们返回给用户。
149 | API应该提供参数,过滤返回结果。
150 |
151 | 使用URL查询串来过滤数据是很好的方式,但不应该用于定位资源名称。如/posts/23,而不是/api?type=posts&id=23
152 |
153 | eg.
154 | ?offset=10:指定返回记录的开始位置。
155 | ?page=2&per_page=100:指定当前页,和每页显示的行数
156 | ?sort=-hiredate|sal:指定排序规则(有-前缀的表示降序)
157 | ?filter="name::gao|city::xian|gender::male":指定筛选条件
158 |
159 |
160 | 4). 错误处理
161 | 如果状态码是4xx或者5xx,就应该向用户返回出错信息。
162 | 一般来说,返回的信息中将error作为键名,错误信息作为键值即可。
163 | {
164 | "error": "错误信息"
165 | }
166 |
167 | 5). 返回结果
168 | 针对不同操作,服务器向用户返回的结果应该符合以下规范:
169 | GET /collections:返回资源对象的列表(数组) code: 200
170 | GET /collections/identity:返回单个资源对象 code: 200
171 | POST /collections:返回新生成的资源对象 code: 201
172 | PUT /collections/identity:返回完整的资源对象 code: 201
173 | PATCH /collections/identity:返回被修改的属性 code: 201
174 | DELETE /collections/identity:返回一个空文档 code: 204
175 |
176 | 6). 状态码
177 | 服务器向用户返回的状态码和提示信息,使用标准HTTP状态码
178 |
179 | 200 OK 服务器成功返回用户请求的数据,该操作是幂等的
180 | 什么是幂等性
181 | HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。
182 | 也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。
183 | 201 CREATED 新建或修改数据成功
184 | 204 NO CONTENT 删除数据成功
185 |
186 | 400 BAD REQUEST 用户发出的请求有错误,该操作是幂等的
187 | 401 Unauthorized 表示用户没有认证,无法进行当前操作
188 | 403 Forbidden 表示用户通过认证了,但是当前访问是被禁止的
189 | 405 用来访问本页面的 HTTP 谓词不被允许(方法不被允许)
190 | 415 不支持的媒体类型(Unsupported media type)
191 | 422 Unprocesable Entity 当创建一个对象时,发生一个验证错误
192 |
193 | 500 INTERNAL SERVER ERROR 服务器发生错误, 用户将无法判断发出的请求是否成功
194 |
195 | 4. RESTful架构与SOAP架构的区别
196 | a. WebService
197 | 1). WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
198 | 2). WebService通过Http协议发送请求和接收结果时采用XML格式封装,并增加了一些特定的HTTP消息头,
199 | 这些特定的HTTP消息头和XML内容格式就是soap协议。
200 |
201 | b. 难易度对比:
202 | SOAP由于各种需求不断扩充其本身协议的内容,导致在SOAP处理方面的性能有所下降。
203 | 同时在易用性方面以及学习成本上也有所增加。(复杂)
204 |
205 | RESTful由于其面向资源来进行接口设计,从而简化了api设计的过程。
206 | 同时也最大限度地利用Http最初的应用协议设计理念。(简单)
207 |
208 | c. 安全性对比:
209 | RESTful对于资源型服务接口来说很合适,特别适合于对效率要求很高,但是对于安全性要求不高的场景。
210 | SOAP的成熟性更适合于跨多语言的,对于安全性要求较高的接口设计。
211 |
212 | d. 综上:纯粹地说一个架构会占据主导地位是没有意义的,关键还是要看应用场景。
213 |
214 | ========================================================================================================================
215 |
216 | 练习:
217 | 资源路径: /users /articles
218 | HTTP动词: GET POST DELETE PUT
219 | 过滤信息: 文章的分页筛选
220 | 状态码: 200 404 422 403
221 |
222 | 数据库设计:
223 | 用户表:ID、用户名、密码、注册时间
224 | 文章表:文章ID、标题、内容、发表时间、用户ID
225 |
226 | 完成用户的CRUD
227 | 完成文章的CRUD
228 |
229 | 参考文献:https://www.cnblogs.com/jaxu/p/7908111.html
230 |
231 | ==========================================================================================================
232 | springmvc还有什么知识点:
233 | springmvc标签库, spel
234 |
--------------------------------------------------------------------------------
/src/main/java/com/woniuxy/m_restful/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/main/resources/gao.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u59D3\u540D\u5FC5\u987B\u5728{min}\u5230{max}\u5217\u4E4B\u95F4\u5427\uFF01\uFF01\uFF01\uFF01\uFF01\#\#\#\#\#
2 |
--------------------------------------------------------------------------------
/src/main/resources/gao_en_US.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=name must between {min} and {max} column
2 |
--------------------------------------------------------------------------------
/src/main/resources/gao_ja.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u3050\u3059\u305A\u305B\u3066\uFF01\uFF01\uFF01\uFF01\uFF01@@
2 |
--------------------------------------------------------------------------------
/src/main/resources/gao_ja_JP.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u3050\u3059\u305A\u305B\u3066\uFF01\uFF01\uFF01\uFF01\uFF01
2 |
--------------------------------------------------------------------------------
/src/main/resources/gao_zh_CN.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u59D3\u540D\u5FC5\u987B\u5728{min}\u5230{max}\u5217\u4E4B\u95F4\u5427\uFF01\uFF01\uFF01\uFF01\uFF01
2 | errors.cellphone.pattern=\u8FD9\u4E0D\u662F\u624B\u673A\uFF01
3 |
--------------------------------------------------------------------------------
/src/main/resources/log4j2.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger = OFF , stdout
2 |
3 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender
4 | log4j.appender.stdout.layout = org.apache.log4j.TTCCLayout
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 | springDispatcherServlet
15 | org.springframework.web.servlet.DispatcherServlet
16 |
17 | contextConfigLocation
18 | classpath:com/woniuxy/m_restful/spring-servlet.xml
19 |
20 | 1
21 |
22 |
23 |
24 | springDispatcherServlet
25 |
26 | /
27 |
28 |
29 |
30 | CharacterEncodingFilter
31 | org.springframework.web.filter.CharacterEncodingFilter
32 |
33 | encoding
34 | utf-8
35 |
36 |
37 |
38 | CharacterEncodingFilter
39 | /*
40 |
41 |
42 |
43 | HiddenHttpMethodFilter
44 | org.springframework.web.filter.HiddenHttpMethodFilter
45 |
46 |
47 | HiddenHttpMethodFilter
48 | /*
49 |
50 |
--------------------------------------------------------------------------------
/src/main/webapp/a.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | a.jsp
11 |
12 | 我从未见过如此厚颜无耻之人
13 |
14 | ${requestScope.msg }
15 |
16 |
--------------------------------------------------------------------------------
/src/main/webapp/e.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | e.jsp
11 |
12 | 谁敢杀我,谁敢杀我,谁敢杀我,啊!!
13 |
14 |
--------------------------------------------------------------------------------
/src/main/webapp/f.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | f.jsp
11 |
12 |
13 |
27 |
28 |
29 |
37 |
38 |
48 |
49 |
65 |
66 |
67 |
83 |
84 |
100 |
101 |
102 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/src/main/webapp/g.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 |
11 | g.jsp
12 |
13 |
25 |
26 |
27 |
28 |
41 |
42 |
43 |
44 |
45 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/main/webapp/h.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | h.jsp
11 |
12 | ${requestScope.abc }
13 | ${requestScope.date }
14 | ${requestScope.user }
15 |
16 |
--------------------------------------------------------------------------------
/src/main/webapp/html/m2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Insert title here
6 |
7 |
8 |
9 | m2.html
10 |
11 | 开始满意自己,就是开始退步!
12 |
13 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/main/webapp/i.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | i.jsp
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/webapp/images/1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/webapp/images/1.gif
--------------------------------------------------------------------------------
/src/main/webapp/images/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/webapp/images/1.jpg
--------------------------------------------------------------------------------
/src/main/webapp/images/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/src/main/webapp/images/2.jpg
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | index.jsp
11 |
12 | 天下大势,合久必分,分久必合!
13 |
14 |
--------------------------------------------------------------------------------
/src/main/webapp/j.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | j.jsp
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/webapp/k_error.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | k error.jsp
11 |
12 | 程序猿鼓励师美女图... 请自行脑补..
13 |
14 | 程序猿正在玩命修复bug...
15 |
16 | 请稍微休息以下,玩个游戏把:
17 | tank大战..
18 |
19 |
--------------------------------------------------------------------------------
/src/main/webapp/l.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 | <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
4 |
5 |
6 |
7 |
8 | Insert title here
9 |
10 |
11 | l.jsp
12 |
13 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/webapp/l2.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 | <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
4 |
5 |
6 |
7 |
8 | Insert title here
9 |
10 |
11 | l2.jsp
12 |
13 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/webapp/l_success.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | l.jsp
11 |
12 | success
13 |
14 |
--------------------------------------------------------------------------------
/src/main/webapp/m.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 | <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
4 |
5 |
6 |
7 |
8 | Insert title here
9 |
10 |
11 | m.jsp
12 |
13 | 要想有成就: 一门深入 长时熏修。
14 |
15 |
18 |
19 |
22 |
23 |
27 |
28 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/test/java/com/woniuxy/test/AppTest.java:
--------------------------------------------------------------------------------
1 | package com.woniuxy.test;
2 |
3 | import org.junit.Test;
4 |
5 | public class AppTest {
6 | @Test
7 | public void test() throws Exception {
8 | int i = 2147483647;
9 | int i2 = 2147483632;
10 |
11 | System.out.println(i);
12 | System.out.println(i2);
13 |
14 | System.out.println(i == i2);
15 |
16 | float f = i;
17 | float f2 = i2;
18 |
19 | System.out.println(f);
20 | System.out.println(f2);
21 |
22 | System.out.println(f == f2);
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/a_hello/1.感性的springmvc运行原理图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/a_hello/1.感性的springmvc运行原理图.png
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/a_hello/2.springmvc架构图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/a_hello/2.springmvc架构图.png
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/a_hello/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/a_hello/readme.txt
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/a_hello/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/b_replace/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/b_replace/readme.txt
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/b_replace/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
22 |
23 |
24 |
25 | kk
26 | qq
27 |
28 |
29 |
30 |
31 |
39 |
40 |
41 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/c_default/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/d_annotation/1.根据注解生成的内存模型.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/d_annotation/1.根据注解生成的内存模型.png
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/d_annotation/2.客户端请求注解控制器的原理.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/d_annotation/2.客户端请求注解控制器的原理.png
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/d_annotation/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/e_simple/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/f_parameter/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/f_parameter/readme.txt
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/f_parameter/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/g_httpmessageconverter/readme.txt:
--------------------------------------------------------------------------------
1 | 0.http请求由几部分组成?
2 | a. 请求行
3 | b. 请求头
4 | c. 请求体
5 |
6 | 1. http协议中的请求头:
7 | content-type,客户端告诉服务器,我客户端给你发送的是什么格式的数据。
8 | accept,客户端告诉服务器,我客户端想要什么格式的数据。
9 |
10 | 2. 客户端要什么格式的数据,服务器未必就会给什么格式的数据,因为这只是一个http规范而已,
11 | 服务器最终返回什么格式的数据,取决于你所编写的代码。
12 |
13 | 3. 我们都知道,springmvc框架是如何为控制器的参数注入值的:按照名称注入值(也就是拿着请求参数的名字,与目标方法的参数名匹配)。
14 |
15 | 4. 当我们在控制器的方法参数上添加了@RequestBody注解,springmvc框架就不再按照名称自动注入参数的值,
16 | 而是使用HttpMessageConverter来为参数注入值。
17 |
18 | 5. SpringMVC中HttpMessageConverter的工作原理:
19 | a. 客户端发起请求,并携带请求参数
20 | b. SpringMVC根据映射器找到对应的handler,再把handler交给适配器
21 | c. 适配器检测方法的参数上是否有@RequestBody
22 | 如果没有,则按照名称注入参数的值,然后流程就直接结束了。
23 | 如果有,则使用HttpMessageConverter注入参数的值,进入第4步
24 | d. SpringMVC框架读取出请求头中的content-type的值,比如为text/html(也就是客户端告诉服务器我给你发的是html格式的数据)
25 | SpringMVC根据获取到的content-type的值,去找出所有与此content-type的值匹配的HttpMessageConverter对象。
26 |
27 | 如果一个都找不到,则抛出异常:HttpMediaTypeNotSupportedException
28 | 如果找到一个或一个以上,则进入第5步 (多个HttpMessageConveter的顺序就是配置的顺序)
29 |
30 | e. SpringMVC拿着已经找到的一个或多个HttpMessageConverter对象,一一调用其canRead方法(canRead方法又回调了supports方法),
31 | canRead方法中判断目标参数的类型是否归当前HttpMessageConverter管理:
32 |
33 |
34 | 如果不是,则继续判断下一个;
35 | 如果是,则就确定了这唯一的一个HttpMessageConverter对象,然后进入第6步;(第一匹配者优先)
36 | 如果最终一个都找不到,则抛出异常: HttpMediaTypeNotSupportedException
37 |
38 | f. SpringMVC调用HttpMessageConverter的read方法: StringHttpMessageConverter
39 | // 参数clazz是要返回的对象的类型,也就是目标参数的类型
40 | // 参数inputMessage中封装了请求参数,可以通过该inputMessage获取到请求中的参数信息
41 | public final T read(Class extends T> clazz, HttpInputMessage inputMessage) throws IOException
42 |
43 | g. HttpMessageConverter的read方法执行完毕,把返回的对象注入给目标参数。
44 | 完成!
45 |
46 | h. 自定义HttpMessageConverter, 需要继承AbstractHttpMessageConverter,并实现相关方法。
47 | 然后需要在spring配置文件中,添加以下配置:
48 |
49 |
50 |
51 |
52 | text/user
53 |
54 |
55 |
56 |
57 | 其中register-defaults用于告诉springmvc框架是否加载默认的HttpMessageConverter(包括StringHttpMessageConverter)
58 |
59 | i. 可以查看AnnotationDrivenBeanDefinitionParser源码来分析HttpMessageConveter的底层原理。
60 |
61 | j. 通过阅读AnnotationDrivenBeanDefinitionParser源码,我们得知,如果register-defaults的取值为ture,且当前项目的classpath中有
62 | com.fasterxml.jackson.databind.ObjectMapper
63 | com.fasterxml.jackson.core.JsonGenerator
64 | 这两个类的话,springmvc就会自动加载用于处理json格式的HttpMessageConverter。 只需要导入jackson-databind jar包即可
65 |
66 | k. 参数配置代码如下:
67 |
68 |
69 |
70 |
71 |
72 | text/user
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | ============================================================================================================================
93 |
94 | 1. 我们已经知道,控制器的返回值是String的时候,视图解析器会把这个返回值当做逻辑视图,然后再把逻辑视图解析为物理视图。
95 |
96 | 2. 当我们在控制器的方法上添加@ResponseBody的时候,视图解析器就不会出来工作了。也就是说此时就没有视图解析器的什么事情了。
97 |
98 | 3. 当我们在控制器的方法上添加@ResponseBody的时候,SpringMVC框架会先根据客户端请求头中的 "返回值类型",再根据 "Accept的值" 来寻找一个最合适的HttpMessageConverter对象!
99 |
100 | accept: "a/b": StringHttpMessageConverter
101 |
102 | supports: String.class = c
103 |
104 | write, 最终write方法中的输入流写了什么,就会给客户端响应什么
105 |
106 |
107 | 4. SpringMVC会调用最合适的HttpMessageConverter对象的write方法:
108 | public final void write(final T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException
109 |
110 | 完成。
111 |
112 | ============================================================================================================================
113 |
114 | 注意
115 | 1.并不是使用了某一个HttpMessageConverter对象的read方法后,就一定会使用同一个HttpMessageConverter对象的write方法。
116 | 2.注意本例的Jackson-databind的使用,以及其中的ObjectMapper的使用(在Test类中有演示)
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/g_httpmessageconverter/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | woniu/gao
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/h_controller/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/i_upload/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/i_upload/readme.txt
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/i_upload/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/j_interceptor/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/j_interceptor/拦截器图解1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/j_interceptor/拦截器图解1.png
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/j_interceptor/拦截器图解2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/j_interceptor/拦截器图解2.jpg
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/j_interceptor/拦截器图解3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/j_interceptor/拦截器图解3.jpg
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/k_exception/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/l_validation/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gapper0208/springmvc/595bfebfae3b944a97b73039c539d5b6c8c1d131/target/classes/com/woniuxy/l_validation/readme.txt
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/l_validation/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/m_restful/readme.txt:
--------------------------------------------------------------------------------
1 | springmvc对restful风格的支持
2 |
3 | 0. 预备知识:
4 | a. 默认Servlet
5 |
6 | b. 资源 什么是资源?
7 | 1). 图片
8 | 2). 文本
9 | 3). 歌曲
10 | 4). 视频
11 | 所谓“资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。
12 | “但凡有利用价值的,都可以称之为资源”
13 |
14 | c. http协议复习
15 | 略
16 |
17 | 1. 什么是rest
18 | a. representational state transfer 表现性状态转换
19 | b. rest是一种设计风格,是一种思想,而不是一种标准。
20 | c. rest的核心是面向资源
21 | d. rest架构的主要原则
22 | 1) 网络上的所有事物都被抽象为资源
23 | 2) 每一个资源都有唯一的资源标识,对资源的操作不会改变这些标识。
24 | 比如,你根据资源标识删除了某个资源以后,这个资源标识还是有效的,只不过该资源标识代表的资源不存在而已。
25 | 3) 对资源做不同的操作时,总是通过相同的资源标识符来访问资源的
26 | 4) 所有操作都是无状态的
27 | 因为rest是基于http协议的一种设计风格,http就是无状态的连接协议
28 | 5) 同一个资源具有多种表现形式(xml, json)
29 | 6) 符合rest原则的架构方式即可称为RESTFUL
30 |
31 | 2. 为什么使用restful
32 | 不符合RESTFUL的URL
33 | 增 http://127.0.0.1:8080/user/save.do 请求方式:post
34 | 删 http://127.0.0.1:8080/user/delete.do?id=1 请求方式:post
35 | 改 http://127.0.0.1:8080/user/update.do 请求方式:post
36 | 查 http://127.0.0.1:8080/user/findOne.do?id=1 请求方式:post
37 | 查 http://127.0.0.1:8080/user/findAll.do 请求方式:post
38 |
39 | 符合RESTFUL的URL(资源+谓词)
40 | 增 http://127.0.0.1:8080/users 请求方式:post
41 | 删 http://127.0.0.1:8080/users 请求方式:delete
42 | 改 http://127.0.0.1:8080/users 请求方式:put
43 | 查 http://127.0.0.1:8080/users/1 请求方式:get
44 | 查 http://127.0.0.1:8080/users 请求方式:get
45 |
46 | 其实,不符合RESTFUL的URL也是没有什么问题的,但是大神认为是有问题的,有什么问题呢?
47 | 非RESTFUL的URL,查询的时候用了findOne或findAll,新增的时候用了save,其实完全
48 | 没有这个必要! 这样会导致api显得很杂乱。
49 |
50 | 因为http协议中已经提供了post、delete、put、get请求方式,程序员使
51 | 用不同请求方式的意图很明显,完全没有必要做额外的描述,这就是为什么有了RESTFUL
52 |
53 | 3. springmvc中如何使用restful
54 | a. 前端控制器DispatcherServlet的映射路径改为/
55 |
56 | springDispatcherServlet
57 | org.springframework.web.servlet.DispatcherServlet
58 |
59 | contextConfigLocation
60 | classpath:com/feicui/m_restful/applicationContext.xml
61 |
62 | 1
63 |
64 |
65 | springDispatcherServlet
66 | /
67 |
68 |
69 | 把前段控制器的映射路径该成“/”的目的是,保证请求地址中,没有后缀! 这恰恰是restful最佳实践所要求。
70 |
71 | 注意/*与/的
72 | 1)区别:/ 不拦截对jsp资源发起的请求,而 /* 会拦截对jsp发起的请求
73 | 2)相同:除了对jsp资源的访问外,/* 与 / 都会拦截所有请求,这样,当访问静态资源时,它们都会把静态资源当做映射来处理的。
74 | 比如在访问http://localhost:8080/images/2.jpg时,springmvc框架会直接把images/2.jpg交给映射器处理器,如果映射器处理器根据这个url找不到
75 | 对应的handler,则也不会把这个请求交给默认Serlvet,导致最终找不到这个资源。
76 | 3)注意,因为/*也会拦截jsp资源,所以此时springmvc框架也会把jsp资源当做映射来处理的..
77 |
78 | 在使用/*的大前提下:
79 | 1)访问jsp:拦截,且当做映射,404
80 | 2)访问jpg:拦截,且当做映射,404
81 | 3)访问users(get方式),拦截,且当做映射,200
82 |
83 | 在使用/的大前提下:
84 | 1)访问jsp:不拦截,交给servlet容器处理,200
85 | 2)访问jpg:拦截,且当做映射,404
86 | 3)访问users(get方式),拦截,且当做映射,200
87 |
88 | 在使用*.do的大前提下:
89 | 1)访问jsp:不拦截,200
90 | 2)访问jpg:不拦截,交给默认拦截器处理,200
91 | 3)访问users(get方式),拦截,且当做映射,200
92 |
93 | b. 静态资源映射(经常搭配前端控制器DispatcherServlet的映射路径为/)
94 |
95 | 或者直接配置默认servlet,该配置会自动找name为default的servlet作为默认servlet
96 |
97 |
98 | c. 编写controller,注意:
99 | 1) 在findOne方法中@PathVariable注解的使用,
100 | 2) 且为了响应json格式的数据给客户端,需要完成以下两个步骤:
101 | a.导入jackjson-databind.jar
102 | b.在控制器方法加上@ResponseBody注解!
103 |
104 | d. 先完成一个简单的restful风格的crud(只要能利用“资源标识+http谓词”分发请求即可)
105 | 1) 控制器的方法上需要使用RequestMapping的method属性来指定处理的http请求
106 |
107 | 2) 本来form只支持get和post请求方式,并不支持put和delete请求方式
108 | 幸好springmvc框架提供了 "HiddenHttpMethodFilter过滤器" 来间接让表单支持put/delete请求
109 |
110 | HiddenHttpMethodFilter
111 | org.springframework.web.filter.HiddenHttpMethodFilter
112 |
113 |
114 |
115 | HiddenHttpMethodFilter
116 | /*
117 |
118 | 此时,需要在表单中添加一个隐藏域,名字必须叫 "_method" ,其值可以是PUT/DELETE
119 | 如此,form表单就可以发起get、post、put、delete请求了!
120 |
121 | 表单代码,见m.jsp
122 |
123 | e. 利用"RESTful API设计6要素"改善api接口
124 | 1). 资源路径(URI)
125 | 在RESTful架构中,每个网址都代表一个资源,所以网址中不能有动词,只能有名词。
126 | API中的名词应该使用复数。
127 |
128 | eg. 有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样:
129 | 动物园资源:http://www.gao.com/zoos
130 | 动物资源:http://www.gao.com/animals
131 | 雇员资源:http://www.gao.com/employees
132 |
133 | 2). HTTP动词
134 | 对于资源的操作(CRUD),是由HTTP动词(谓词)表示的。
135 | GET:获取资源(一项或多项)
136 | POST:新建一个资源
137 | PUT:更新资源(整体)
138 | PATCH:更新资源(部分)
139 | DELETE:删除资源
140 |
141 | eg.
142 | 新建一个动物园:POST /zoos
143 | 获取某个动物园:GET /zoos/ID
144 | 更新某个动物园:PUT /zoos/ID
145 | 删除某个动物园:DELETE /zoos/ID
146 |
147 | 3). 过滤信息
148 | 如果记录数量很多,服务器不能都将它们返回给用户。
149 | API应该提供参数,过滤返回结果。
150 |
151 | 使用URL查询串来过滤数据是很好的方式,但不应该用于定位资源名称。如/posts/23,而不是/api?type=posts&id=23
152 |
153 | eg.
154 | ?offset=10:指定返回记录的开始位置。
155 | ?page=2&per_page=100:指定当前页,和每页显示的行数
156 | ?sort=-hiredate|sal:指定排序规则(有-前缀的表示降序)
157 | ?filter="name::gao|city::xian|gender::male":指定筛选条件
158 |
159 |
160 | 4). 错误处理
161 | 如果状态码是4xx或者5xx,就应该向用户返回出错信息。
162 | 一般来说,返回的信息中将error作为键名,错误信息作为键值即可。
163 | {
164 | "error": "错误信息"
165 | }
166 |
167 | 5). 返回结果
168 | 针对不同操作,服务器向用户返回的结果应该符合以下规范:
169 | GET /collections:返回资源对象的列表(数组) code: 200
170 | GET /collections/identity:返回单个资源对象 code: 200
171 | POST /collections:返回新生成的资源对象 code: 201
172 | PUT /collections/identity:返回完整的资源对象 code: 201
173 | PATCH /collections/identity:返回被修改的属性 code: 201
174 | DELETE /collections/identity:返回一个空文档 code: 204
175 |
176 | 6). 状态码
177 | 服务器向用户返回的状态码和提示信息,使用标准HTTP状态码
178 |
179 | 200 OK 服务器成功返回用户请求的数据,该操作是幂等的
180 | 什么是幂等性
181 | HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。
182 | 也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。
183 | 201 CREATED 新建或修改数据成功
184 | 204 NO CONTENT 删除数据成功
185 |
186 | 400 BAD REQUEST 用户发出的请求有错误,该操作是幂等的
187 | 401 Unauthorized 表示用户没有认证,无法进行当前操作
188 | 403 Forbidden 表示用户通过认证了,但是当前访问是被禁止的
189 | 405 用来访问本页面的 HTTP 谓词不被允许(方法不被允许)
190 | 415 不支持的媒体类型(Unsupported media type)
191 | 422 Unprocesable Entity 当创建一个对象时,发生一个验证错误
192 |
193 | 500 INTERNAL SERVER ERROR 服务器发生错误, 用户将无法判断发出的请求是否成功
194 |
195 | 4. RESTful架构与SOAP架构的区别
196 | a. WebService
197 | 1). WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
198 | 2). WebService通过Http协议发送请求和接收结果时采用XML格式封装,并增加了一些特定的HTTP消息头,
199 | 这些特定的HTTP消息头和XML内容格式就是soap协议。
200 |
201 | b. 难易度对比:
202 | SOAP由于各种需求不断扩充其本身协议的内容,导致在SOAP处理方面的性能有所下降。
203 | 同时在易用性方面以及学习成本上也有所增加。(复杂)
204 |
205 | RESTful由于其面向资源来进行接口设计,从而简化了api设计的过程。
206 | 同时也最大限度地利用Http最初的应用协议设计理念。(简单)
207 |
208 | c. 安全性对比:
209 | RESTful对于资源型服务接口来说很合适,特别适合于对效率要求很高,但是对于安全性要求不高的场景。
210 | SOAP的成熟性更适合于跨多语言的,对于安全性要求较高的接口设计。
211 |
212 | d. 综上:纯粹地说一个架构会占据主导地位是没有意义的,关键还是要看应用场景。
213 |
214 | ========================================================================================================================
215 |
216 | 练习:
217 | 资源路径: /users /articles
218 | HTTP动词: GET POST DELETE PUT
219 | 过滤信息: 文章的分页筛选
220 | 状态码: 200 404 422 403
221 |
222 | 数据库设计:
223 | 用户表:ID、用户名、密码、注册时间
224 | 文章表:文章ID、标题、内容、发表时间、用户ID
225 |
226 | 完成用户的CRUD
227 | 完成文章的CRUD
228 |
229 | 参考文献:https://www.cnblogs.com/jaxu/p/7908111.html
230 |
231 | ==========================================================================================================
232 | springmvc还有什么知识点:
233 | springmvc标签库, spel
234 |
--------------------------------------------------------------------------------
/target/classes/com/woniuxy/m_restful/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/target/classes/gao.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u59D3\u540D\u5FC5\u987B\u5728{min}\u5230{max}\u5217\u4E4B\u95F4\u5427\uFF01\uFF01\uFF01\uFF01\uFF01\#\#\#\#\#
2 |
--------------------------------------------------------------------------------
/target/classes/gao_en_US.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=name must between {min} and {max} column
2 |
--------------------------------------------------------------------------------
/target/classes/gao_ja.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u3050\u3059\u305A\u305B\u3066\uFF01\uFF01\uFF01\uFF01\uFF01@@
2 |
--------------------------------------------------------------------------------
/target/classes/gao_ja_JP.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u3050\u3059\u305A\u305B\u3066\uFF01\uFF01\uFF01\uFF01\uFF01
2 |
--------------------------------------------------------------------------------
/target/classes/gao_zh_CN.properties:
--------------------------------------------------------------------------------
1 | errors.name.size=\u59D3\u540D\u5FC5\u987B\u5728{min}\u5230{max}\u5217\u4E4B\u95F4\u5427\uFF01\uFF01\uFF01\uFF01\uFF01
2 | errors.cellphone.pattern=\u8FD9\u4E0D\u662F\u624B\u673A\uFF01
3 |
--------------------------------------------------------------------------------
/target/classes/log4j2.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger = OFF , stdout
2 |
3 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender
4 | log4j.appender.stdout.layout = org.apache.log4j.TTCCLayout
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/maven/com.woniuxy/springmvc/pom.properties:
--------------------------------------------------------------------------------
1 | #Generated by Maven Integration for Eclipse
2 | #Wed Jun 26 08:57:03 CST 2019
3 | version=0.0.1-SNAPSHOT
4 | groupId=com.woniuxy
5 | m2e.projectName=springmvc
6 | m2e.projectLocation=D\:\\spring-tool-suite-4\\sts-4.2.2.RELEASE\\workspace\\springmvc
7 | artifactId=springmvc
8 |
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/maven/com.woniuxy/springmvc/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.woniuxy
4 | springmvc
5 | 0.0.1-SNAPSHOT
6 | war
7 |
8 |
9 |
10 |
11 | org.springframework
12 | spring-webmvc
13 | 4.3.23.RELEASE
14 |
15 |
16 | junit
17 | junit
18 | 4.12
19 |
20 |
21 | javax.servlet
22 | javax.servlet-api
23 | 3.1.0
24 |
25 |
26 | javax.servlet
27 | jstl
28 | 1.2
29 |
30 |
31 | log4j
32 | log4j
33 | 1.2.12
34 |
35 |
36 | com.fasterxml.jackson.core
37 | jackson-databind
38 | 2.9.9
39 |
40 |
41 |
42 | commons-fileupload
43 | commons-fileupload
44 | 1.4
45 |
46 |
47 | org.hibernate.validator
48 | hibernate-validator
49 | 6.0.7.Final
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------