文章笔记整合【狂神说】
一、第一个springMVC项目 1.1 理解原理版项目
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > moc.mc</groupId > <artifactId > SpringMVC</artifactId > <packaging > pom</packaging > <version > 1.0-SNAPSHOT</version > <modules > <module > mvc01</module > </modules > <dependencies > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.12</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.2</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.47</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > 5.1.10.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 5.1.10.RELEASE</version > </dependency > <dependency > <groupId > org.aspectj</groupId > <artifactId > aspectjweaver</artifactId > <version > 1.9.4</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.2</version > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.10</version > </dependency > </dependencies > <build > <resources > <resource > <directory > src/main/java</directory > <includes > <include > **/*.properties</include > <include > **/*.xml</include > </includes > <filtering > true</filtering > </resource > </resources > </build > </project >
web/WEB-INF/web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" > <servlet > <servlet-name > springmvc</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc-servlet.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > springmvc</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > </web-app >
com/mc/controller/HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.mc.controller;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class HelloController implements Controller { public ModelAndView handleRequest (HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg" ,"HelloSpringMVC!" ); mv.setViewName("hello" ); return mv; } }
springmvc-servlet.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean class ="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <bean class ="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" id ="InternalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/jsp/" /> <property name ="suffix" value =".jsp" /> </bean > <bean id ="/hello" class ="com.mc.controller.HelloController" /> </beans >
hello.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <%-- Created by IntelliJ IDEA. User: wenjing Date: 2020 /12 /27 Time: 21 :57 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Kuangshen</title> </head> <body> ${msg} </body> </html>
启动
1.2 注解版项目 1、新建一个Moudle,springmvc-03-hello-annotation 。添加web支持!
2、由于Maven可能存在资源过滤的问题,我们将配置完善
1 2 3 4 5 6 7 8 9 10 11 12 <build > <resources > <resource > <directory > src/main/java</directory > <includes > <include > **/*.properties</include > <include > **/*.xml</include > </includes > <filtering > true</filtering > </resource > </resources > </build >
3、在pom.xml文件引入相关的依赖:主要有Spring框架核心库、Spring MVC、servlet , JSTL等。我们在父依赖中已经引入了!
4、配置web.xml
注意点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" > <servlet > <servlet-name > springmvc</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc-servlet.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > springmvc</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > </web-app >
/ 和 /* 的区别: < url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进入spring的 DispatcherServlet类 。< url-pattern > /* </ url-pattern > 会匹配 *.jsp,会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。
注意web.xml版本问题,要最新版!
注册DispatcherServlet
关联SpringMVC的配置文件
启动级别为1
映射路径为 / 【不要用/*,会404】
5、添加Spring MVC配置文件
在resource目录下添加springmvc-servlet.xml配置文件,配置的形式与Spring容器配置基本类似,为了支持基于注解的IOC,设置了自动扫描包的功能,具体配置信息如下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.kuang.controller"/>
<!-- 让Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler />
<!-- 支持mvc注解驱动 在spring中一般采用@RequestMapping注解来完成映射关系 要想使@RequestMapping注解生效 必须向上下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理。 而annotation-driven配置帮助我们自动完成上述两个实例的注入。 --> <mvc:annotation-driven />
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 5 . 在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。6 . - 让IOC的注解生效 - 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 ..... - MVC的注解驱动 - 配置视图解析器7 . **6 、创建Controller**8 . 编写一个Java控制类:com.kuang.controller.HelloController , 注意编码规范9 . ```java package com.kuang.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation .RequestMapping; @Controller @RequestMapping("/HelloController" ) public class HelloController { @RequestMapping("/hello" ) public String sayHello(Model model){ model.addAttribute("msg" ,"hello,SpringMVC" ); return "hello" ; } }
@Controller是为了让Spring IOC容器初始化时自动扫描到;
@RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
方法中声明Model类型的参数是为了把Action中的数据带到视图中;
方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello .jsp。
7、创建视图层
在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息;
可以通过EL表示取出Model中存放的值,或者对象;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>SpringMVC</title>
</head>
<body>${msg}</body>
</html>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 **8、配置Tomcat运行** 配置Tomcat , 开启服务器 , 访问 对应的请求路径!## 小结 实现步骤其实非常的简单:1. 新建一个web项目2. 导入相关jar包3. 编写web.xml , 注册DispatcherServlet4. 编写springmvc配置文件5. 接下来就是去创建对应的控制类 , controller6. 最后完善前端视图和controller之间的对应7. 测试运行调试. 使用springMVC必须配置的三大件:**处理器映射器、处理器适配器、视图解析器** (注解版只需自行配置**视图解析器** ) 通常,我们只需要**手动配置视图解析器** ,而**处理器映射器** 和**处理器适配器** 只需要开启**注解驱动** 即可,而省去了大段的xml配置## 1.3 SpringMVC原理 ### 1.3.1 MVC架构思想 - MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。- 是将业务逻辑、数据、显示分离的方法来组织代码。- MVC主要作用是**降低了视图与业务逻辑间的双向偶合** 。- MVC不是一种设计模式,**MVC是一种架构模式** 。当然不同的MVC存在差异。**Model(模型):** 数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。**View(视图):** 负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。**Controller(控制器):** 接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。**职责分析:** **Model:模型** 1. 业务逻辑2. 保存数据的状态**View:视图** 1. 显示页面**Controller:控制器** 1. 取得表单数据2. 调用业务逻辑3. 转向指定的页面### 1.3.2 中心控制器 Spring的web框架围绕DispatcherServlet设计。DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。 Spring MVC框架像许多其他MVC框架一样, **以请求为驱动** , **围绕一个中心Servlet分派请求及提供其他功能** ,**DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)** 。  SpringMVC的原理如下图所示: 当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。 ## 1.4 SpringMVC执行原理  图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。**简要分析执行流程** 1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。 我们假设请求的url为 : http://localhost:8080/SpringMVC/hello **如上url拆分成三部分:** http://localhost:8080服务器域名 SpringMVC部署在服务器上的web站点 hello表示控制器 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。6. Handler让具体的Controller执行。7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。12. 最终视图呈现给用户。# 二、控制器和Restful风格 ## 2.1 控制器Controller - 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。- 控制器负责解析用户的请求并将其转换为一个模型。- 在Spring MVC中一个控制器类可以包含多个方法- 在Spring MVC中,对于Controller的配置方式有很多种### 实现Controller接口 Controller是一个接口,在org.springframework.web.servlet.mvc包下,接口中只有一个方法;```java //实现该接口的类获得控制器功能 public interface Controller { //处理请求且返回一个模型与视图对象 ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception; }
测试
新建一个Moudle,springmvc-04-controller 。将刚才的03 拷贝一份, 我们进行操作!
删掉HelloController
mvc的配置文件只留下 视图解析器!
编写一个Controller类,ControllerTest1
1 2 3 4 5 6 7 8 9 10 11 12 public class ControllerTest1 implements Controller { public ModelAndView handleRequest (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg" ,"Test1Controller" ); mv.setViewName("test" ); return mv; } }
编写完毕后,去Spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类
1 <bean name ="/t1" class ="com.kuang.controller.ControllerTest1" />
编写前端test.jsp,注意在WEB-INF/jsp目录下编写,对应我们的视图解析器
1 2 3 4 5 6 7 8 9 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Kuangshen</title> </head> <body> ${msg} </body> </html>
配置Tomcat运行测试,我这里没有项目发布名配置的就是一个 / ,所以请求不用加项目名,OK!
说明:
使用注解@Controller
@Controller注解类型用于声明Spring类的实例是一个控制器(在讲IOC时还提到了另外3个注解);
Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。
1 2 <context:component-scan base-package ="com.kuang.controller" />
增加一个ControllerTest2类,使用注解实现;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Controller public class ControllerTest2 { @RequestMapping("/t2") public String index (Model model) { model.addAttribute("msg" , "ControllerTest2" ); return "test" ; } }
2.2 @RequestMapping @RequestMapping
@RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
为了测试结论更加准确,我们可以加上一个项目名测试 myweb
只注解在方法上面
1 2 3 4 5 6 7 @Controller public class TestController { @RequestMapping("/h1") public String test () { return "test" ; } }
访问路径:http://localhost:8080 / 项目名 / h1
同时注解类与方法
1 2 3 4 5 6 7 8 @Controller @RequestMapping("/admin") public class TestController { @RequestMapping("/h1") public String test () { return "test" ; } }
访问路径:http://localhost:8080 / 项目名/ admin /h1 , 需要先指定类的路径再指定方法的路径;
2.3 RestFul 风格 概念
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
功能
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。
传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
学习测试
在新建一个类 RestFulController
1 2 3 @Controller public class RestFulController { }
在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Controller public class RestFulController { @RequestMapping("/commit/{p1}/{p2}") public String index (@PathVariable int p1, @PathVariable int p2, Model model) { int result = p1+p2; model.addAttribute("msg" , "结果:" +result); return "test" ; } }
我们来测试请求查看下
思考:使用路径变量的好处?
使路径变得更加简洁;
获得参数更加方便,框架会自动进行类型转换。
通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/commit/1/a,则路径与方法不匹配,而不会是参数转换失败。
我们来修改下对应的参数类型,再次测试
1 2 3 4 5 6 7 8 9 10 11 @RequestMapping("/commit/{p1}/{p2}") public String index (@PathVariable int p1, @PathVariable String p2, Model model) { String result = p1+p2; model.addAttribute("msg" , "结果:" +result); return "test" ; }
使用method属性指定请求类型
用于约束请求的类型,可以收窄请求范围。指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等
我们来测试一下:
如果将POST修改为GET则正常了;
1 2 3 4 5 6 @RequestMapping(value = "/hello",method = {RequestMethod.GET}) public String index2 (Model model) { model.addAttribute("msg" , "hello!" ); return "test" ; }
小结:
Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH。
所有的地址栏请求默认都会是 HTTP GET 类型的。
方法级别的注解变体有如下几个:组合注解
1 2 3 4 5 @GetMapping @PostMapping @PutMapping @DeleteMapping @PatchMapping
@GetMapping 是一个组合注解,平时使用的会比较多!
它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式。
三、结果跳转方式 3.1 ModelAndView 设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 .
页面 : {视图解析器前缀} + viewName +{视图解析器后缀}
1 2 3 4 5 6 7 8 <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" id ="internalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/jsp/" /> <property name ="suffix" value =".jsp" /> </bean >
对应的controller类
1 2 3 4 5 6 7 8 9 10 public class ControllerTest1 implements Controller { public ModelAndView handleRequest (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg" ,"ControllerTest1" ); mv.setViewName("test" ); return mv; } }
3.2 ServletAPI 通过设置ServletAPI , 不需要视图解析器 .
1、通过HttpServletResponse进行输出
2、通过HttpServletResponse实现重定向
3、通过HttpServletResponse实现转发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Controller public class ResultGo { @RequestMapping("/result/t1") public void test1 (HttpServletRequest req, HttpServletResponse rsp) throws IOException { rsp.getWriter().println("Hello,Spring BY servlet API" ); } @RequestMapping("/result/t2") public void test2 (HttpServletRequest req, HttpServletResponse rsp) throws IOException { rsp.sendRedirect("/index.jsp" ); } @RequestMapping("/result/t3") public void test3 (HttpServletRequest req, HttpServletResponse rsp) throws Exception { req.setAttribute("msg" ,"/result/t3" ); req.getRequestDispatcher("/WEB-INF/jsp/test.jsp" ).forward(req,rsp); } }
3.3 SpringMVC 通过SpringMVC来实现转发和重定向 - 无需视图解析器;
测试前,需要将视图解析器注释掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Controller public class ResultSpringMVC { @RequestMapping ("/rsm/t1" ) public String test1 ( ) { return "/index.jsp" ; } @RequestMapping ("/rsm/t2" ) public String test2 ( ) { return "forward:/index.jsp" ; } @RequestMapping ("/rsm/t3" ) public String test3 ( ) { return "redirect:/index.jsp" ; } }
通过SpringMVC来实现转发和重定向 - 有视图解析器;
重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
可以重定向到另外一个请求实现 .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Controller public class ResultSpringMVC2 { @RequestMapping ("/rsm2/t1" ) public String test1 ( ) { return "test" ; } @RequestMapping ("/rsm2/t2" ) public String test2 ( ) { return "redirect:/index.jsp" ; } }
四、数据处理 4.1 处理提交数据 1、提交的域名称和处理方法的参数名一致
提交数据 : http://localhost:8080/hello?name=kuangshen
处理方法 :
1 2 3 4 5 @RequestMapping ("/hello" )public String hello (String name ) { System.out.println(name); return "hello" ; }
后台输出 : kuangshen
2、提交的域名称和处理方法的参数名不一致
提交数据 : http://localhost:8080/hello?username=kuangshen
处理方法 :
1 2 3 4 5 6 @RequestMapping ("/hello" )public String hello (@RequestParam ("username" ) String name ) { System.out.println(name); return "hello" ; }
后台输出 : kuangshen
3、提交的是一个对象
要求提交的表单域和对象的属性名一致 , 参数使用对象即可
1、实体类
1 2 3 4 5 6 7 8 public class User { private int id; private String name; private int age; }
2、提交数据 : http://localhost:8080/mvc04/user?name=kuangshen&id=1&age=15
3、处理方法 :
1 2 3 4 5 @RequestMapping("/user")public String user (User user ){ System .out .println(user ); return "hello"; }
后台输出 : User { id=1, name=’kuangshen’, age=15 }
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
4.2 数据显示到前端 第一种 : 通过ModelAndView
我们前面一直都是如此 . 就不过多解释
1 2 3 4 5 6 7 8 9 10 public class ControllerTest1 implements Controller { public ModelAndView handleRequest (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg" ,"ControllerTest1" ); mv.setViewName("test" ); return mv; } }
第二种 : 通过ModelMap
ModelMap
1 2 3 4 5 6 7 8 @RequestMapping ("/hello" )public String hello (@RequestParam ("username" ) String name, ModelMap model ) { model.addAttribute("name" ,name); System.out.println(name); return "hello" ; }
第三种 : 通过Model
Model
1 2 3 4 5 6 7 8 @RequestMapping ("/ct2/hello" )public String hello (@RequestParam ("username" ) String name, Model model ) { model.addAttribute("msg" ,name); System.out.println(name); return "test" ; }
4.3 对比 就对于新手而言简单来说使用区别就是:
1 2 3 4 5 Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解; ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性; ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
当然更多的以后开发考虑的更多的是性能和优化,就不能单单仅限于此的了解。
请使用80%的时间打好扎实的基础,剩下18%的时间研究框架,2%的时间去学点英文,框架的官方文档永远是最好的教程。
4.4 乱码问题 测试步骤:
1、我们可以在首页编写一个提交的表单
1 2 3 4 <form action ="/e/t" method ="post" > <input type ="text" name ="name" > <input type ="submit" > </form >
2、后台编写对应的处理类
1 2 3 4 5 6 7 8 @Controller public class Encoding { @RequestMapping("/e/t") public String test (Model model,String name) { model.addAttribute("msg" ,name); return "test" ; } }
3、输入中文测试,发现乱码
不得不说,乱码问题是在我们开发中十分常见的问题,也是让我们程序猿比较头大的问题!
以前乱码问题通过过滤器解决 , 而SpringMVC给我们提供了一个过滤器 , 可以在web.xml中配置 .
修改了xml文件需要重启服务器!
1 2 3 4 5 6 7 8 9 10 11 12 <filter > <filter-name > encoding</filter-name > <filter-class > org.springframework.web.filter.CharacterEncodingFilter</filter-class > <init-param > <param-name > encoding</param-name > <param-value > utf-8</param-value > </init-param > </filter > <filter-mapping > <filter-name > encoding</filter-name > <url-pattern > /*</url-pattern > </filter-mapping >
但是我们发现 , 有些极端情况下.这个过滤器对get的支持不好 .
处理方法 :
1、修改tomcat配置文件 :设置编码!
1 2 3 <Connector URIEncoding ="utf-8" port ="8080" protocol ="HTTP/1.1" connectionTimeout ="20000" redirectPort ="8443" />
2、自定义过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 package com.kuang.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.util.Map;public class GenericEncodingFilter implements Filter { @Override public void destroy () { } @Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse myResponse=(HttpServletResponse) response; myResponse.setContentType("text/html;charset=UTF-8" ); HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletRequest myrequest = new MyRequest(httpServletRequest); chain.doFilter(myrequest, response); } @Override public void init (FilterConfig filterConfig) throws ServletException { } }class MyRequest extends HttpServletRequestWrapper { private HttpServletRequest request; private boolean hasEncode; public MyRequest (HttpServletRequest request) { super (request); this .request = request; } @Override public Map getParameterMap () { String method = request.getMethod(); if (method.equalsIgnoreCase("post" )) { try { request.setCharacterEncoding("utf-8" ); return request.getParameterMap(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else if (method.equalsIgnoreCase("get" )) { Map<String, String[]> parameterMap = request.getParameterMap(); if (!hasEncode) { for (String parameterName : parameterMap.keySet()) { String[] values = parameterMap.get(parameterName); if (values != null ) { for (int i = 0 ; i < values.length; i++) { try { values[i] = new String(values[i] .getBytes("ISO-8859-1" ), "utf-8" ); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } } hasEncode = true ; } return parameterMap; } return super .getParameterMap(); } @Override public String getParameter (String name) { Map<String, String[]> parameterMap = getParameterMap(); String[] values = parameterMap.get(name); if (values == null ) { return null ; } return values[0 ]; } @Override public String[] getParameterValues(String name) { Map<String, String[]> parameterMap = getParameterMap(); String[] values = parameterMap.get(name); return values; } }
这个也是在网上找的一些大神写的,一般情况下,SpringMVC默认的乱码处理就已经能够很好的解决了!
然后在web.xml中配置这个过滤器即可!
乱码问题,需要平时多注意,在尽可能能设置编码的地方,都设置为统一编码 UTF-8!
五、json交互处理
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广泛。
采用完全独立于编程语言的文本格式 来存储和表示数据。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:
对象表示为键值对,数据由逗号分隔
花括号保存对象
方括号保存数组
JSON 键值对 是用来保存 JavaScript 对象的一种方式,和 JavaScript 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:
1 2 3 {"name" : "QinJiang" } {"age" : "3" } {"sex" : "男" }
很多人搞不清楚 JSON 和 JavaScript 对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
1 2 var obj = {a: 'Hello' , b: 'World' }; var json = '{"a": "Hello", "b": "World"}' ;
JSON 和 JavaScript 对象互转
要实现从JSON字符串转换为JavaScript 对象,使用 JSON.parse() 方法:
1 2 var obj = JSON.parse('{"a": "Hello", "b": "World"}' );
要实现从JavaScript 对象转换为JSON字符串,使用 JSON.stringify() 方法:
1 2 var json = JSON.stringify({a: 'Hello' , b: 'World' });
代码测试
1、新建一个module ,springmvc-05-json , 添加web的支持
2、在web目录下新建一个 json-1.html , 编写测试内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > JSON_秦疆</title > </head > <body > <script type ="text/javascript" > var user = { name:"秦疆" , age:3, sex:"男" }; var str = JSON .stringify(user); console .log(str); var user2 = JSON .parse(str); console .log(user2.age,user2.name,user2.sex); </script > </body > </html >
3、在IDEA中使用浏览器打开,查看控制台输出!
5.1 Controller返回JSON数据 Jackson应该是目前比较好的json解析工具了
当然工具不止这一个,比如还有阿里巴巴的 fastjson 等等。
我们这里使用Jackson,使用它需要导入它的jar包;
1 2 3 4 5 6 <dependency > <groupId > com.fasterxml.jackson.core</groupId > <artifactId > jackson-databind</artifactId > <version > 2.9.8</version > </dependency >
配置SpringMVC需要的配置
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" > <servlet > <servlet-name > SpringMVC</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc-servlet.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > SpringMVC</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > <filter > <filter-name > encoding</filter-name > <filter-class > org.springframework.web.filter.CharacterEncodingFilter</filter-class > <init-param > <param-name > encoding</param-name > <param-value > utf-8</param-value > </init-param > </filter > <filter-mapping > <filter-name > encoding</filter-name > <url-pattern > /</url-pattern > </filter-mapping > </web-app >
springmvc-servlet.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:mvc ="http://www.springframework.org/schema/mvc" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd" > <context:component-scan base-package ="com.kuang.controller" /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" id ="internalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/jsp/" /> <property name ="suffix" value =".jsp" /> </bean > </beans >
我们随便编写一个User的实体类,然后我们去编写我们的测试Controller;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.kuang.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class User { private String name; private int age; private String sex; }
这里我们需要两个新东西,一个是@ResponseBody,一个是ObjectMapper对象,我们看下具体的用法
编写一个Controller;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Controller public class UserController { @RequestMapping("/json1") @ResponseBody public String json1 () throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); User user = new User("秦疆1号" , 3 , "男" ); String str = mapper.writeValueAsString(user); return str; } }
配置Tomcat , 启动测试一下!
【注意:使用json记得处理乱码问题】
5.2 代码优化 乱码统一解决
上一种方法比较麻烦,如果项目中有许多请求则每一个都要添加,可以通过Spring配置统一指定,这样就不用每次都去处理了!
我们可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter转换配置!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <mvc:annotation-driven > <mvc:message-converters register-defaults ="true" > <bean class ="org.springframework.http.converter.StringHttpMessageConverter" > <constructor-arg value ="UTF-8" /> </bean > <bean class ="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" > <property name ="objectMapper" > <bean class ="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" > <property name ="failOnEmptyBeans" value ="false" /> </bean > </property > </bean > </mvc:message-converters > </mvc:annotation-driven >
返回json字符串统一解决
在类上直接使用 @RestController ,这样子,里面所有的方法都只会返回 json 字符串了,不用再每一个都添加@ResponseBody !我们在前后端分离开发中,一般都使用 @RestController ,十分便捷!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @RestController public class UserController { @RequestMapping(value = "/json1") public String json1 () throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); User user = new User("秦疆1号" , 3 , "男" ); String str = mapper.writeValueAsString(user); return str; } }
启动tomcat测试,结果都正常输出!
5.3 测试集合输出 增加一个新的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @RequestMapping("/json2") public String json2 () throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); User user1 = new User("秦疆1号" , 3 , "男" ); User user2 = new User("秦疆2号" , 3 , "男" ); User user3 = new User("秦疆3号" , 3 , "男" ); User user4 = new User("秦疆4号" , 3 , "男" ); List<User> list = new ArrayList<User>(); list.add(user1); list.add(user2); list.add(user3); list.add(user4); String str = mapper.writeValueAsString(list); return str; }
运行结果 : 十分完美,没有任何问题!
5.4 输出时间对象 增加一个新的方法
1 2 3 4 5 6 7 8 9 10 11 @RequestMapping("/json3") public String json3 () throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); Date date = new Date(); String str = mapper.writeValueAsString(date); return str; }
运行结果 :
默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数!
Jackson 默认是会把时间转成timestamps形式
解决方案:取消timestamps形式 , 自定义时间格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @RequestMapping("/json4") public String json4 () throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false ); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" ); mapper.setDateFormat(sdf); Date date = new Date(); String str = mapper.writeValueAsString(date); return str; }
运行结果 : 成功的输出了时间!
5.5 抽取为工具类 如果要经常使用的话,这样是比较麻烦的,我们可以将这些代码封装到一个工具类中;我们去编写下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.kuang.utils;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;import java.text.SimpleDateFormat;public class JsonUtils { public static String getJson (Object object) { return getJson(object,"yyyy-MM-dd HH:mm:ss" ); } public static String getJson (Object object,String dateFormat) { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false ); SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); mapper.setDateFormat(sdf); try { return mapper.writeValueAsString(object); } catch (JsonProcessingException e) { e.printStackTrace(); } return null ; } }
我们使用工具类,代码就更加简洁了!
1 2 3 4 5 6 @RequestMapping("/json5") public String json5 () throws JsonProcessingException { Date date = new Date(); String json = JsonUtils.getJson(date); return json; }
大功告成!完美!
5.6 FastJson fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是一样的。
fastjson 的 pom依赖!
1 2 3 4 5 <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.60</version > </dependency >
fastjson 三个主要的类:
JSONObject 代表 json 对象
JSONObject实现了Map接口, 猜想 JSONObject底层操作是由Map实现的。
JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取”键:值”对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。
JSONArray 代表 json 对象数组
JSON代表 JSONObject和JSONArray的转化
JSON类源码分析与使用
仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。
代码测试,我们新建一个FastJsonDemo 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.kuang.controller;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.kuang.pojo.User;import java.util.ArrayList;import java.util.List;public class FastJsonDemo { public static void main (String[] args) { User user1 = new User("秦疆1号" , 3 , "男" ); User user2 = new User("秦疆2号" , 3 , "男" ); User user3 = new User("秦疆3号" , 3 , "男" ); User user4 = new User("秦疆4号" , 3 , "男" ); List<User> list = new ArrayList<User>(); list.add(user1); list.add(user2); list.add(user3); list.add(user4); System.out.println("*******Java对象 转 JSON字符串*******" ); String str1 = JSON.toJSONString(list); System.out.println("JSON.toJSONString(list)==>" +str1); String str2 = JSON.toJSONString(user1); System.out.println("JSON.toJSONString(user1)==>" +str2); System.out.println("\n****** JSON字符串 转 Java对象*******" ); User jp_user1=JSON.parseObject(str2,User.class); System.out.println("JSON.parseObject(str2,User.class)==>" +jp_user1); System.out.println("\n****** Java对象 转 JSON对象 ******" ); JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2); System.out.println("(JSONObject) JSON.toJSON(user2)==>" +jsonObject1.getString("name" )); System.out.println("\n****** JSON对象 转 Java对象 ******" ); User to_java_user = JSON.toJavaObject(jsonObject1, User.class); System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>" +to_java_user); } }
这种工具类,我们只需要掌握使用就好了,在使用的时候在根据具体的业务去找对应的实现。和以前的commons-io那种工具包一样,拿来用就好了!