前言
Spring框架提供了构建Web应用程序的全功能MVC模块,而且它分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离使其更容易被定制。Spring的MVC框架主要由下面几部分组成:DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图。本文主要是对学习过程中的知识进行归纳总结,由于框架中很多代码是可以复用的,方便以后的学习。
一、SpringMVC的执行过程
1、当用户通过浏览器输入url 时,会发送一个http请求给web服务器,web服务器收到http请求后,会对该请求进行解析,如果匹配到了DispatcherServlet 的请求映射路径(在web.xml中指定,代码见步骤二),web容器会将该请求转交给DispatcherServlet。
2、 DispatcherServlet 收到请求之后,会调用处理器映射器HandlerMapping。
3、处理器映射器根据请求url 找到具体的处理器Handler,生成处理器对象及处理器拦截器(如有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet 调用HandlerAdapter处理器适配器,执行HandlerAdapter的一系列操作,包括:数据验证等。
5、 HandlerAdapter 经过适配后调用具体的处理器(Controller,也叫后端控制器或者页面控制器)。
6、 Controller 执行完成后返回ModelAndView结果。
7、HandlerAdapter 再将 Controller 执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet 将执行结果ModelAndView传给ViewReslover视图解析器。
9、ViewReslover 解析后返回具体View。
10、DispatcherServlet 根据View进行视图渲染(即将模型数据model填充至视图中)。
11、DispatcherServlet 响应用户。
二、导入SpringMVC的相关pom依赖
1、导入pom依赖,建议建立一个父模块,然后在其下面绑定许多子模块,就无需每次都导入依赖
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.15</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies>
2、在build中配置resources,来防止我们资源导出失败的问题
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
三、第一个SpringMVC项目
1、配置web.xml文件
1)在web.xml文件中注册DispatcherServlet,DispatcherServlet是SpringMVC的核心,又被称为请求分发器或者前端控制器。使用DispatcherServlet时,需要绑定springmvc配置文件。启动级别越小,启动得越早。
<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> <!--启动级别为1,和服务器一起启动--> <load-on-startup>1</load-on-startup> </servlet>
2)配置好了servlet,一定不要忘记配置它的映射,即servlet-mapping。映射方式通常有两种,“/” 和“/*”。“/”匹配除jsp页面的所有请求(代表本级),不会匹配到.jsp,“/*”匹配所有的请求(代表下一级),包括jsp页面请求(会匹配到*.jsp,而且可能会出现404错误)。
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
2、 配置SpringMVC配置文件
<?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"> </beans>
1)添加处理器映射器,BeanNameUrlHandlerMapping实际用的少
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
2)添加处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
3)添加视图解析器,有许多模板引擎,包括Thymeleaf、Freemarker.....
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean>
4)编写好业务代码后(步骤3),记得注册bean,name对应请求路径,class对应处理请求的类
<bean name="/hello" class="com.controller.HelloController"/>
3、基本配置完成后,进行业务操作
在SpringMVC中,对于Controller的实现有很多种,通常有实现Controller接口和注解定义两种方式,推荐使用注解定义的方法。通过SpringMVC的执行过程,我们知道Controller控制器负责解析用户的请求并将其转换为一个模型,最后将结果返回给视图解析器(将mv返回至2.3进行解析)。该方法的缺点很明显,一个控制器中只能有一个方法,如果需要使用到多个方法就需要定义多个Controller,定义的方式比较繁琐。
package com.controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //只要实现了Controller接口的类,就说明这是一个控制器了 public class HelloController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = new ModelAndView(); //业务代码 String result = "Hello,SpringMVC!"; mv.addObject("msg", result);//添加数据 //进行视图跳转 mv.setViewName("hello");//设置视图的名字为:hello return mv; } }
4、要跳转的jsp页面
该页面放于/WEB-INF/jsp包下,用以显示ModelandView存放的数据以及我们正常的页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html>
5、部署项目,查看运行结果
四、使用注解方式实现SpringMVC
1、配置web.xml文件
该配置和不用注解的方式一样
2、配置SpringMVC配置文件
1)配置头文件
<?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">
2)自动扫描包的功能,让指定包下(这里是com.controller包)的注解生效,由Spring的IOC容器统一管理
<context:component-scan base-package="com.controller"/>
3)过滤掉HTML,JS ,CSS , 图片 , 视频等静态资源
<mvc:default-servlet-handler/>
4)annotation-driven配置可以帮助我们自动完成处理映射器和处理器适配器的注入
<mvc:annotation-driven/>
5)视图解析器跟无注解的一样,以后开展项目时,无需改动它。从下面代码中可以看出我们把所有的视图文件都放置于/WEB-INF/x/中,这是出于安全性的考虑,因为用户不能够直接访问到该文件夹下的配置资源。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 后缀 --> <property name="suffix" value=".jsp"/> </bean>
3、编写一个Java控制类(HelloController.java)
@Controller是为了让Spring IOC容器初始化时自动扫描到指定包;@RequestMapping是为了映射请求路径;方法中声明Model类型的参数是为了把Action中的数据带到视图中;方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
package com.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller /* 代表这个类会被Spring接管,被注解的类中的所有方法,如果返回值是String, 并且有具体页面可以跳转时,那么就可能被视图解析器解析. */ public class HelloController { @RequestMapping("/hello") public String hello(Model model){ //封装数据 model.addAttribute("msg","hello,SpringMVCAnnotation"); return "hello"; } }
4、要跳转的jsp页面
解析“msg”,显示目标界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html>
5、部署项目,查看运行结果
五、乱码过滤器
从Tomcat8.0开始,get请求中的中文参数不需要特殊处理,而使用post的提交方式,有时候还是会出现乱码问题。解决乱码问题有多种方法,第一种是自定义过滤器,第二种是修改Tomcat的配置文件,第三种是采用SpringMVC自带的过滤器。
1、自定义过滤器
创建一个EncodingFilter类,实现Filter接口并重写其中的方法,设置编码方式为UTF-8
package com.filter; import javax.servlet.*; import java.io.IOException; public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
在web.xml文件中配置过滤便签及过滤映射标签
<filter> <filter-name>encoding</filter-name> <filter-class>com.filter.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2、 修改Tomcat配置文件
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
3、使用SpringMVC自带的乱码过滤器(建议使用)
在web.xml中配置,添加之后,重启Tomcat服务器
<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>
注:最后附上Maven Repository地址,方便导入相关依赖jar包:https://mvnrepository.com/