前言
到这里我们对Java Web的学习也到尾声了,本专栏关于Java Web的知识也是非常全的,如果有这方面的需求可以关注一下本专栏。
接下来我们来学习几个辅助性质的技术,首先来学习过滤器。
什么是过滤器?
过滤器实际上就是对web资源
进行拦截
,做一些处理
后再交给下一个过滤器或servlet处理
。
通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理。
对于过滤器:
(1)过滤器(
Filter
)是J2EE Servlet模板下的组件。
(2)Filter的作用是对URL进行统一的拦截处理
。
(3)Filter通常用于应用程序层面
进行全局处理。
大概流程图如下:
开发一个过滤器
要只要我们开发一个过滤器都需要经过一下三个步骤:
(1)任何过滤器都要实现
javax.servlet.Filter
接口。
(2)在Filter接口的do Filter()
方法中编写过滤器的功能代码。
(3)在web.xml
中对过滤器进行配置,说明拦截URL的范围。
接下来我们就来演示开发一个简单的过滤器。
首先创建写一个过滤器先实现Filter
接口,然后重写里面的do Filter()
方法。
我们第一个过滤器:
public class MyFirstFilter implements Filter{
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("过滤器已生效");
chain.doFilter(request, response);
}
}
在web.xml中进行配置
(1)filter标签用于说明哪个类是过滤器,并在应用启动时自动加载.
(2)filter-mapping标签用于说明过滤器对URL应用的范围,要点有二:
- filter-name 过滤器名称与filter.filter-name保持一致
- url-pattern 说明过滤器作用范围,
/*代表对所有URL进行过滤
<!-- filter标签用于说明哪个类是过滤器,并在应用启动时自动加载 -->
<filter>
<filter-name>MyFirstFilter</filter-name>
<filter-class>com.imooc.filter.MyFirstFilter</filter-class>
</filter>
<!--
filter-mapping标签用于说明过滤器对URL应用的范围,要点有二:
1.filter-name 过滤器名称与filter.filter-name保持一致
2.url-pattern 说明过滤器作用范围, /*代表对所有URL进行过滤
-->
<filter-mapping>
<filter-name>MyFirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我们再写一个servlet进行测试:
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html ; charset=utf-8");
response.getWriter().println("你好,世界!");
}
输出:
在浏览器对servlet进行访问
看控制台
说明我们在do Filter()
中设置的处理语句成功生效了。
我们除了在web.xml中配置还可以使用注解形式配置,如:
@WebFilter(filterName="MyFirstFilter", urlPatterns="/*")
public class MyFirstFilter implements Filter{
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("过滤器已生效");
chain.doFilter(request, response);
}
}
看起来是非常简单的,也是配置成功了。
过滤器的生命周期
我们在实现Filter接口之后,其实需要重写的方法有三个,如下:
public class MyFirstFilter implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
这三个函数也构成了过滤器的生命周期。它们的作用分别是:
(1)
Filter.init()
:过滤器初始化工作。
(2)Filter.doFilter()
:进行过滤处理。
(3)Filter.destroy()
:销毁过滤器。
我们可以把之前的案例中的过滤器进行更改,如下:
public class MyFirstFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("过滤器已被销毁");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("过滤器已生效");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
System.out.println("过滤器初始化成功");
}
}
看一下过滤器的处理过程:
在启动Tomcat之后,先是初始化成功,然后在访问url之后过滤器生效了。
最后在关闭Tomcat之后,显示销毁过滤器了。
过滤器的特征:
(1) 过滤器对象在Web应用
启动时被创建
且全局唯一
(2)唯一的过滤器对象在并发环境中采用“多线程
”提供服务
过滤器参数化
过滤器参数化分为两部分:
(1)过滤器为了增强灵活性,允许配
置信息放在web.xml
中。
(2)在web.xml中配置<init-param>设置过滤器参数
接下来我们做一个字符集过滤器来进行演示:
Web输出是中文的话会出现中文乱码问题,对于解决中文乱码问题我们有以下几个办法:
(1)GET请求:在
servlet.xml
中增加URIEncoding = "UTF-8"
。
(2)POST请求:使用request.setCharacterEncoding("UTF-7");
(3)响应:response.setContentType("text/html;charset=UTF-8");
如果我们做的是个大的项目的话我们就需要给多个Servlet去添加这些东西,其实我们只需要添加一个过滤器提前去解决这些问题就行了。不必去一个一个添加处理。
我们写一个字符集过滤器,但是有时根据用户不同我们使用的字符集编码又不是统一的,需要经常进行更改,如果直接在过滤器中进行更改的话,我们每一次更改都需要整个项目重新进行编译处理,重新发布。
这样十分麻烦,我们直接在web.xml中把字符集设置成参数,在web.xml中更改,由于这是一个解释型语言,所以不需要重新编译就很方便。
如下:
public class CharacterEncodingFilter implements Filter {
//设置所用的字符集编码,值通过过滤器获取
private String encoding;
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest req = (HttpServletRequest)request;
req.setCharacterEncoding(encoding);
HttpServletResponse res = (HttpServletResponse)response;
res.setContentType("text/html; charset = " + encoding);
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
encoding = filterConfig.getInitParameter("encoding");
System.out.println("encoding:" + encoding);
}
}
在web.xml中进行配置并且设置参数:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.imooc.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>
非常简单,但是非常实用。
设置过滤范围
在前面简略的提到了url-pattern
说明过滤器作用范围, /*代表对所有URL进行过滤
。接下来我们就具体来学习在url-pattern标签中设置过滤器生效的范围。
url-pattern常用写法
(1)
/index.jsp
:执行资源精准
匹配
(2)/servlet/*
:以前缀
进行模式匹配
(3)*.jsp
:以后缀
进行模式匹配
例如*.jsp
,就是把url后缀为*.jsp
的所有url进行拦截下来通过所绑定的这个过滤器处理。其他类同!
过滤链
我们在写一个web项目的时候,使用的到过滤器通常不止一个,这些多个过滤器就构成了一个过滤链,如下:
我们在开发过滤链的时候需要注意:
(1)每一个过滤器应具有单独职能。
(2)过滤器的执行顺序以web.xml
中<filter-mapping>
的顺序为准。
(3)调用chain.doFilter()
将请求向后传递。
尤其注意chain.doFilter()
,我们之前在doFilter方法中的最后一步都是chain.doFilter(request, response)
,就是代表将请求传向下一个过滤器或者servlet。
结语
过滤器内容比较少,但是过滤器比较常用所以还是要多多理解练习!
本专栏持续更新中…