SpringMVC_Two
SpringMVC_Two
响应数据和结果视图
创建工厂
导坐标:
<!-- 版本锁定 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><spring.version>5.0.2.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency></dependencies>
配置web.xml
在web.xml配置文件中核心控制器DispatcherServlet
<!-- SpringMVC的核心控制器 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- 配置servlet启动时加载对象 --><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
处理乱码的过滤器:
<!--处理乱码的过滤器--><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></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
配置编写springmvc.xml的配置文件
在resources下创建springmvc.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 1:配置spring创建容器时要扫描的包 --><context:component-scan base-package="com.le"></context:component-scan><!-- 2:配置视图解析器 --><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><!-- 3:配置spring开启注解mvc的支持 --><mvc:annotation-driven></mvc:annotation-driven></beans>
创建index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body></body></html>
在WEB-INF下创建pages的文件夹,创建success.jsp
<body><h1>访问成功</h1></body>
返回值分类
Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。
创建response.jsp
<body><h3>返回字符串</h3><a href="user/testReturnString">返回字符串</a><br><a href="user/userUpdate">修改用户(表单回显)</a></body>
创建包com.le.controller,创建类UserController.java
@Controller@RequestMapping(path = "/user")public class UserController {// 返回字符串@RequestMapping(path="/testReturnString")public String testReturnString(){System.out.println("执行了testReturnString方法!");return "success";}/*** 请求参数的绑定*/@RequestMapping(value="/userUpdate")public String userUpdate(Model model) {// 模拟从数据库中查询的数据,在页面上进行回显User user = new User();user.setUsername("张三");user.setPassword("123");user.setAge(18);model.addAttribute("user", user);return "update";}}
在WEB-INF的pages下,编写update.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %><html><head><title>Title</title></head><body><h3>修改用户</h3>${ requestScope }<form action="${pageContext.request.contextPath}/user/update" method="post">姓名:<input type="text" name="username" value="${ user.username }"><br>密码:<input type="text" name="password" value="${ user.password }"><br>年龄:<input type="text" name="age" value="${ user.age }"><br><input type="submit" value="提交"></form></body></html>
点击“提交”
// 更新保存@RequestMapping(value = "/update")public String update(User user){System.out.println("执行UserController的update的方法!user:"+user);return "success";}
返回值是void
情况1:如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。
默认会跳转到@RequestMapping(path="/testVoid")testVoid的页面。
response.jsp
<h3>无返回值void</h3><a href="user/testVoid">无返回值</a>
userController.java
// 无返回值@RequestMapping(path="/testVoid")public void testVoid(){System.out.println("执行了testVoid方法!");}

情况2:可以使用请求转发或者重定向跳转到指定的页面
修改testVoid的方法
@RequestMapping(value="/testVoid")public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {System.out.println("请求转发或者重定向");// 1:请求转发// request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);// 2:重定向// response.sendRedirect(request.getContextPath()+"/index.jsp");response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");// 3:直接响应数据response.getWriter().print("你好");return;}
页面结果:
情况3:如果不指定转发和重定向,直接响应数据。

返回值是ModelAndView对象
ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图
具体的代码如下
response.jsp
<h3>返回ModelAndView对象</h3><a href="user/testModelAndView">ModelAndView</a>
修改Usercontroller.java
/*** 返回ModelAndView对象* 可以传入视图的名称(即跳转的页面),还可以传入对象。* @return* @throws Exception*/@RequestMapping(value="/testModelAndView")public ModelAndView testModelAndView() throws Exception {ModelAndView mv = new ModelAndView();// 默认执行视图解析器,跳转到WEB-INF/pages/success.jsp的页面mv.setViewName("success");// 模拟从数据库中查询所有的用户信息List<User> list = new ArrayList<>();User user1 = new User();user1.setUsername("张三");user1.setPassword("123");User user2 = new User();user2.setUsername("赵四");user2.setPassword("456");list.add(user1);list.add(user2);// 添加对象mv.addObject("list", list);return mv;}
坐标:
<dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %><%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html><head><title>Title</title></head><body><h1>访问成功</h1><h3>查询所有的数据</h3><c:forEach items="${ list }" var="user">${ user.username }-----${user.password}<br></c:forEach></body></html>
SpringMVC框架提供的转发和重定向
forward请求转发
UserController.java方法返回String类型,想进行请求转发也可以编写成:
response.jsp
<h3>转发和重定向</h3><a href="user/testForwardOrRedirect">ForwardOrRedirect</a>
转发和重定向
/*** 使用forward关键字进行请求转发* "forward:转发的JSP路径",不走视图解析器了,所以需要编写完整的路径* @return* @throws Exception*/@RequestMapping("/testForwardOrRedirect")public String testForwardOrRedirect() throws Exception {System.out.println("testForwardOrRedirect方法执行了...");// return "forward:/WEB-INF/pages/success.jsp";return "forward:/user/testReturnString";}
redirect重定向
controller方法返回String类型,想进行重定向也可以编写成
/*** 重定向* @return* @throws Exception*/@RequestMapping("/testForwardOrRedirect")public String testForwardOrRedirect() throws Exception {System.out.println("testForwardOrRedirect方法执行了...");// return "redirect:/index.jsp";return "redirect:/user/testReturnString";}
@ResponseBody响应json数据
去掉对静态资源的拦截
DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。
response.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><script src="js/jquery.min.js"></script><script>$(function(){$("#btn").click(function(){alert("ok");})})</script><html><head><title>Title</title></head><body><h3>ResponseBody响应json数据</h3><input type="button" value="提交" id="btn"/></body></html>
此时发现【提交】按钮不起作用,因为springMVC的使用了servlet的配置,servlet中使用/,拦截所有的请求,js/jquery.min.js也被拦截了,不起作用。
【解决方案】:需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
推荐使用:在springmvc.xml中使用:
<!--去掉所有的静态资源,让DispatchServlet不能拦截静态资源--><!--方案一--><mvc:default-servlet-handler></mvc:default-servlet-handler>
使用@RequestBody获取请求的数据
response.jsp
<script>$(function(){$("#btn").click(function(){// alert("ok");$.ajax({url:"user/testJson",contentType:"application/json;charset=UTF-8",data:'{"username":"tom","password":"123","age":30}',dataType:"json",type:"post",success:function(data){alert(data);alert(data.addressName);}});})})</script>
UserController.java
/*** 获取请求体的数据* @param body*/@RequestMapping("/testJson")public void testJson(@RequestBody String body) {System.out.println(body);}

但是此时获取了json数据的字符串,我们需要将数据封装到javaBean的对象怎么办?
↓↓↓↓↓↓↓
json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.0</version></dependency>
使用@ResponseBody注解将JavaBean对象转换成Json返回
使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应
要求方法需要返回JavaBean的对象
response.jsp
<script src="js/jquery.min.js"></script><script>$(function(){$("#btn").click(function(){// alert("ok");$.ajax({url:"user/testJson",contentType:"application/json;charset=UTF-8",data:'{"username":"tom","password":"123","age":30}',dataType:"json",type:"post",success:function(data){alert(data);alert(data.username);alert(data.password);alert(data.age);}});})})</script>
注意:data:'{"username":"tom","password":"123","age":30}',一定保证单引号在外,双引号在里,否则抛出异常
UserController.java
/*** 获取请求体的数据,响应数据Json* @param body*/@RequestMapping("/testJson")public @ResponseBody User testJson(@RequestBody User user) {// 请求userSystem.out.println(user);// 响应uUser u = new User();u.setUsername("张三");u.setPassword("123");u.setAge(18);return u;}
SpringMVC实现文件上传
文件上传的必要前提:
- A form表单的enctype取值必须是:multipart/form-data (支持二进制数据)
(默认值是:application/x-www-form-urlencoded) (支持传递参数,例如:?username=zhangsan&age=18)
enctype:是表单请求正文的类型 - B method属性取值必须是Post
- C 提供一个文件选择域
文件上传的原理分析 :
当form表单的enctype取值不是默认值后(例如:multipart/form-data),request.getParameter()将失效。
默认值:
enctype=”application/x-www-form-urlencoded”时,form表单的正文内容是:
key=value&key=value&key=value
当form表单的enctype取值为Mutilpart/form-data时,请求正文内容就变成: 每一部分都是MIME类型描述的正文
-----------------------------7de1a433602ac 分界符Content-Disposition: form-data; name="userName" 协议头aaa 协议的正文-----------------------------7de1a433602acContent-Disposition: form-data; name="file"; filename="C:\Users\zhy\Desktop\fileupload_demofile\b.txt"Content-Type: text/plain 协议的类型(MIME类型)bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-----------------------------7de1a433602ac--
springmvc传统方式的文件上传
坐标:
<!-- 版本锁定 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><spring.version>5.0.2.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency></dependencies>
web.xml
<!-- SpringMVC的核心控制器 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- 配置servlet启动时加载对象 --><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--配置解决中文乱码过滤器--><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></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.le.controller"/><!--视图解析器--><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><mvc:annotation-driven></mvc:annotation-driven><!-- 设置静态资源不过滤 --><mvc:default-servlet-handler></mvc:default-servlet-handler></beans>
导入index.jsp
<body><a href="user/testFileUpload">文件上传</a></body>
UserController.java
@Controller@RequestMapping(path = "/user")public class UserController {// 文件上传@RequestMapping(path="/testFileUpload")public String testFileUpload(){System.out.println("执行了testFileUpload方法!");return "success";}}
WEB-INF/pages/success.jsp
<body><h1>文件上传成功</h1></body>
普通文件上传
index.jsp
<%--enctype="multipart/form-data"把请求体分成多个部分上传--%><form action="user/testFileUpload1" method="post" enctype="multipart/form-data">选择文件:<input type="file" name="upload"><br/><input type="submit" value="上传"/><br/></form>
UserController.java
// 文件上传@RequestMapping(path="/testFileUpload1")public String testFileUpload1(HttpServletRequest request) throws Exception {System.out.println("执行了testFileUpload1方法!");// 上传的位置,获取到项目根目录下的uploads文件夹绝对路径String path = request.getSession().getServletContext().getRealPath("/uploads");// 创建file对象File file = new File(path);// 判断是否存在if(!file.exists()) {// 创建目录file.mkdirs();}// 创建磁盘文件项工厂DiskFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload fileUpload = new ServletFileUpload(factory);// 解析requestList<FileItem> list = fileUpload.parseRequest(request);// 遍历,获取到每一个文件项的对象for (FileItem fileItem : list) {// 判断,当前fileItem是否是文件项if(fileItem.isFormField()) {// 说明是普通的表单 ,文本框}else {// 文件上传项 fileItem// 获取到文件的名称String filename = fileItem.getName();// 生成唯一标识String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();filename = uuid+"_"+filename;// 上传文件fileItem.write(new File(file, filename));// 删除临时文件fileItem.delete();}}return "success";}
查看上传结果
SpringMVC传统方式文件上传
简化ServletFileUpload的写法。
SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的name属性名称相同。

springmvc.xml中配置
<!-- 配置文件解析器对象,要求id名称必须是multipartResolver --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!--文件大小限制:10*1024*1024字节,表示10M--><property name="maxUploadSize" value="10485760"/></bean>
index.jsp
<hr><form action="user/testFileUpload2" method="post" enctype="multipart/form-data">选择文件:<input type="file" name="upload"><br/><input type="submit" value="上传"/><br/></form>
UserController.java
/*** 使用的是SpringMVC的文件上传* 框架提供了一个类,表示上传文件的对象,底层已经帮你解析了request对象,把文件上传对象通过方法的参数传递进来** MultipartFile upload 变量名称必须和表单file标签的name属性名称相同,上传文件的对象,SpringMVC框架传递给你的。** @param request* @return* @throws Exception*/@RequestMapping("/testFileUpload2")// ↓↓↓注意这里的参数名称需要和文件上传表单中的"name属性名称一致public String testFileUpload2(HttpServletRequest request,MultipartFile upload) throws Exception {System.out.println("SpringMVC的上传文件...");// 上传的位置,获取到项目根目录下的uploads文件夹绝对路径String path = request.getSession().getServletContext().getRealPath("/uploads");// 创建file对象File file = new File(path);// 判断是否存在if(!file.exists()) {// 创建目录file.mkdirs();}// 获取到文件的名称String filename = upload.getOriginalFilename();// 生成唯一标识String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();filename = uuid+"_"+filename;// 使用upload对象中方法就直接上传文件upload.transferTo(new File(file, filename));return "success";}
springmvc跨服务器方式的文件上传
分服务器的目的
在实际开发中,我们会有很多处理不同功能的服务器。例如:
应用服务器:负责部署我们的应用 (源码)
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。
图片服务器:负责存储用户上传的图片的信息。
(注意:此处说的不是服务器集群)
分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

准备两个tomcat服务器,并创建一个用于存放图片的web工程
创建工程
选择项目,右键,new一个Module

创建2个tomcat服务器
一个应用服务器:用来启动springmvc_day02_fileupload(端口:8080)

另一个图片服务器:用来启动springmvc_day02_fileuploadserver(端口:9090)

两个服务器的端口需要不一致
同时在图片服务器上创建upload文件夹,用来指定上传的文件。

注意:这里要新建一个任意文件,不然可能会报错
坐标
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><dependency><groupId>com.sun.jersey</groupId><artifactId>jersey-core</artifactId><version>1.18.1</version></dependency><dependency><groupId>com.sun.jersey</groupId><artifactId>jersey-client</artifactId><version>1.18.1</version></dependency>
index.jsp
<hr><form action="user/testFileUpload3" method="post" enctype="multipart/form-data">选择文件:<input type="file" name="upload"><br/><input type="submit" value="上传"/><br/></form>
UserController.java
/*** 跨服务器上传文件,把文件上传到图片服务器中去* @param upload* @return* @throws Exception*/@RequestMapping("/testFileUpload3")public String testFileUpload3(MultipartFile upload) throws Exception {System.out.println("跨服务器上传文件...");// 指定上传文件的路径String path = "http://localhost:9090/springmvc_day02_fileuploadserver/uploads/";// 获取到文件的名称String filename = upload.getOriginalFilename();// 生成唯一标识String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();filename = uuid+"_"+filename;// 上传文件// 创建客户端对象Client client = Client.create();filename = path+filename;// 连接图片服务器WebResource webResource = client.resource(filename);// 把文件上传到图片服务器上webResource.put(upload.getBytes());return "success";}
可在success.jsp中,显示上传的图片
<body>${pageContext.request.contextPath}<h1>访问成功!</h1><img src="http://localhost:8088/springmvc_day02_fileuploadserver/upload/D7E35E6EDAC94039BDE6533BEFF8F981_02.jpg"/></body>
注意:如果抛出异常:returned a response status of 403 Forbidden
出现这个错误的原因是因为我将图片上传单独部署了一个服务器。但是图片不能写入。需要在这个存储图片的项目所在的tomcat中配置可写操作。具体的是在Tomcat目录下的conf文件夹下的web.xml中加入
加入此行的含义是:接收文件的目标服务器可以支持写入操作。
<servlet><servlet-name>default</servlet-name><servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>readonly</param-name><param-value>false</param-value></init-param><init-param><param-name>listings</param-name><param-value>false</param-value></init-param><load-on-startup>1</load-on-startup></servlet>
SpringMVC的异常处理
异常处理思路
系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。 系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理

SpringMVC的异常处理
坐标
<!-- 版本锁定 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><spring.version>5.0.2.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency></dependencies>
web.xml
<!-- SpringMVC的核心控制器 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- 配置servlet启动时加载对象 --><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--配置解决中文乱码过滤器--><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></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.le.controller"/><!--视图解析器--><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><mvc:annotation-driven></mvc:annotation-driven><!-- 设置静态资源不过滤 --><mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 --><mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 --><mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript --></beans>
导入index.jsp
<body><a href="user/testException">异常处理</a></body>
UserController.java
@Controller@RequestMapping(path = "/user")public class UserController {// 自定义异常处理@RequestMapping(path="/testException")public String testException(){System.out.println("执行了testException方法!");int a = 10/0;return "success";}}
WEB-INF/pages/success.jsp
<body><h1>访问成功!</h1></body>

自定义异常类
创建包com.le.exception,创建类SysException.java。
/*** 自定义异常类*/public class SysException extends Exception {// 异常提示信息private String message;public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public SysException(String message) {this.message = message;}}
编写异常处理器
创建包com.le.exception,创建类SysExceptionResolver.java。
/*** 编写异常处理器*/public class SysExceptionResolver implements HandlerExceptionResolver {/*** 跳转到具体的错误页面的方法*/@Overridepublic ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @Nullable Object o, Exception e) {e.printStackTrace();SysException se = null;// 获取到异常对象if(e instanceof SysException) {se = (SysException) e;}else {se = new SysException("请联系管理员");}ModelAndView mv = new ModelAndView();// 存入错误的提示信息mv.addObject("message", se.getMessage());// 跳转的Jsp页面mv.setViewName("error");// 跳转到WEB-INF/pages/error.jspreturn mv;}}
配置异常处理器(跳转到错误提示页面)
springmvc.xml
<!-- 配置异常处理器 --><bean id="sysExceptionResolver" class="com.le.exception.SysExceptionResolver"/>
修改UserController.java
// 自定义异常处理@RequestMapping(path="/testException")public String testException() throws SysException{System.out.println("执行了testException方法!");try {int a = 10/0;} catch (Exception e) {// 在控制台打印e.printStackTrace();throw new SysException("服务器繁忙,稍后再试...");}return "success";}
指定error.jsp错误页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %><html><head><title>Title</title></head><body><h1>访问失败</h1>${message}<br></body></html>
SpringMVC中的拦截器
拦截器的作用
Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器(Controller)进行预处理和后处理。
用户可以自己定义一些拦截器来实现特定的功能(权限控制、日志处理等)。
谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:
过滤器和拦截器的区别:
区别1:
过滤器是servlet规范中的一部分,任何java web工程都可以使用。
拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
区别2:
过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法(只会拦截Controller)
核心控制器设置成/,表示拦截所有请求
核心控制器设置成.do(.action),表示拦截.do结尾的url请求
要求必须实现:HandlerInterceptor接口。

自定义拦截器
坐标
<!-- 版本锁定 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><spring.version>5.0.2.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency></dependencies>
web.xml
<!-- SpringMVC的核心控制器 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- 配置servlet启动时加载对象 --><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--配置解决中文乱码过滤器--><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></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.le.controller"/><!--视图解析器--><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><mvc:annotation-driven></mvc:annotation-driven><!-- 设置静态资源不过滤 --><mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 --><mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 --><mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript --></beans>
UserController.java
@Controller@RequestMapping(path = "/user")public class UserController {// 自定义拦截器@RequestMapping(path="/testInterceptor")public String testInterceptor(){System.out.println("执行了testInterceptor方法!");return "success";}}
index.jsp
<body><a href="user/testInterceptor">自定义拦截器</a></body>
WEB-INF/pages/success.jsp
<body><h1>访问成功</h1></body>
自定义拦截器
创建包com.le.interceptor,创建类MyInterceptor1.java,实现HandlerInterceptor接口
public class MyInterceptor1 implements HandlerInterceptor{/*** controller方法执行前,进行拦截的方法* return true放行* return false拦截* 可以使用转发或者重定向直接跳转到指定的页面。*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("访问Controller类之前执行...");return true;}}
配置拦截器类
在springmvc.xml中配置拦截器类
<!--配置拦截器类--><mvc:interceptors><mvc:interceptor><!-- 哪些方法进行拦截 --><mvc:mapping path="/user/*"/><!--哪些方法不进行拦截--><!--<mvc:exclude-mapping path="/user/save"/>--><!-- 注册拦截器对象 --><bean class="com.le.interceptor.MyInterceptor1"></bean></mvc:interceptor></mvc:interceptors>
在success.jsp中添加:
<body><h1>访问成功</h1><%System.out.println("浏览器success.jsp执行...");%></body>

HandlerInterceptor接口中的方法
1:preHandle方法是controller方法执行前拦截的方法
可以使用request或者response跳转到指定的页面
return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
return false不放行,不会执行controller中的方法。
2:postHandle是controller方法执行后执行的方法,在JSP视图执行前。
可以使用request或者response跳转到指定的页面
如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
3:afterCompletion方法是在JSP执行后执行(用的不多)
request或者response不能再跳转页面了,否则抛出异常。
修改:MyInterceptor.java
public class MyInterceptor1 implements HandlerInterceptor{/*** controller方法执行前,进行拦截的方法(预处理)* return true放行* return false拦截* 可以使用转发或者重定向直接跳转到指定的页面。*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("MyInterceptor1访问Controller类之前执行...");// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);return true;}/*** controller方法执行后,进行拦截的方法(后处理),success.jsp执行之前* 可以使用转发或者重定向直接跳转到指定的页面。*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {System.out.println("MyInterceptor1访问Controller类之后执行...");// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);}/*** success.jsp执行之后,该方法执行(终处理)*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {System.out.println("MyInterceptor1访问success.jsp之后...");}}

配置多个拦截器
再编写一个拦截器的类MyInterceptor2.java
public class MyInterceptor2 implements HandlerInterceptor{/*** controller方法执行前,进行拦截的方法(预处理)* return true放行* return false拦截* 可以使用转发或者重定向直接跳转到指定的页面。*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("MyInterceptor2访问Controller类之前执行...");// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);return true;}/*** controller方法执行后,进行拦截的方法(后处理),success.jsp执行之前* 可以使用转发或者重定向直接跳转到指定的页面。*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {System.out.println("MyInterceptor2访问Controller类之后执行...");// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);}/*** success.jsp执行之后,该方法执行(终处理)*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {System.out.println("MyInterceptor2访问success.jsp之后...");}}
配置2个拦截器
<!--配置拦截器类--><mvc:interceptors><mvc:interceptor><!-- 哪些方法进行拦截 --><mvc:mapping path="/user/*"/><!--哪些方法不进行拦截--><!--<mvc:exclude-mapping path="/user/save"/>--><!-- 注册拦截器对象 --><bean class="com.le.interceptor.MyInterceptor1"></bean></mvc:interceptor><mvc:interceptor><!-- 哪些方法进行拦截 --><mvc:mapping path="/**"/><!--哪些方法不进行拦截--><!--<mvc:exclude-mapping path="/user/save"/>--><!-- 注册拦截器对象 --><bean class="com.le.interceptor.MyInterceptor2"></bean></mvc:interceptor></mvc:interceptors>

使用拦截器处理“权限控制”,例如,存在session就能访问Controller,不存在session不能访问Controller

浙公网安备 33010602011771号