标签:load otto 文本 not 匹配 focus 过滤 通配符 框架
//Filter对请求的拦截有2次,一次是请求过程中,一次是响应过程中;在请求过程被拦截后,执行doFilter()方法,遇到chain.doFilter(request,response); 语句后跳转到下一个资源,有可能是服务器,也有可能是另一个过滤器。当服务器发出响应再次经过该过滤器时,执行chain.doFilter(request,response); 以下的语句。然后才将响应传递给浏览器
实例化——初始化——doFilter()——销毁
//Filter整个生命周期的执行,都是由服务器负责管理,我们只是获得相应的时机
两者都是单例多线程
Filter是在应用被加载时创建并初始化,Servlet是在该Servlet被第一次访问时被创建并初始化。但两者的无参构造和init方法都只执行一次
用户每提交一次该Filter可以过滤的请求,服务器都会执行一次doFilter()方法,即doFilter()方法可以被多次执行
当应用被停止时执行destory()方法,Filter被销毁,destory()方法只会执行一次
两者都存在线程安全问题
//两者非常类似,各方面都差不多,可以将Filter看成一个特殊的Servlet
package com.dh.Filter;
?
import javax.servlet.*;
import java.io.IOException;
?
public class SomeFilter implements Filter {
public SomeFilter() {
System.out.println("实例化");
}
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化"); //从这里获取FilterConfig接口的对象
}
?
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("等价于service方法");
chain.doFilter(request,response); //将请求传递到下一资源中
System.out.println("第二次拦截");
}
?
public void destroy() {
System.out.println("销毁");
}
}
//Filter中一共有4个方法(含无参构造器),提供了3个时机可被使用。而doFilter()方法与Servlet中的service()一样,只要访问该Filter,必然自动调用doFilter()方法
//在web.xml文件中
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">
<filter>
<filter-name>SomeFilter</filter-name>
<filter-class>com.dh.Filter.SomeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/*</url-pattern> //这是对所有路径都进行拦截
</filter-mapping>
</web-app>
/*:表示当前Servlet可以匹配所有请求,也可以拦截所有请求
/:表示当前Servlet可以匹配所有请求,但不会拦截动态资源,只会拦截静态资源
可以不写<url-pattern>,如下就只拦截发送给xxxServlet的请求
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<servlet-name>xxxServlet</servlet-name>
</filter-mapping>
//静态资源:使用静态网页技术(html,css,js)发布的资源。特点是所有用户访问之后的结果是一样
//动态资源:使用动态网页技术(jsp,Servlet,...)发布的资源。特点是不同的用户访问,得到的结果可能不一样
//若有用户请求的是动态资源,那么服务器会自动将动态资源转化为静态资源,在发送给浏览器。因为浏览器无法解析动态资源
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
//dispatcher标签的取值有:FORWARD, INCLUDE, REQUEST(默认), ERROR(错误跳转页面的请求)
//当其值为哪个时,Filter就只拦截这一种类型的请求,其他种类的请求就相当于没有拦截器,均不拦截
//FORWARD, INCLUDE的区别? P67页
//FilterConfig接口与ServletConfig一模一样
//以下就是FilterConfig接口封装的内容。一个Filter对应一个FilterConfig对象
<filter>
<filter-name>SomeServlet</filter-name>
<filter-class>com.dh.SomeServlet</filter-class>
<init-param>
<param-name>...</param-name>
<param-value>...</param-value>
</init-param>
......
</filter>
//获取Filter的name
String getFilterName()
//获取所有初始化参数的名称
Enumeration<> getInitParameterNames()
//通过Key获取value
String getInitParameter(String key)
//获取全局域
public class SomeFilter implements Filter {
private FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig=filterConfig;
}
ServletContext sc=filterConfig.getServletContext();
//在我们的请求到达Servle之间是可以经过多个Filter的,一般来说,建议Filter之间不要有关联,各自处理各自的逻辑即可。这样,我们也无需关心执行顺序问题。//如果一定要确保执行顺序,就要对配置进行修改了,执行顺序如下
在web.xml中,filter执行顺序跟在<filter-mapping>中的注册顺序有关,先声明的先执行
使用注解配置的话,filter的执行顺序跟名称的字母顺序有关,例如AFilter会比BFilter先执行
如果既有在web.xml中声明的Filter,也有通过注解配置的Filter,那么会优先执行web.xml中配置的Filter
//Servlet容器是由两个Map集合组成的,而Filter容器是由一个Map集合和一个数组构成。因为Filter是在应用启动时就创建并初始化的,并不需要第二Map来创建
//Filter的Map中key是<url-pattern/>值,value是Filter的实例对象的引用;数组中存放的是为请求相匹配的所有Filter
//当某资源请求到达Web容器后,会先对请求进行解析,得到uri作为比较对象,从Map中查找是否有相匹配的key。若存在,则读取其value值,将该引用存到数组中,然后继续查找,直到将Map集合中所有符合的都找出来。再数组初始化完毕之后,开始按照数组中元素的顺序执行Filter。数组中所有的Filter全部执行完毕之后,再跳转到请求的目标资源中
@WebFilter(filterName = "MyFilter",
initParams = {@WebInitParam(name="zs",value="23"),
@WebInitParam(name="ls",value="24")
},
value={"/a","/b","/c"},
//urlPatterns = {"/f","/d"},
//servletNames = "SomeServlet"
dispatcherTypes =DispatcherType.FORWARD
)
public class MyFilter implements Filter {
?
}
//filename:<file-name>标签
//initParams:FilterConfig接口封装的初始化属性值
//value,urlPattern,ServletNames三者的功能都是一样的,所以三者不能同时出现,一次只能出现其中一个
//dispatcherTpyes: <dispatcher>标签
//无论两种方式的的url-pattern值是否相同,其都是作为两个独立的Filter出现,互不干扰。(即两种方式的url-pattern值是相同的,一次请求也同时进过两个相同的Filter)
//springmvc就是一个spring框架,它能创建对象,并将对象放到springMVC的容器中。也能使用ioc管理对象,也可以使用<bean>,@Component,@Repository,@Service,@Controller等注解。但springmvc容器中主要放的是控制器对象
//使用@Controller注解创建控制器对象,用该对象接收用户的请求,显示处理结果,可以看作成一个Servlet使用
//但使用@Controller注解创建的对象是一个普通对象,能将其看成一个Servlet,但其本质上不是一个Servlet,因为该对象没有继承HttpServlet类,它不能直接接收用户有浏览器发送过来的请求,只能就受中央调度器的二次转发
//在springmvc中有一个servlet:DispatcherServlet(中央调度器)它负责直接接收用户的请求,再将请求转发给控制器对象,对请求进行处理
在web.xml文件中对DispatcherServlect对象进行注册
<servlet>
<servlet-name>aaa</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name> //contextConfigLocation固定写法
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
?
<servlet-mapping>
<servlet-name>aaa</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
//DispatcherServlet对象需要在服务器启动时被创建,因为该对象被创建的同时,也同时会创建springmvc的容器对象,并读取springmvc的配置文件,将springmvc配置文件中的对象都创建好,当用户发起请求时,可直接使用对象,节约时间。所以得加入<load-on-startup>标签
//DispatcherServlet对象被创建后,会执行初始化方法init(),init()的内容是
创建容器,读取配置文件:WebApplicationContext ctx=new ClassPathXmlApplicationContext ("springmvc.xml")
把容器对象放到ServletContext中:getServletContext().setAttribute(key,ctx)
//<init-param>标签中是配置Tomcat服务器读取springmvc.xml配置文件的位置,以上配置是在类路径的根目录下读取;默认位置是:/WEB-INF/<servlet-name>-servlet.xml,<servlet-name>在这里是aaa
//<load-on-startup>标签要写在<init-param>标签后面,不然会报错
创建控制类
public class MyController {
"/some.do") (
public ModelAndView doSome(){
ModelAndView mv=new ModelAndView();
mv.addObject("a","123");
mv.addObject("b","456");
mv.setViewName("/show.jsp");
return mv;
}
}
//@Controller:定义控制器类,接收处理用户的请求。一个控制器类中可以有多个处理器方法
//@RequestMapping:请求映射,将一个请求地址和一个方法绑定在一起
//属性:value,String类型,表请求的URL地址,唯一值
//位置:在方法上(常用);也可以在类上
//ModelAndView:springmvc中的一个类,表示既可以返回数据,也可以返回视图,如:jsp等
//setViewName()方法相当于forward操作
在springmvc.xml文件中声明组件扫描器
<context:component-scan base-package="com.dh.controller"/>
//base-package:控制器类所在的包名
发起请求:.../some.do
Tomcat接收到请求后,解析出其uri,然后找到对应的<url-pattern>为*.do的Servlet——DispatcherServlet
DispatcherServlet通过springmvc配置文件扫描控制器包,找到@Controller注解类,找到对应的处理器方法
DispatcherServlet把.../some.do请求转发给doSome()方法
框架执行doSome方法,把得到的ModelAndView进行处理,转发到show.jsp中
//当show.jsp在webapp的根目录下是,用户是可以直接通过网址访问的
//我们可以将show.jsp放在WEB-INF目录下,该目录下的文件是受保护的,无法直接由网页地址访问
//setViewName()方法中的路径改为
mv.setViewName("/WEB-INF/show.jsp");
//配置视图解析器在springmvc.xml之中
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/> //前缀:视图文件路径
<property name="suffix" value=".jsp"/> //后缀:视图文件扩展名
</bean>
//setViewName()方法中的路径改为
mv.setViewName("show");
"test") (
public class MyController {
"/some.do") (
public ModelAndView doSome(){
//此时doSome()方法的真实url为:/test/some.do
//test出现在类上,被所有的处理其方法共有,所以被称为模块名称
public class MyController {
value = "/some.do",method = RequestMethod.GET) (
public ModelAndView doSome(){
}
//method属性:表示接收请求方式,它的值是RequestMethod枚举值。常用的有GET,POST,PUT......
//若method=RequestMethod.GET,此时发送post请求,则报错:405
//若在@RequestMapping注解中不指定method属性,则该方法可以接收任何请求方式的请求,没有限制
HttpServletRequest
HttpServletResponse
HttpSession
用户提交的参数(逐个接收,对象接收)
//前3种参数可以直接使用,在调用时由系统自动赋值
(...)
public ModelAndView doSome(HttpServletRequest request, HttpServletResponse response, HttpSession session){
request...
session...
}
//适合参数数量较少时使用
<form action="receive.do" method="post">
姓名:<input type="text" name="name"/> <br> //abc
年龄:<input type="text" name="age"/> <br> //123
<input type="submit" value="提交">
</form>
value = "receive.do",method = RequestMethod.POST) (
public ModelAndView doSome(String name,int age){ //这里int使用的自动类型转换
System.out.println(name);
System.out.println(age); //abc 123
return mv;
}
//处理器方法的形参名必须和请求中的参数名一致。系统自动会将同名的请求参数赋给同名的形参,不关心位置,只看名称
//底层是String age=request.getParameter("age"),然后框架提供了自动转换功能,能将String转换为int,float等类型
//若年龄一栏不写,空着提交。则网页:400;控制台:不会抛异常,但会出现在服务器日志上。原因是空串无法转化为int类型。解决办法:doSome(String name,integer age),这样空串就转化为null,就不会报错了(实验证明:没啥用,依然会报错400:Required Integer parameter ‘age‘ is not present)。若年龄一栏填12.9或abc这样的,依然报错
//在提交请求参数时,get请求中没有中文乱码,使用post请求提交请求时,中文有乱码问题,需使用过滤器处理乱码
//过滤器可以自定义,也可以使用springmvc提供的过滤器:CharacterEncodingFilter
//在web.xml中添加
<filter>
<filter-name>abc</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> //强制HttpServletRequest对象使用上面encoding中的编码方式
</init-param>
<init-param>
<param-name>foreResponseEncoding</param-name>
<param-value>true</param-value> //强制HttpServletResponse对象使用上面encoding中的编码方式
</init-param>
</filter>
<filter-mapping>
<filter-name>abc</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
//forceRequestEncoding,foreResponseEncoding的默认值都是false
//在逐个接收请求中,解决请求中的参数名与处理器方法的形参名不一样的问题
//位置:在处理器方法的形参前面
//属性:value:请求中的参数名称
required:boolean类型,默认值为true。为true时,表示请求中必须包含该参数,即使在文本框中什么都不写,该参数的值为空串,依然会提交上来,不会报错。它其实指的是哪些没有name属性,无法提交的参数,若又设置了它的required值为true,就会报错:400。若不写required属性,默认为true
value = "receive.do",method = RequestMethod.POST) (
public ModelAndView doSome( (value = "name",required = false) String a,
value = "age") Integer b){ (
System.out.println(a);
System.out.println(b);
}
//适合参数数量较多时使用
public class Student {
private String name;
private Integer age; //还要写构造,set,get等方法
...
}
?
public class MyController {
value = "other.do",method = RequestMethod.POST) (
public ModelAndView doother(Student stu){
System.out.println(stu.getName());
System.out.println(stu.getAge());
}
}
//Studnet类中的属性名必须和请求中的参数名相同
//在doother(Student stu)中,框架会自动将请求中的参数赋给同名的属性,完成stu对象的赋值
//doother(对象1,对象2,对象3,...):可同时有多个对象
ModelAndView | 数据+视图 |
---|---|
String | 视图,不能返回数据 |
void | 即不返回数据,又不能跳转到其他的视图 |
对象Object | 返回数据,但不能跳转到其他视图 |
public class ReturnController {
value = "string.do",method = RequestMethod.POST) (
public String doString(String name, Integer age) {
System.out.println(name);
System.out.println(age); //abc 12
return "show";
}
}
//使用该返回值,依然能接受表单提交的数据,但无法将表单的数据输出到show.jsp中
// return "show";语句就相当于forward,跳转到show.jsp文件,但由于其无法携带数据,所以此时的show.jsp是一个静态页面
//若想携带数据跳转,则doString(HttpServletRequest request,String name, Integer age)——request.setAttribute("a",name),加入参数request,将数据装进request域中,再在jsp文件中通过El表达式获取
//假设show.jsp文件在WEB-INF目录下,当有视图解析器时,只需返回逻辑名称即可:return "show"; 当没有视图解析器时,就需要返回完整视图路径:return "WEB-INF/show.jsp";
value="void.do",method = RequestMethod.POST) (
public void doVoid(String name, Integer age) {
System.out.println(name);
System.out.println(age);
PrintWriter out=response.getWriter();
Student s=new Student();
s.setName("ww");
s.setAge(66);
out.print(s);
out.flush();
out.close();
}
//因为没有返回值,所以不能跳转到其他页面。但在处理Ajax时,通过添加 HttpServletResponse response参数输出数据,响应Ajax请求。注:要加入Jackson依赖
//若处理器方法的返回值是Object类型,则该处理器方法必须有@ResponseBody注解,否则无法访问该处理器方法
在springmvc.xml加入注解驱动
<context:component-scan base-package="com.dh.Controller"/>
?
<mvc:annotation-driven/>
//注解驱动的作用是:完成java对象到json,xml,text,二进制等数据格式的转化
//其底层是通过HttpMessageConveter接口(消息转化器)实现的。该接口有很多实现类,完成数据的转化,我们需要记住的是:
StringHttpMessageConverter //转为字符串格式
MappingJackson2HttpMessageConverter //转为接送格式
//该接口有5个方法:以下两个是控制器类把结果输出给浏览器时使用的
boolean canWrite(Class<?> var1, MediaType var2);
void write(T var1, MediaType var2, HttpOutputMessage var3)
//canWrite方法是检查处理器方法的返回值能不能转化为var2表示的数据格式。若能,返回true;MediaType是数据格式封装的类,如json,xml等
//write方法是调用Jackson中的ObjectMapper方法将处理器方法的返回值对象转化为json格式
@ResponseBody注解
public class MyController {
"some.do") (
public Student doSome(String name,Integer age) {
System.out.println(name);
System.out.println(age);
Student s=new Student();
s.setName("ww");
s.setAge(66);
return s;
}
}
//@ResponseBody注解是放在处理器方法上。底层是通过HttpServletResponse输出数据,响应Ajax的请求
PrintWriter out=response.getWriter();
out.print(s);
out.flush();
out.close(); //@ResponseBody注解代替的代码
//若处理器方法的返回值是Object类型,则该处理器方法必须有@ResponseBody注解,否则无法访问该处理器方法
//@ResponseBody注解是无法用于其他的返回值类型,比如:void,ModelAndView等
//返回对象的处理过程
框架会先调用HttpMessageConveter接口中的每个实现类的canWrite方法,检查那个实现类能处理Student类型的数据。在这里选择的是:MappingJackson2HttpMessageConverter,转为json
之后调用MappingJackson2HttpMessageConverter实现类的write方法,把Student的对象转化为json格式,底层是Jackson中的ObjectMapper方法。并且规定了字符集utf-8
最后调用@ResponseBody注解,将转化后的数据输出到浏览器中,完成Ajax的请求
value = "string.do",produces = "text/plain;charset=utf-8") (
public String doString(String name,Integer age) {
System.out.println("String:"+name);
System.out.println("String:"+age);
return "Hello,张三";
}
//前面的Sring是返回视图,这里的String是返回的数据——String对象,属于Object中的。区分两者就是看有没有@ResponseBody注解
//produces = "text/plain;charset=utf-8"语句是解决输出数据的中文字符乱码问题的;若Ajax是使用jQuery写的,解决中文乱码和String类型无法转化为json问题,请看笔记P39页
//springmvc框架中中央调度器DispatcherServlet的<url-pattern>有两种值
(1) *.xxx
(2) / (只是单独一个斜杠,后面不能跟其他东西)
//斜杠是专门处理未映射到其他Servlet的请求。AServlet的url-pattern为/a,BServlet的url-pattern为/b,此时在网页上访问http://localhost:8080/c,由于/c没有 与其对应的Servlet,所以就属于未映射的到其他的Servlet请求。这种请求主要包含静态资源,如:html,图片,js等文件都属于
//Tomcat服务器中有一个内置的Servlet:org.apache.catalina.servlets.DefaultServlet,专门是用来处理静态资源的
将中央调度器DispatcherServlet的<url-pattern>改为/,不用额外增加另外的为*.do的<url-pattern>也能访问some.do为url的Servlet,或者相关的控制器类。
中央调度器DispatcherServlet的<url-pattern>改为/后,导致DispatcherServlet替代了org.apache.catalina.servlets.DefaultServlet的作用。但DispatcherServlet没有处理静态资源的能力,因为没有对应的控制器对象。所静态资源访问都是404。但不影响some.do这类的请求
所以在加入springmvc.xml中加入以下标签来处理静态资源
<mvc:default-servlet-handler/>
//加入该标签后,框架会自动创建DefaultServletHttpRequestHandler控制对象,该对象的作用就是将所有请求转发给tomcat的org.apache.catalina.servlets.DefaultServlet,让他来处理静态资源
但该标签与@RequestMapping注解有冲突,静态资源可以正常访问,但some.do不行。原因可能是DefaultServletHttpRequestHandler把所有请求都转给Tomcat处理了,而org.apache.catalina.servlets.DefaultServlet不能处理控制器对象相关的请求,由转不出来,所以就不能访问。所以需要在springmvc.xml中加入注解驱动
<mvc:annotation-driven/>
//该方式的优点:简单,方便;缺点:必须依赖服务器,而且该服务器必须有org.apache.catalina.servlets.DefaultServlet才行
//假设有a.html文件在webapp/html/目录下,则在springmvc.xml中添加
<mvc:resources mapping="/html/**" location="/html/"/>
//mapping:访问静态资源的url地址,可以使用通配符:**
//location:静态资源在你项目中的目录位置
//<mvc:resources>标签:该标签加入springmvc.xml中后,会创建ResourceHttpRequestHandler处理器应用,它是springmvc内置的,专门用来处理静态资源的。之后就不需要依赖其他服务器,在框架内部即可完成
//<mvc:resources>标签与@RequestMapping注解有一定的冲突,所以需要加入注解驱动
<mvc:annotation-driven/>
<%
String basePath=request.getScheme()+"://"+
request.getServerName()+":"+
request.getServerPort()+
request.getContextPath()+"/"; //basePath表示的网址:http://localhost:8080/myweb/
?
%>
<base href="basePath"/>
<a href="/some.do">跳转</a> //这里的真实href为:http://localhost:8080/myweb/some.do,简写了
//加上<base href="basePath"/>后,以下所有标签中的url都有这个前缀:http://localhost:8080/myweb/,相当于简写了
//整合开发以注解方式为主,xml配置文件为辅
springmvc容器:管理Controller控制器对象
spring容器:管理Servlet,Dao。工具类对象
//两个容器都是独立存在的;springmvc容器是spring容器的子容器,类似java中的继承关系:子可以访问父的内容。在子容器中的Controller控制器对象可以访问父容器中的Service对象。
?
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
//添加 ?useUnicode=true&characterEncoding=UTF-8 这一段是解决从service写入数据库中,造成数据的中文乱码问题,但不能使数据库中已经乱码的数据复原回来,只作用于新加入的数据
请求转发
mv.setViewName("forward:视图文件的完整路径")
//添加了forward与没添加forward,没有区别,setViewName方法本身就是forward方式
//forward特点:不和视图解析器一起使用,即使项目中有视图解析器,也当其没有。forward后依然要跟完成路径
//forward后的完成路径以webapp的根目录为起点开始算的
//forward底层是request.getRequestDispatcher ("xxx.jsp") .forward ()
重定向
mv.setViewName("redirect:视图文件的完整路径")
//两次请求,第二次的请求(即重定向的那次)不能访问WEB-INF中的资源
//redirect特点:不和视图解析器一起使用,即使项目中有视图解析器,也当其没有。redirect后依然要跟完成路径
//redirect底层是response.sendRedirect ("xxx.jsp")
//springmvc框架采用的是统一,全局的异常处理。把controller中所有的异常处理都集中到一个地方(这样就不用在每个地方中写try..catch,单独处理),把异常处理和业务逻辑代码分开,解耦合
//采用了aop思想,增强目标类的功能
在控制器类的处理器方法中抛出异常InsertFailException(自定义的异常)
创建普通类作为全局异常处理类
package com.dh.handler;
?
public class handler {
?
InsertFailException.class) (
public ModelAndView doInsertFailException(Exception ex){
ModelAndView mv = new ModelAndView();
mv.addObject("ex",ex);
mv.setViewName("doException"); //跳转到异常处理页面
return mv;
}
}
//@ControllerAdvice:控制器增强(即给控制器类增加了异常处理功能);位置:在类上
//@ExceptionHandler:定义异常处理方法。异常处理方法与处理方法一样,有4中返回值类型,即String,ModelAndView,viod,object;异常处理方法的形参为Exception,可打印指定异常的异常信息
//@ExceptionHandler的属性是value,值为异常类。当控制器类中的方法抛出指定异常时,转到对应的异常处理方法,执行该异常方法中的内容,不会再回到原控制器类中的方法
//同一个异常处理类中可有多个异常处理方法;若还有一个异常处理方法,但该方法没有指定value值,则该异常处理方法处理除了InsertFailException异常外的所有异常
为异常处理类所在包配置组件扫描器
<context:component-scan base-package="com.dh.handler"/>
需要把异常记录下来,记录到数据库中,以及日志文件。记录日志发生的时间,位置,异常错误内容
发送通知,把异常信息通过邮件,短信等方式发送给相关人员
给用户友好的提示,不要404页面
拦截器是springmvc框架中的,需要实现HandlerInterceptor接口
拦截器与过滤器类似,但功能的侧重点不同。过滤器主要是用来过滤请求参数的,设置字符编码等工作;拦截器是拦截用户请求的,做请求的判断处理
拦截器是全局的,可以同时对多个Controller做拦截。一个项目中可以有多个拦截器,它们同时起作用
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
//参数Object handler为被拦截的控制器对象
//该方法在控制器类中的处理器方法执行之前执行;该方法可以验证用户信息是否符合,验证失败,返回false,截断请求
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
//该方法在处理器方法之后执行
//通过参数ModelAndView modelAndView可获取处理器方法的返回值,再在后处理方法中对视图,数据进行二次修改,可以影响最后的输出结果
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex)
//在请求处理完成后执行,即当处理器方法中的跳转到指定视图中的语句执行之后,就认为该请求处理完成
//该方法一般做资源回收工作,即删除一些创建的对象,回收占有的内存
//框架中的拦截器按照声明的先后顺序放到ArrayList集合中,越先声明,该拦截器就越先执行
//若有a,b两个拦截器,a先声明
1. a.preHandler()
2. b.preHandler()
3. MyController.doSome()
4. b.postHandler()
5. a.postHandler()
6. b.afterCompletion()
7. a.afterCompletion()
//若a,b的preHandler()都返回true,则按上述顺序执行
//若a.preHandler()返回true,b.preHandler()返回false,则只会执行1,2,7三个方法
//若a.b的preHandler()都返回false,则只执行1方法
//无论有多少个拦截器,只要其中一个拦截器的preHandler()方法返回false,则不会执行控制器类的处理器方法
过滤器是Servlet中的对象,拦截器是springmvc框架中
过滤器是实现Filter接口,拦截器是实现HandlerInterceptor接口
过滤器主要是用来设置request,response参数的属性的,侧重数据过滤;拦截器主要是用来验证请求,截断请求的
过滤器在拦截器之前执行
过滤器只有一个执行时间点,拦截器有3个
过滤器可以处理jsp,html等静态资源;拦截器侧重拦截Controller对象,若你的请求不能被DispatcherServlet接收,则该请求不会受到拦截器的拦截
拦截器拦截普通方法执行,过滤器是过滤Servlet请求
过滤器是Tomcat服务器创建对象,拦截器是spring容器中创建对象
标签:load otto 文本 not 匹配 focus 过滤 通配符 框架
原文地址:https://www.cnblogs.com/zhestudy-2021/p/14961130.html