- SpringMVC概述
- 在我们之前WEB层使用的是servlet技术,但是每一个servlet都需要进行一个配置,太过于复杂,SpringMVC就能够解决这个问题;
- SpringMVC是一个基于MVC模式的WEB/表现层框架,它解决WEB开发中常见的问题:参数接收、文件上传/下载、表单验证、国际化等等;
- SpringMVC作为Spring框架一个非常重要的功能模块,可以与Spring无缝集成,提高开发效率;
- Spring是一个轻量级的Java 开发框架,为了解决企业应用开发的复杂性而创建。SpringMVC以Spring框架为核心,为应用程序中的Web层(表现层)提出的一套优秀的解决方案;
- 目前很多公司都使用SpringMVC,90%的招聘单位要求熟悉使用SpringMVC;
注意:SpringMvc的功能就是之前Servlet的功能,可以理解为使用SpringMVC代替了Servlet;
- SpringMVC入门
-
jar包管理
-
SpringMVC是建立在Spring基础上的。所以使用SpringMVC必须先保证你的项目拥有Spring的运行环境;
-
使用框架的第一步需要框架的官方网站下载框架相关的文件,而SpringMVC无需单独下载,因为SpringMVC是作为Spring中的一个模块存在,所以我们只需要下载Spring即可;
-
SpringMVC需要的jar包:
- spring-webmvc-4.1.2.RELEASE.jar -- SpringMVC核心包
- spring-web-4.1.2.RELEASE.jar -- Spring对Web项目项目的支持
-
加入相关Spring的jar包
- com.springsource.org.apache.commons.logging-1.1.1.jar - spring-beans-4.1.2.RELEASE.jar - spring-context-4.1.2.RELEASE.jar - spring-core-4.1.2.RELEASE.jar - spring-expression-4.1.2.RELEASE.jar - spring-aop-4.1.2.RELEASE.jar -- Spring测试需要导入此包 - servlet-api.jar -- SpringMVC底层还是使用了servlet,所以需要servletjar包 复制代码注意:1. spring orm、jdbc、tx相关jar根据项目使用自行添加; 2. 不要使用spring.3的jar和4.x的jar文件混用;
-
SpringMVC核心控制器
- 核心控制器:用于Web层核心功能的处理以及在所有控制器执行之前,所有的WebMvc框架都采用了这种方式,在SpringMVC中使用的是DispatcherServlet为核心控制器. DispatcherServlet核心控制器会拦截匹配的请求,把拦截下来的请求,依据相应的规则分发到目标Controller来处理;
-
-
配置核心控制器
- webmvc框架的心脏就是核心控制器,负责所有请求的公共功能,然后在分发给具体的控制器(我们编写的控制器),完成业务逻辑,响应视图;
- 核心控制器其实就是一个Servlet,只不过这个Servlet是由SpringMVC框架提供的,不需要自己写,只需要配置,交给容器去管理。在web.xml配置核心控制器(容器启动时就创建sevlet实例对象,并加载classpath下的一个名为spring-mvc.xml文件);
<servlet>
<!-- 给核心控制器配置起一个唯一的名称 -->
<servlet-name>dispatcherServlet</servlet-name>
<!-- 核心控制器的全限定名 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- init-param标签的位置必须在load-on-startup上面 -->
<!-- 告诉SpringMVC去哪里找核心配置文件 -->
<init-param>
<!-- contextConfigLocation 固定写法,不能改变 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-MVC.xml</param-value>
</init-param>
<!-- 这个的意思是指定核心控制器的加载时机,参数值为 1~10 数字越低加载时机越高 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!-- 根据名称引入核心控制器 -->
<servlet-name>dispatcherServlet</servlet-name>
<!-- url-pattern参数值,有两种写法
1./ 拦截所有请求
2. *.do
*: 匹配所有的意思
.do: 以.do结尾的所有请求
3./* 拦截所有请求
-->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
复制代码
-
准备SpringMVC核心配置文件
- SpringMVC是Spring的一个模块,它的配置文件和Spring的配置差不多,复制一份applicationContext.xml修改为spring-mvc.xml;
<?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>
复制代码
-
编写请求处理器Controller
-
三种方式:第一种
-
我们以前使用servlet的时候,我们写的是一个HelloServlet控制器类,然后实现的是Servlet,现在我们使用SpringMVC就实现一个Controller
-
编写HelloController
- handleRequest方法的两个参数与我们以前的servlet中service方法一样,request和response对象,我们可以使用这个两个对象完成一次请求的所有工作,比如你可以使用request接受参数,或者使用response重定向等等,注意方法除了返回值以外还有一个返回值ModelAndView;
- ModelAndView是SpringMVC控制器中特有一个对象,描述一次请求响应的数据(Model)和 视图(View);
-
package cn.itsource.springmvc_01;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
// 以前我们写第一个HelloServlet,是实现的Servlet
// 现在我们写第一个HelloController, 我们就实现一个Controller 接口就可以了
// 第一种实现方式
public class HelloController01 implements Controller{
/**
* ModelAndView: 模型和视图
* Model:后台封装数据的,方便前端获取
* View:定义控制器返回的路径
*/
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
// 创建一个ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 以前servlet传递参数的写法
// req.setAttribute("msg", "你好,控制器!!!");
// 现在的用法, 将参数封装到作用域中
modelAndView.addObject("msg", "你好,控制器!!!");
// 告诉控制器,跳转的路径
modelAndView.setViewName("/WEB-INF/views/index.jsp");
return modelAndView;
}
}
复制代码
-
编写页面,展示数据
- 在WEB-INF下创建views文件夹,然后创建index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
${msg}
</body>
</html>
复制代码
-
配置控制器
- SpringMVC是基于Spring,Spring中的核心就是Ioc容器,而Ioc容器中最重要的成员就是bean,SpringMVC中的控制器也是一个一个bean;
<?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"
>
<!-- id在以前学习spring的时候是我们全局唯一的名称,在引入SpringMVC之后,id就是我们往外面暴露的请求路径 -->
<!-- class 就是控制器的全限定名 -->
<bean id="/hello1.do" class="cn.itsource.springmvc_01.HelloController01"></bean>
</beans>
复制代码
-
访问控制器
注意:因为我们设置的拦截是*.do,并且暴露的连接请求是hello1.do,所以我们访问hello1.do
- 查看效果,展示我们在ModelAndView中设置的值
-
三种方式:第二种
- 实现HttpRequestHandler接口
- 除了实现Controller接口的这种方式,我们还可以使用第二种
package cn.itsource.springmvc_01;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
// 第二种实现方式
public class HelloController02 implements HttpRequestHandler{
@Override
public void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("msg", "第二种方式!!!");
req.getRequestDispatcher("/WEB-INF/views/index.jsp").forward(req, resp);
}
}
复制代码
- 配置spring-mvc.xml
<?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"
>
<!-- id在以前学习spring的时候是我们全局唯一的名称,在引入SpringMVC之后,id就是我们往外面暴露的请求路径 -->
<!-- class 就是控制器的全限定名 -->
<bean id="/hello2.do" class="cn.itsource.springmvc_01.HelloWordController02"></bean>
</beans>
复制代码
-
访问控制器
- http://localhost/hello2.do
- 查看效果,展示我们在ModelAndView中设置的值
-
三种方式:第三种
- 前面两种方式,都与我们的Servlet方式十分的相似,并没有改变我们的配置复杂的问题,如果SpringMVC只能达到这种程度,我们完全没必要学习他,所以我们来看SpringMVC推荐的方式,也是我们最常用的方式!
- 创建控制器
package cn.itsource.springmvc_01;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
// 第三种实现方式 在类上加上controller注解
// 标识这个类是一个控制器
@Controller
public class HelloController03 {
// 就是对外暴露的资源路径
@RequestMapping("/hello3")
public ModelAndView hello3() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", "第三种实现方式!!!");
modelAndView.setViewName("/WEB-INF/views/index.jsp");
return modelAndView;
}
}
复制代码
- 因为我们使用了注解,所以我们需要在配置文件中添加注解扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
>
<!-- id在以前学习spring的时候是我们全局唯一的名称,在引入SpringMVC之后,id就是我们往外面暴露的请求路径 -->
<!-- class 就是控制器的全限定名 -->
<bean id="/hello1.do" class="cn.itsource.springmvc_01.HelloWordController01"></bean>
<bean id="/hello2.do" class="cn.itsource.springmvc_01.HelloWordController02"></bean>
<!-- 这个就是配置哪个包下面的注解需要去扫描 -->
<context:component-scan base-package="cn.itsource"/>
</beans>
复制代码
-
访问控制器
- http://localhost/hello3.do
- 查看效果,展示我们在ModelAndView中设置的值
- 前端控制器 url-pattern 配置
-
url-pattern就是设置我们拦截方式的,他有三种拦截方式
-
第一种:*.do 不推荐使用
- 拦截所有以.do结尾的请求
- 问题:这种请求方式要求你的请求路径必须以.do的方式才能访问我的核心控制器
-
第二种:/* 不推荐使用
- 拦截所有请求
- 问题:这种请求方式会在我们跳转jsp页面的时候也拦截,会导致我们在访问控制器之后跳转页面时404
-
第三种:/ 推荐使用
-
拦截所有请求,并且不会拦截页面资源,还支持restful风格
-
问题:如果拦截路径是 / ,他会把tomcat自带的servlet给覆盖掉,被覆盖的servlet就是别人专门处理静态资源的servlet,所以就会导致我们无法访问静态资源
-
解决方案:springMVC给我们提供了解决访问,所以我们需要在springMVC核心控制器中加入以下配置
- 引入mvc命名空间
- 加入 <mvc:default-servlet-handler /> 表示静态资源放行
- 加入静态资源放行,会导致springMVC的注解失效,也就是@RequestMapping("/hello3"),所以需要开启springMVC注解支持
-
-
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"
>
<!-- id在以前学习spring的时候是我们全局唯一的名称,在引入SpringMVC之后,id就是我们往外面暴露的请求路径 -->
<!-- class 就是控制器的全限定名 -->
<bean id="/hello1.do" class="cn.itsource.springmvc_01.HelloWordController01"></bean>
<bean id="/hello2.do" class="cn.itsource.springmvc_01.HelloWordController02"></bean>
<!-- 这个就是配置哪个包下面的注解需要去扫描 -->
<context:component-scan base-package="cn.itsource"/>
<!-- 静态资源放行 -->
<mvc:default-servlet-handler/>
<!-- 开启对springMVC注解的支持 -->
<mvc:annotation-driven/>
</beans>
复制代码
注意:虽然配置 / 也会有一些问题,但是springMVC已经给我们提供了解决方案,所以我们推荐使用 / 方式配置拦截,这也是现在最流行的使用方式
- restful风格
- REST(英文:Representational State Transfer,简称REST)Rest是web服务的一种架构风格,一种设计风格,是一种思想;同时Rest不是针对某一种编程语言的。
- 以往我们写接口访问路径,我们会以路径区别我们具体访问的那个方法
http://localhost:8080/admin/getUser (查询用户)
http://localhost:8080/admin/addUser (新增用户)
http://localhost:8080/admin/updateUser (更新用户)
http://localhost:8080/admin/deleteUser (删除用户)
- Rest架构:一个请求路径对应多个方法,以请求方式区分此请求到底进那个方法
GET http://localhost:8080/admin/user (查询用户)
POST http://localhost:8080/admin/user (新增用户)
PUT http://localhost:8080/admin/user (更新用户)
DELETE http://localhost:8080/admin/user (删除用户)
- 接收参数的五种方式
- 以前我们在使用Servlet的时候,我们接收参数的方式是通过HttpServletRequest获取,在SpringMVC中有五种方式获取
- 第一种:
/**
* SpringMVC 接收参数方式一,通过HttpServletRequest获取(不推荐)
* @param username
* @param age
*/
@RequestMapping("/param/03")
public void param03(HttpServletRequest request) {
System.out.println(request.getParameter("username"));
System.out.println(request.getParameter("password"));
}
复制代码
- 第二种:通过形参直接接收,SpringMVC可以自动将值给我们注入到形参中,但是前后端的形参类型,形参名称要一致
/**
* SpringMVC 接收参数方式二(推荐使用)
* @param username
* @param age
*/
@RequestMapping("/param/01")
public void param01(String username, Integer age) {
System.out.println("username = " + username);
System.out.println("age = " + age);
}
复制代码
- 第三种:如果形参过多,那么我们可以封装一个实体类,通过实体类接收
/**
* SpringMVC 接收参数方式三(推荐使用)
* @param username
* @param age
*/
@RequestMapping("/param/02")
public void param02(User user) {
System.out.println("user = " + user);
}
复制代码
- 第四种:Restful风格,参数作为访问路径的时候
/**
* SpringMVC 接收参数方式四(推荐使用 Restful风格,将参数作为路径,这时候就要加上注解 @PathVariable(路径的参数对应的形参))
* @param username
* @param age
*/
@RequestMapping("/param/04/{username}/{password}")
public void param04(@PathVariable("username")String username,@PathVariable("password")Integer password) {
System.out.println(username);
System.out.println(password);
}
复制代码
- 第五种:其实跟第二种很相似,但是区别在于如果前后端的参数名称不一致的时候如何处理
/**
* SpringMVC 接收参数方式五(在前后端参数不一致时,可以使用@RequestParam("name") 指定前端的参数名称注入到后端那个参数里面)
* @param username
* @param age
*/
@RequestMapping("/param/05")
public void param05(@RequestParam("name")String username,@RequestParam("pword") Integer password) {
System.out.println(username);
System.out.println(password);
}
复制代码
- URL地址的抽取
-
在刚才我们学习五种参数类型时,大家可以发现我们每个请求前面都有一个param,那么既然我每个请求路径都需要一个param,我能不能抽取出来呢?
- 解决方案:在SrpringMVC中,我们在方法上是可以加上 @RequestMapping(/公共路径) 设置我们该控制器的公共地址的
package cn.itsource.springmvc_01;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
// 一级路径可以抽取出来,放在方法上面,还是使用@RequestMapping("") 指定该类的公共路径
@RequestMapping("/param2")
public class ParamController {
/**
* SpringMVC 接收参数方式一(推荐使用)
* @param username
* @param age
*/
@RequestMapping("/01")
public void param01(String username, Integer age) {
System.out.println("username = " + username);
System.out.println("age = " + age);
}
/**
* SpringMVC 接收参数方式二(推荐使用)
* @param username
* @param age
*/
@RequestMapping("/02")
public void param02(User user) {
System.out.println("user = " + user);
}
/**
* SpringMVC 接收参数方式三(不推荐)
* @param username
* @param age
*/
@RequestMapping("/03")
public void param03(HttpServletRequest request) {
System.out.println(request.getParameter("username"));
System.out.println(request.getParameter("password"));
}
/**
* SpringMVC 接收参数方式四(推荐使用 Restful风格,将参数作为路径,这时候就要加上注解 @PathVariable(路径的参数对应的形参))
* @param username
* @param age
*/
@RequestMapping("/04/{username}/{password}")
public void param04(@PathVariable("username")String username,@PathVariable("password")Integer password) {
System.out.println(username);
System.out.println(password);
}
/**
* SpringMVC 接收参数方式五(在前后端参数不一致时,可以使用@RequestParam("name") 指定前端的参数名称注入到后端那个参数里面)
* @param username
* @param age
*/
@RequestMapping("/05")
public void param05(@RequestParam("name")String username,@RequestParam("pword") Integer password) {
System.out.println(username);
System.out.println(password);
}
}
复制代码
注意:路径的前面的 / 可写可不写,因为SpringMVC会自动帮我们加上。但是规范写法我们还是写上
- 向页面传值的三种方式
- 我们以前在Servlet时期,传递值到前端是通过我们的HttpServletRequest,SpringMVC可以有三种传递值得方式
- 第一种
/**
* 方式一:就是以前我们servlet的那种方式
* @return
*/
@RequestMapping("/transfer03")
public String transfer03(HttpServletRequest request) {
request.setAttribute("msg", "hello word 第三种方式!!!");
// 指定跳转路径
return "/WEB-INF/views/index.jsp";
}
复制代码
- 第二种
/**
* 方式二:使用Model进行数据的封装
* @return
*/
@RequestMapping("/transfer02")
public String transfer02(Model model) {
// 将数据封装到Model中
model.addAttribute("msg", "hello word 第二种方式!!!");
// 指定跳转路径
return "/WEB-INF/views/index.jsp";
}
复制代码
- 第三种
/**
* 方式三:使用ModelAndView进行数据的封装,路径的跳转
* @return
*/
@RequestMapping("/transfer01")
public ModelAndView transfer01() {
// 初始化一个ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 封装数据到ModelAndView
modelAndView.addObject("msg", "hello word 第一种方式!!!");
// 指定跳转的路径
modelAndView.setViewName("/WEB-INF/views/index.jsp");
// 返回ModelAndView
return modelAndView;
}
复制代码
注意:三种方式没有好坏之分,都可以使用
- SpringMVC视图解析器
-
通过刚才的代码我们发现,在返回页面时,页面的路径前面都是相同的,并且我们的页面类型也都是jsp,那么我们能否抽取公共的页面路径,并且自动给我们加上.jsp后缀呢?
- SpringMvc提供了InternalResourceViewResolver,用于统一管理响应视图的匹配;
- 使用之后,响应的数据就会交给这个视图解析器进行解析,然后转向响应的页面,控制器中响应视图写法就比较简单了;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"
>
<!-- id在以前学习spring的时候是我们全局唯一的名称,在引入SpringMVC之后,id就是我们往外面暴露的请求路径 -->
<!-- class 就是控制器的全限定名 -->
<bean id="/hello1.do" class="cn.itsource.springmvc_01.HelloWordController01"></bean>
<bean id="/hello2.do" class="cn.itsource.springmvc_01.HelloWordController02"></bean>
<!-- 这个就是配置哪个包下面的注解需要去扫描 -->
<context:component-scan base-package="cn.itsource"/>
<!-- 静态资源放行 -->
<mvc:default-servlet-handler/>
<!-- 开启对springMVC注解的支持 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 在我的访问页面的路径前加上我的公共路径 -->
<property name="Prefix" value="/WEB-INF/views/"></property>
<!-- 在我的访问页面名称后面加上.jsp -->
<property name="Suffix" value = ".jsp"></property>
</bean>
</beans>
复制代码
- SpringMVC跳转页面的四种方式
- 刚才我们配置了视图解析器,以后我们的页面返回路径就会自动给我们加上前缀和后缀,那么如果我的前缀和后缀不是配置的视图解析器,我应该如何跳转呢?
package cn.itsource.springmvc_01;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class JumpController {
/**
* SpringMVC跳转的方式一:如果公共的路径下面还有路径,那么我们在跳转的时候加上前面的路径即可
* @return
*/
@RequestMapping("/list")
public String list() {
return "/student/list";
}
/**
* SpringMVC跳转的方式二:如果跳转的页面后缀不是你指定的公共后缀类型,那么就不能直接返回路径
* 就必须全路径并且要加上 forward 或者redirect
* forward:请求转发,访问路径不会发生变化
* redirect:重定向,访问路径会发生变化
* @return
*/
@RequestMapping("/01")
public String list01() {
return "forward:/WEB-INF/views/student/student.html";
}
/**
* SpringMVC跳转的方式三:如果返回值类型是ModelAndView,那么在返回页面的时候,
* 也要必须全路径并且要加上 forward 或者redirect
* forward:请求转发,访问路径不会发生变化
* redirect:重定向,访问路径会发生变化
* @return
*/
@RequestMapping("/02")
public ModelAndView list02() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("forward:/WEB-INF/views/student/student.html");
return modelAndView;
}
/**
* SpringMVC跳转的方式四:如果是在webapp下面的静态资源,
* 那么就直接使用forward或者redirect去访问页面即可
* forward:请求转发,访问路径不会发生变化
* redirect:重定向,访问路径会发生变化
* @return
*/
@RequestMapping("/03")
public String list03() {
return "forward:/student.html";
}
}
复制代码
- 过滤器
-
在以前我们使用Servlet的时候,我们解决Post乱码的方式就是通过在每个Servlet中配置字符集编码 req.setCharacterEncoding("UTF-8"),在SpringMVC中使用此方法就无法解决我们的Post乱码问题了,所以我们需要使用过滤器来帮助我们解决乱码问题
- Filter过滤器是一个对访问的请求和响应进行拦截的web组件;
- Filter过滤器可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理;
-
过滤器编写
- 写一个类去实现Filter接口,并实现接口中的所有方法;
- 在web.xml中配置或者使用注解配置【@WebFilter("/")】
package cn.itsource.springmvc_01;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
// 与配置二选一,使用了注解就不用配置过滤路径
@WebFilter("/*")
public class AFilter implements Filter{
/**
* 在tomcat启动的时候执行
*/
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("tomcat启动执行了过滤器的init方法。。。");
}
/**
* 过滤器的核心方法
*/
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
System.out.println("放行前。。。");
// 设置字符集编码
req.setCharacterEncoding("UTF-8");
// 对拦截放行
chain.doFilter(req, resp);
System.out.println("放行后。。。");
}
/**
* 在tomcat正常关闭的时候执行,不推荐在里面写代码
*/
@Override
public void destroy() {
}
}
复制代码
<!-- WEB.xml配置拦截路径,如果使用注解方式就不用配置,二选一 -->
<filter>
<filter-name>first</filter-name>
<filter-class>cn.itsource.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>first</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
复制代码
-
配置字符编码过滤器
- springmvc框架本身没有处理请求编码,但是spring框架为我们提供了一个编码过滤器。开发者只需要配置一个spring内置请求编码过滤器即可。在web.xml配置一个请求编码过滤器:
<?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_3_1.xsd"
version="3.1"
metadata-complete="false">
<servlet>
<!-- 给核心控制器配置起一个唯一的名称 -->
<servlet-name>dispatcherServlet</servlet-name>
<!-- 核心控制器的全限定名 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- init-param标签的位置必须在load-on-startup上面 -->
<!-- 告诉DispatcherServlet核心控制器去哪里找核心配置文件 -->
<init-param>
<!-- contextConfigLocation 固定写法,不能改变 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-MVC.xml</param-value>
</init-param>
<!-- 这个的意思是指定核心控制器的加载时机,参数值为 1~10 数字越低加载时机越高 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- url-pattern参数值,有两种写法
1./ 拦截所有请求(推荐使用,问题有解决方案),但是他不会拦截页面资源,并且支持restful风格
问题:如果路径是/,他会把tomcat自带的servlet给覆盖掉
被覆盖的servlet就是别人专门处理静态资源的servlet
2. *.do:你的请求路径必须以.do结尾,才能访问我的核心控制器
*: 匹配所有的意思
.do: 以.do结尾的所有请求
3./* : 也是拦截所有请求,但是他会把jsp跳转也拦截(这个方式不推荐使用)
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 解决SpringMVC post 提交乱码问题 -->
<filter>
<filter-name>characterEncodingFilter</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>
<!-- 强制指定字符编码,即使request或response设置了字符编码,
也会强制使用当前设置的,任何情况下强制使用此编码 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
复制代码
SpringMVC的基础学习就到此结束了