SpringMVC
SpringMVC概述
SpringMVC:是基于spring的一个框架, 实际上就是spring的一个模块, 专门是做web开发的。是servlet的一个升级
Web开发底层是servlet , 框架是在servlet基础上面加入一些功能,让你做web开发方便。
SpringMVC就是一个Spring。 Spring是容器,ioc能够管理对象,使用< bean >, @Component, @Repository, @Service, @Controller
SpringMVC能够创建对象, 放入到容器中(SpringMVC容器), springmvc容器中放的是控制器对象,
我们要做的是 使用@Contorller创建控制器对象, 把对象放入到springmvc容器中, 把创建的对象作为控制器使用, 这个控制器对象能接收用户的请求, 显示处理结果,就当做是一个servlet使用。
使用@Controller注解创建的是一个普通类的对象, 不是Servlet。 springmvc赋予了控制器对象一些额外的功能。
Web开发底层是servlet, springmvc中有一个对象是Servlet : DispatherServlet(中央调度器)
DispatherServlet: 负责接收用户的所有请求, 用户把请求给了DispatherServlet, 之后DispatherServlet把请求转发给我们的Controller对象, 最后是Controller对象处理请求。
第一个SpringMVC程序
需求: 用户在页面发起一个请求, 请求交给springmvc的控制器对象,并显示请求的处理结果(在结果页面显示一个欢迎语句)。
实现步骤:
新建web maven工程
加入依赖,spring-webmvc依赖,会间接把spring的依赖都加入到项目,jsp,servlet依赖
重点: 在web.xml中注册springmvc框架的核心对象DispatcherServlet(注意:只要是SpringMVC的项目,就必须有DispatcherServlet对象,这个对象是衡量程序是不是用了SpringMVC的标准)
- DispatcherServlet叫做中央调度器, 是一个servlet, 它的父类是继承HttpServlet
- DispatcherServle也叫做前端控制器(front controller)
- DispatcherServlet负责接收用户提交的请求, 调用其它的控制器对象,并把请求的处理结果显示给用户
创建一个发起请求的页面 index.jsp
创建控制器(处理器)类
- 在类的上面加入@Controller注解,创建对象,并放入到springmvc容器中
- 在类中的方法上面加入@RequestMapping注解。
创建一个作为结果的jsp,显示请求的处理结果。
创建springmvc的配置文件(spring的配置文件一样)
- 声明组件扫描器, 指定@Contorller注解所在的包名
- 声明视图解析器。帮助处理视图的。
加入依赖:
1 2 3 4 5 6 7 8 9 10 11 12
| <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.5.RELEASE</version> </dependency>
|
更改web版本为4.0

