您的位置:首页 > 其它

深入学习SSH框架《三:Servlet中配置过滤器Filter和异步过滤器》

2017-03-08 19:27 417 查看

在SSH应用程序中过滤器是一个很重要的角色,它有以下目的:

过滤器可以拦截访问资源的请求、资源的响应或者两个同时拦截,它们将以某种方式作用于这些请求或响应,过滤器可以检测和修改请求和响应,它们甚至可以拒绝和转发请求。其中过滤器也可编程式配置和在部署描述符中配置。过滤经常用在一下模块==》日志过滤器,验证过滤器,压缩和加密过滤器,错误处理过滤器。

1.过滤器的实现。

public class RequestLogFilter implements Filter
{
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
Instant time = Instant.now();
StopWatch timer = new StopWatch();
try
{
timer.start();
chain.doFilter(request, response);
}
finally
{
timer.stop();
HttpServletRequest in = (HttpServletRequest)request;
HttpServletResponse out = (HttpServletResponse)response;
String length = out.getHeader("Content-Length");
if(length == null || length.length() == 0)
length = "-";
System.out.println(in.getRemoteAddr() + " - - [" + time + "]" +
" \"" + in.getMethod() + " " + in.getRequestURI() + " " +
in.getProtocol() + "\" " + out.getStatus() + " " + length +
" " + timer);
}
}

@Override
public void init(FilterConfig filterConfig) throws ServletException { }

@Override
public void destroy() { }
}

2.部署过滤器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>Filter Order Application</display-name>
<filter>
<filter-name>filterA</filter-name>
<filter-class>com.wrox.FilterA</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>filterA</filter-name>
<url-pattern>/*</url-pattern>
<!-- <servlet-name>async</servlet-name> -->
<dispatcher>ASYNC</dispatcher>
<!-- <dispatcher>REQUEST</dispatcher> -->
</filter-mapping>
<filter>
<filter-name>filterB</filter-name>
<filter-class>com.wrox.FilterB</filter-class>
</filter>
<filter-mapping>
<filter-name>filterB</filter-name>
<url-pattern>/servletTwo</url-pattern>
<url-pattern>/servletThree</url-pattern>
</filter-mapping>
<filter>
<filter-name>filterC</filter-name>
<filter-class>com.wrox.FilterC</filter-class>
</filter>
<filter-mapping>
<filter-name>filterC</filter-name>
<url-pattern>/servletTwo</url-pattern>
</filter-mapping>
</web-app>

其中要注意的是filter有一个支持异步属性,

<dispatcher>ASYNC</dispatcher>有效的类型还有REQUEST,FORWARD,INCLUDE,ERROR和ASYNC意思是该过滤器支持的
类型是请求、转发、包含、错误和异步类型,比如下面的示例:

@WebServlet(urlPatterns="/async", asyncSupported=true,name="async")
public class AsynServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private HttpServletResponse responseAsyn;
/**
* @see HttpServlet#HttpServlet()
*/
public AsynServlet() {
super();
// TODO Auto-generated constructor stub
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
responseAsyn=resp;
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.println("进入Servlet的时间:" + new Date() + ".");
out.flush();

//在子线程中执行业务调用,并由其负责输出响应,主线程退出
final AsyncContext ctx = req.startAsync();
ctx.setTimeout(200000);
new Work(ctx,responseAsyn).start();
out.println("结束Servlet的时间:" + new Date() + ".");
out.flush();
}
}

class Work extends Thread{
private AsyncContext context;
private HttpServletResponse response;
public Work(AsyncContext context,HttpServletResponse response){
this.context = context;
this.response=response;
}
@Override
public void run() {
try {
Thread.sleep(2000);//让线程休眠2s钟模拟超时操作
PrintWriter wirter = context.getResponse().getWriter();
response.sendRedirect("/servletOne");
wirter.write("2s后调用servletOne");
wirter.flush();
context.complete();
} catch (InterruptedException e) {

} catch (IOException e) {

}
}
}

3.使用注解声明过滤器

package com.wrox;

import javax.servlet.DispatcherType;
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;
import javax.xml.ws.Dispatch;

import java.io.IOException;
@WebFilter(
urlPatterns={"/servlet/*","/servletone"},
servletNames={"servletTwo"},
dispatcherTypes={DispatcherType.ASYNC}
)
public class FilterA implements Filter
{
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
System.out.println("Entering FilterA.doFilter().ASNY!!!");
chain.doFilter(request, response);
System.out.println("Leaving FilterA.doFilter().");
}

@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("进入了过滤器的init方法==>");
}

@Override
public void destroy() { }
}

4.过滤器的排序

由于注解标识的过滤器无法按照需要的顺序过滤,所以只能使用部署描述符进行过滤。排在越前的过滤器先执行,过滤器链就像一条流水线,一个出错了就不会继续执行过滤,实例代码.

5.过滤器处理异步请求。

import javax.servlet
4000
.AsyncContext;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;

public class AnyRequestFilter implements Filter
{
private String name;

@Override
public void init(FilterConfig config)
{
this.name = config.getFilterName();
}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
System.out.println("Entering " + this.name + ".doFilter().");
chain.doFilter(
new HttpServletRequestWrapper((HttpServletRequest)request),
new HttpServletResponseWrapper((HttpServletResponse)response)
);
if(request.isAsyncSupported() && request.isAsyncStarted())
{
AsyncContext context = request.getAsyncContext();
System.out.println("Leaving " + this.name + ".doFilter(), async " +
"context holds wrapped request/response = " +
!context.hasOriginalRequestAndResponse());
}
else
System.out.println("Leaving " + this.name + ".doFilter().");
}

@Override
public void destroy() { }
}

其中异步过滤器只有在标注了异步(@WebServlet(urlPatterns="/async", asyncSupported=true,name="async")或者 

<filter>

    <filter-name>filterA</filter-name>

    <filter-class>com.wrox.FilterA</filter-class>

    <async-supported>true</async-supported> 

  </filter>

才会执行

有关更多实例代码,在我的github地址

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: