├── .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 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 |
14 | 8种基本类型 15 |
16 | byte:
17 | short:
18 | int:
19 | long:
20 | float:
21 | double:
22 | boolean:
23 | char:
24 | 25 |
26 |
27 | 28 | 29 |
30 | String类型 31 |
32 | username:
33 | password:
34 | 35 |
36 |
37 | 38 |
39 | User类型 40 |
41 | uid:
42 | name:
43 | birthday:
44 | money:
45 | 46 |
47 |
48 | 49 |
50 | List类型 51 |
52 | hobby: 53 | 56 | 59 | 62 | 63 |
64 |
65 | 66 | 67 |
68 | Set类型 69 |
70 | food: 71 | 74 | 77 | 80 | 81 |
82 |
83 | 84 |
85 | Map类型 86 |
87 | foo: 88 | 91 | 94 | 97 | 98 |
99 |
100 | 101 | 102 |
103 | String数组类型 104 |
105 | strs: 106 | 109 | 112 | 115 | 116 |
117 |
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 |
13 | photo:
14 | 15 |
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 |
14 | uid:${uidError }
15 | name:${nameError }
16 | birthday:" />
17 | money:
18 | cellphone:${cellphoneError }
19 | 20 |
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 |
14 | uid:${uidError }
15 | name:${nameError }
16 | birthday:" />
17 | money:
18 | cellphone:${cellphoneError }
19 | 20 |
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 |
16 | 17 |
18 | 19 |
20 | 21 |
22 | 23 |
24 | 25 | 26 |
27 | 28 |
29 | 30 | 31 |
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 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 | --------------------------------------------------------------------------------