注册中央调度器DispatcherServlt,需要在tomcat服务器启动后,创建DispatcherServlet对象的实例。
为什么要创建DispatcherServlet对象的实例呢? 因为DispatcherServlet在他的创建过程中, 会同时创建springmvc容器对象, 读取springmvc的配置文件,把这个配置文件中的对象都创建好, 当用户发起请求时就可以直接使用对象了。
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
| <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.xml</param-value> </init-param>
<load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
|
SpringMVC配置文件 SpringMVC.xml , 注册组件扫描器
1
| <context:component-scan base-package="com.Jancoyan.*"/>
|
创建发起请求的页面 index.jsp
1 2
| <p>第一个spring MVC项目</p> <a href="some.do">发起some.do请求</a>
|
创建处理器(控制器)类(这样的类可以有很多个)
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
|
@Controller public class MyController {
@RequestMapping(value = "/some.do") public ModelAndView doSome(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg1", "hello,SpringMVC"); modelAndView.addObject("msg2", "welcome"); modelAndView.setViewName("/show.jsp"); return modelAndView; } }
|
请求处理流程
- 发起some.do
- tomcat(web.xml–url-pattern知道 *.do的请求给DispatcherServlet)
- DispatcherServlet(根据springmvc.xml配置知道 some.do—doSome())
- DispatcherServlet把some.do转发给MyController.doSome()方法
- 框架执行doSome()把得到ModelAndView进行处理, 转发到show.jsp
上面的过程简化的方式 some.do—DispatcherServlet—MyController

用户可以直接通过在地址栏敲入show.jsp直接显示页面,但是这时候页面中并没有获取到数据,此时我们需要隐藏显示结果的视图,也就是将show.jsp放入 webapp/WEB-INF/view 下面达到隐藏效果,但是此时在控制器中转发的时候要写完整的路径,所以我们要在springmvc配置文件中进行配置视图解析器
1 2 3 4 5 6 7
| <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/> </bean>
|
当配置完视图解析器之后,可以使用逻辑名称(文件名),指定视图,框架会使用视图解析器的前缀 + 逻辑名称 + 后缀 组成完成路径, 这里就是字符连接操作
1
| modelAndView.setViewName("show");
|
至此,第一个项目已经结束,具体源代码参考 GITHUB\Learning\JavaWeb\SpringMVC\1.FirstApplication
SpringMVC执行流程

- 浏览器提交请求到中央调度器
- 中央调度器直接将请求转给处理器映射器。
- 处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器。
- 中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器。
- 处理器适配器调用执行处理器。
- 处理器将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器。
- 处理器适配器直接将结果返回给中央调度器。
- 中央调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。
- 视图解析器将封装了的视图对象返回给中央调度器
- 中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。
- 中央调度器响应浏览器。
SpringMVC注解式开发
@ RequestMapping 定义请求规则
@ RequestMapping 放在类的上面,表示该控制器类中所有的RequestMapping前面都会加上类上面RequestMapping括号中的内容,我们通常根据这个来划分不同的控制器的功能,以及进行模块的迁移。只需要改动控制器类上面的requestMapping,就可以实现模块的迁移
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <a href="user/some.do"> 调用user的doSome </a>
@Controller @RequestMapping("/user") public class MyController {
@RequestMapping(value = "/some.do") public ModelAndView doSome(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg", "Hello"); modelAndView.setViewName("show"); return modelAndView; } }
|
指定method请求方式
如果前后端的请求方式不同,就会报错。
1 2 3 4 5 6 7 8
| @RequestMapping(value = "/some.do", method = RequestMethod.POST) public ModelAndView doSome(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg", "Hello"); modelAndView.setViewName("show"); return modelAndView; }
|
处理器方法的参数
处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即我们可在方法内直接使用。 写在控制器方法的形参列表的位置。
- HttpServletRequest
- HttpServletResponse
- HttpSession
- 请求中所携带的请求参数
前三种在调用的时候系统自动赋值,我们直接在控制器方法中直接赋值即可。
1 2 3 4 5 6 7 8
| @RequestMapping(value = "/some.do", method = RequestMethod.POST) public ModelAndView doSome(HttpServletRequest request, HttpServletResponse response, HttpSession session){ ModelAndView modelAndView = new ModelAndView(); String name = request.getParameter("name"); System.out.println(name); return modelAndView; }
|
第四种有两种方法
注意:在提交请求参数时,get请求方式中文没有乱码。 使用post方式提交请求,中文有乱码,需要使用过滤器处理乱码的问题。过滤器可以自定义,也可使用框架中提供的过滤器 CharacterEncodingFilter
逐个接收参数
逐个接受参数的时候,处理器(控制器)方法的形参名和请求中参数名必须一致。同名的请求参数赋值给同名的形参, 对位置没有要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <form action="user/addOneByOne.do" method="post"> 增加功能的实现: <br> name : <input name="name" type="text"> <br> age : <input type="text" name="age"> <br> <input type="submit" value="逐个接收addOneByOne.do"> </form>
@RequestMapping(value = "/addOneByOne.do", method = RequestMethod.POST) public ModelAndView addOneByOne(String name, int age){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("name", name); modelAndView.addObject("age", age); modelAndView.setViewName("show"); return modelAndView; }
<h3>获取到的name为 : ${name}</h3> <h3>获取到的age为 : ${age}</h3>
|
原理解析:
框架接收请求参数,使用request对象接收请求参数的时候,框架会帮我们自动执行以下内容:
String strName = request.getParameter("name");
String strAge = request.getParameter("age");
springmvc框架通过 DispatcherServlet 调用 MyController的doSome()方法调用方法时,按名称对应,把接收的参数赋值给形参 : doSome(strName,Integer.valueOf(strAge))框架会提供类型转换的功能,能把String转为 int ,long , float, double等类型。
但是当我们在前端传入age=“” 年龄为空的时候,会出现400错误,400状态码是客户端错误, 表示提交请求参数过程中,发生了问题。
因为 Integer.valueOf(strAge) 传入一个空的时候,会出现错误。
这个可以JavaScript进行前端校验
注意:用get方法进行提交的时候不会出现乱码错误,但是post方法会出现中文乱码,这时候应该使用过滤器:
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
| <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>
<init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param>
<init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter>
<filter-mapping> <filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern> </filter-mapping>
|
校正请求参数名@RequestParam
前端的sname赋值给形参name;sage赋值给形参age
@RequestParam: 逐个接收请求参数中, 解决请求中参数名形参名不一样的问题
属性:
- value 请求中的参数名称
- required 是一个boolean,默认是true, true:表示请求中必须包含此参数。
位置: 在处理器方法的形参定义的前面
1 2 3 4 5 6 7 8
| @RequestMapping(value = "/modifyParas.do", method = RequestMethod.POST) public ModelAndView modifyParas(@RequestParam(value = "sname", required = true) String name, @RequestParam(value = "sage", required = true) int age){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("name", name); modelAndView.addObject("age", age); modelAndView.setViewName("show"); return modelAndView; }
|
对象接收参数
先调用无参构造,再用set方法赋值
可以有多个形参对象,他们互不干扰,对象会分别创建然后赋值。
@RequestParam 不能在这种情况下使用。
处理器方法形参是java对象, 这个对象的属性名和请求中参数名一样的,框架会创建形参的java对象, 给属性赋值。 请求中的参数是name,框架会调用setName()
1 2 3 4 5 6 7 8
| @RequestMapping(value = "/addObject", method = RequestMethod.POST) public ModelAndView addObj(Student student){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("name", student.getName()); modelAndView.addObject("age", student.getAge()); modelAndView.setViewName("show"); return modelAndView; }
|
源码:GITHUB\Learning\JavaWeb\SpringMVC\2.Parameters
处理器方法的返回值
p23 – 32 学完ajax + jquery 再来看
解读 < url-pattern />
用户发起的请求是由哪些服务器程序处理的?
1 2 3 4 5
| http://localhost:8080/ch05_url_pattern/index.jsp :tomcat(jsp会转为servlet) http://localhost:8080/ch05_url_pattern/js/jquery-3.4.1.js : tomcat http://localhost:8080/ch05_url_pattern/images/p1.jpg : tomcat http://localhost:8080/ch05_url_pattern/html/test.html: tomcat http://localhost:8080/ch05_url_pattern/some.do : DispatcherServlet(springmvc框架处理的)
|
因此,tomcat本身能处理静态资源的访问, 像html, 图片, js文件都是静态资源
原因:tomcat的web.xml文件有一个servlet 名称是 default , 在服务器启动时创建的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <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>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> 表示静态资源和未映射的请求都这个default处理 </servlet-mapping>
|
default这个servlet作用:
- 处理静态资源
- 处理未映射到其它servlet的请求。
使用框架的时候, url-pattern可以使用两种值
使用扩展名方式, 语法 *.xxxx , xxxx是自定义的扩展名。 常用的方式 *.do, *.action, *.mvc 等等,不能使用 *.jsp
使用斜杠 “/“。当你的项目中使用了 / ,它会替代 tomcat中的default。导致所有的静态资源都给DispatcherServlet处理, 默认情况下DispatcherServlet没有处理静态资源的能力。没有控制器对象能处理静态资源的访问。所以静态资源(html,js,图片,css)都是404。 动态资源some.do是可以访问,的因为我们程序中有MyController控制器对象,能处理some.do请求。
静态资源的访问
三种方式:
- 使用< mvc:default-servlet-handler / >
- 使用 < mvc: resources /> 【掌握】
- 声明注解驱动
使用< mvc:default-servlet-handler / >
需要在springmvc配置文件加入 < mvc:default-servlet-handler >
原理是: 加入这个标签后,框架会创建控制器对象DefaultServletHttpRequestHandler(类似我们自己创建的MyController),DefaultServletHttpRequestHandler这个对象可以把接收的所有请求转发给 tomcat的default这个servlet,为了访问动态资源我们需要 加上 < mvc:annotation-driven / > 来解决问题
直接加上这句话
1 2 3 4
| <mvc:default-servlet-handler /> <mvc:annotation-driven />
|
使用 < mvc: resources /> 【掌握】
mvc:resources 加入后框架会创建 ResourceHttpRequestHandler这个处理器对象。
让这个对象处理静态资源的访问,不依赖tomcat服务器。
mapping:访问静态资源的uri地址, 使用通配符 **
location:静态资源在你的项目中的目录位置。
images/** : 表示 images/p1.jpg , images/user/logo.gif , images/order/history/list.png, **表示所有字符,可以表示文件、目录、多级目录等
mvc:resources和@RequestMapping有一定的冲突,所以要记得加上注解驱动
1 2 3 4 5 6 7 8 9 10
|
<mvc:resources mapping="/images/**" location="/images/" /> <mvc:resources mapping="/html/**" location="/html/" /> <mvc:resources mapping="/js/**" location="/js/" />
<mvc:annotation-driven />
|
使用一条语句解决多种静态资源的访问问题:
首先应该在webapp中新建一个static文件夹,然后将所有静态资源文件夹都放在static文件夹中。
webapp/static/html, webapp/static/js, webapp/static/images
1 2
| <mvc:resources mapping="/static/**" location="/static/" /> <mvc:annotation-driven />
|
SSM整合开发
搭建环境
SSM: SpringMVC + Spring + MyBatis.
SpringMVC: 视图层,界面层,负责接收请求,显示处理结果的。
Spring:业务层,管理service,dao,工具类对象的。
MyBatis:持久层, 访问数据库的
用户发起请求–SpringMVC接收–Spring中的Service对象–MyBatis处理数据
SSM整合也叫做SSI (IBatis也就是mybatis的前身), 整合中有容器。
- 第一个容器SpringMVC容器, 管理Controller控制器对象的。
- 第二个容器Spring容器,管理Service,Dao,工具类对象的
我们要做的把使用的对象交给合适的容器创建,管理。
把Controller还有web开发的相关对象交给springmvc容器,web用的对象写在springmvc配置文件中
service,dao对象定义在spring的配置文件中,让spring管理这些对象。
springmvc容器和spring容器是有关系的,关系已经确定好了。springmvc容器是spring容器的子容器, 类似java中的继承。子可以访问父的内容,在子容器中的Controller可以访问父容器中的Service对象, 就可以实现controller使用service对象
实现步骤
使用springdb的mysql库, 表使用student(id auto_increment, name, age)
新建maven web项目
加入依赖springmvc,spring,mybatis三个框架的依赖,jackson依赖,mysql驱动,druid连接池,jsp,servlet依赖
写web.xml,注册DispatcherServlet ,目的:
创建SpringMVC容器对象,才能创建Controller类对象。
创建的是Servlet,才能接受用户的请求。
注册spring的监听器:ContextLoaderListener,目的: 创建spring的容器对象,才能创建service,dao等对象。
注册字符集过滤器,解决post请求乱码的问题
创建包, Controller包, service ,dao,实体类包名创建好
写springmvc,spring,mybatis的配置文件
- springmvc配置文件
- spring配置文件
- mybatis主配置文件
- 数据库的属性配置文件
写代码, dao接口和mapper文件, service和实现类,controller, 实体类。
写jsp页面
配置 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
| <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2.1-b03</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.5.RELEASE</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-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency>
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
|
配置web.xml
整合注解开发
见文件 Learning\JavaWeb\SpringMVC\3.SSM
SpringMVC核心技术
请求转发和重定向

请求转发的使用情况:因为我们已经配置了视图解析器,所以在跳转的时候我们不能直接通过 setViewName的方式跳转到view目录以外的目录,为了能够跳转到view以外的目录,我们需要用到请求转发操作。
语法:modelAndView.setViewName("forward:完整目录")
特点: 不和视图解析器一同使用,就当项目中没有视图解析器
1 2 3 4 5 6 7 8
| @RequestMapping(value = "/addOneByOne.do", method = RequestMethod.POST) public ModelAndView addOneByOne(String name, int age){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("name", name); modelAndView.addObject("age", age); modelAndView.setViewName("forward:/WEB-INF/view/show.jsp"); return modelAndView; }
|
处理器方法返回ModelAndView,实现重定向redirect
语法:setViewName(“redirect:视图完整路径”)
redirect特点:不和视图解析器一同使用,就当项目中没有视图解析器
框架对重定向的操作:
- 框架会把Model中的简单类型的数据,转为string使用,作为hello.jsp的get请求参数使用。目的是在 doRedirect.do 和 hello.jsp 两次请求之间传递数据
- 在目标hello.jsp页面可以使用参数集合对象
$ {param}获取请求参数值 ${param.myname}
- 重定向不能访问/WEB-INF资源
1 2 3 4 5 6 7 8 9 10 11
| @RequestMapping(value = "/doRedirect.do") public ModelAndView doWithRedirect(String name,Integer age){ ModelAndView mv = new ModelAndView(); mv.addObject("myname",name); mv.addObject("myage",age); mv.setViewName("redirect:/WEB-INF/view/show.jsp"); return mv; }
|
异常处理
代码见Learning\JavaWeb\SpringMVC\4.Exception
springmvc框架采用的是统一,全局的异常处理。
把controller的所有异常处理都集中到一个地方。 采用的是aop的思想。把业务逻辑和异常处理代码分开。解耦合。
使用两个注解
@ExceptionHandler
@ControllerAdvice
异常处理步骤:
新建maven web项目
加入依赖
新建一个自定义异常类 MyUserException , 重写前两个构造方法,即无参构造和String构造,再定义它的子类NameException , AgeException
在controller抛出NameException , AgeException
创建一个普通类,作用全局异常处理类 GlobalExceptionHandler
- 在类的上面加入@ControllerAdvice(控制器增强 - 给控制器增加异常处理功能)特点:必须让框架知道这个注解所在的包名(第7步)
- 在类中定义方法,方法的上面加入@ExceptionHandler
创建处理异常的视图页面
创建springmvc的配置文件
- 组件扫描器 ,扫描@Controller注解
- 组件扫描器,扫描@ControllerAdvice所在的包名
- 声明注解驱动
关键点:把异常抛出给框架,让框架集中处理这些异常。
创建相关类
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
| public class UserException extends Exception { public UserException(){} public UserException(String message) { super(message); } }
public class AgeException extends UserException { public AgeException() { super(); } public AgeException(String message) { super(message); } }
@RequestMapping(value = "/addObject", method = RequestMethod.POST) public ModelAndView addObj(Student student) throws UserException { ModelAndView modelAndView = new ModelAndView(); if(student.getAge() > 100){ throw new AgeException(); } if(!student.getName().equals("zs")){ throw new NameException(); } modelAndView.addObject("name", student.getName()); modelAndView.addObject("age", student.getAge()); modelAndView.setViewName("show"); return modelAndView; }
|
全局异常处理类
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
| @ControllerAdvice public class GlobalExceptionHandler {
@ExceptionHandler(value = NameException.class) public ModelAndView doNameException(Exception e){
ModelAndView mv = new ModelAndView(); mv.addObject("msg","姓名必须是zs,其它用户不能访问"); mv.addObject("e", e); mv.setViewName("nameError"); return mv; } @ExceptionHandler(value = AgeException.class) public ModelAndView doAgeException(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","年龄太大了!!!"); mv.addObject("e", e); mv.setViewName("ageError"); return mv; } @ExceptionHandler() public ModelAndView OtherException(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","其他异常"); mv.addObject("e", e); mv.setViewName("Others"); return mv; } }
|
错误视图略。
配置文件的配置
1 2 3 4
| <context:component-scan base-package="com.Jancoyan.Handler"/> <context:component-scan base-package="com.Jancoyan.Controller"/> <mvc:annotation-driven/>
|
拦截器
- 拦截器是springmvc中的一种,需要实现HandlerInterceptor接口。
- 拦截器和过滤器类似,功能方向侧重点不同。 过滤器是用来过滤器请求参数,设置编码字符集等工作。拦截器是拦截用户的请求,做请求做判断处理的。
- 拦截器是全局的,可以对多个Controller做拦截。 一个项目中可以有0个或多个拦截器, 他们在一起拦截用户的请求。拦截器常用在:用户登录处理,权限检查, 记录日志。
拦截器的使用步骤:
- 定义类实现HandlerInterceptor接口
- 在springmvc配置文件中,声明拦截器, 让框架知道拦截器的存在。

实现接口:
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
| public class MyInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器的MyInterceptor的preHandle()"); return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("拦截器的MyInterceptor的postHandle()");
}
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("拦截器的MyInterceptor的afterCompletion()"); } }
|
修改配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <mvc:interceptors> <mvc:interceptor>
<mvc:mapping path="/**"/> <bean class="com.Jancoyan.Handler.MyInterceptor" /> </mvc:interceptor> </mvc:interceptors>
|
拦截器的执行时间:
- 在请求处理之前, 也就是controller类中的方法执行之前先被拦截。
- 在控制器方法执行之后也会执行拦截器。
- 在请求处理完成后也会执行拦截器。
拦截器:看做是多个Controller中公用的功能,集中到拦截器统一处理。使用的AOP的思想
多个拦截器的执行顺序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 第一个拦截器preHandle=true , 第二个拦截器preHandle=true
111111-拦截器的MyInterceptor的preHandle() 22222-拦截器的MyInterceptor的preHandle() =====执行MyController中的doSome方法===== 22222-拦截器的MyInterceptor的postHandle() 111111-拦截器的MyInterceptor的postHandle() 22222-拦截器的MyInterceptor的afterCompletion() 111111-拦截器的MyInterceptor的afterCompletion()
第一个拦截器preHandle=true , 第二个拦截器preHandle=false
111111-拦截器的MyInterceptor的preHandle() 22222-拦截器的MyInterceptor的preHandle() 111111-拦截器的MyInterceptor的afterCompletion()
第一个拦截器preHandle=false , 第二个拦截器preHandle=true|false
111111-拦截器的MyInterceptor的preHandle()
|
拦截器和过滤器的区别
1.过滤器是servlet中的对象, 拦截器是框架中的对象
2.过滤器实现Filter接口的对象, 拦截器是实现HandlerInterceptor
3.过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的。 拦截器是用来验证请求的,能截断请求。
4.过滤器是在拦截器之前先执行的。
5.过滤器是tomcat服务器创建的对象, 拦截器是springmvc容器中创建的对象
6.过滤器是一个执行时间点。 拦截器有三个执行时间点
7.过滤器可以处理jsp,js,html等等, 拦截器是侧重拦截对Controller的对象。 如果你的请求不能被DispatcherServlet接收, 这个请求不会执行拦截器内容
8.拦截器拦截普通类方法执行,过滤器过滤servlet请求响应