Structs过滤器
一、工作目的
有时候我们希望在action执行之前,能捕获用户发出的请求,进行一些预处理的工作。例如:假设某系统设计,只有该系统的用户才能访问*.jsp页面,那么非系统用户如果直接在浏览器中输入*.jsp的访问路径,如何拒绝其访问呢?可以通过过滤器,判断是否存在该用户登录保存的session,进而实现访问的控制。在本次试验中,将首先介绍一些关于Filter的基础知识,然后根据程序演示过滤器的具体实现。
二、详细内容
Filter用于拦截用户请求,在服务器作出响应前,修改拦截下的request和response,以实现很多开发者想得到的功能。Filter是一个可以传送请求或修改响应的对象。过滤器并不是servlet,他们并不实际创建新的请求。而是请求到达一个servlet前的预处理程序,或响应离开servlet后的后处理程序。它是随你的web应用启动而启动的,只初始化一次,只有当你的web应用停止或重新部署的时候才销毁。过滤器需要实现java.servlet.Filter接口,并定义它的三个方法:
1. void init(): 在过滤器执行服务前被调用,以设置过滤器的配置对象。
2. void destroy():在过滤器执行服务后被调用。
3.void doFilter(): 执行实际的过滤工作。
服务器调用一次init(FilterConfig)为服务准备过滤器,然后在请求需要使用过滤器的时候调用doFilter()。FilterConfig接口检索过滤器名、初始化参数以及活动的servlet上下文。服务器调用destory()以指出过滤器已结束服务。在doFilter()方法中,每个过滤器都接受当前的请求和响应,可以对请求和响应做它想做的一切。过滤器调用chain.doFilter()将控制权传送给下一过滤器。当此调用返回后,过滤器可以在它的doFilter()方法的最后对响应做些其他的工作;例如:记录响应的信息。如果过滤器想要终止请求的处理或得对响应的完全控制,则他可以不调用下一个过滤器。①在web.xml中配置filter
<filter>
<filter-name>requestCheck</filter-name>
<filter-class>filter.requestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestCheck</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>requestCheck</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
filter-name:申明一过滤器名字。
filter-class:指定该过滤器的实现类。
filter-mapping:用来声明Web应用中的过滤器映射,过滤器可被映射到一个servlet或一个URL模式。
url-pattern:表示filter拦截用户请求的类型。如上配置的过滤所有url中带"web/"以及所有的jsp页面。②实现上面配置过滤器的类requeFilter.java
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession(false);
String uri = req.getRequestURI();
try{
if (!uri.contains("/login.jsp")) {
String tag=(String) session.getAttribute("tag");
if ((session == null)||(tag==null)) {
resp.sendRedirect(req.getContextPath() + "/login.jsp");
return;}
}
chain.doFilter(request, response);
}catch(Exception e){
resp.sendRedirect(req.getContextPath() + "/login.jsp");
}
}
public void init(FilterConfig filterConfig) throws ServletException {
}
doFilter
实现的功能是对所有非登录页面的请求执行过滤操作,如果
tomcat
容器保存有当面用户登录的
session
则放行,否则通过
response
重定向到系统的
login.jsp
页面。
③structs.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.i18n.encoding" value="UTF-8" />
<package name="default" namespace="/web" extends="struts-default">
<action name="login" class="action.loginAction" method="login">
<result name="success">/success.jsp</result>
<result name="error">/fail.jsp</result>
</action>
</package>
</struts>
通过登录页面找到处理该action的实现类及方法,验证成功后跳转到success.jsp页面,否则跳转到fail.jsp页面。
处理登录的简单实现:public String login(){
if(username!=null&&password!=null){
if(username.equals("test")&&password.equals("123123")){
HttpSession session=request.getSession();
session.setAttribute("tag", "login");
return SUCCESS;
}else
return ERROR;
}
return ERROR;
}
测试结果一:
直接在浏览器输入: http://192.168.1.110:8080/filterDemo/success.jsp ,由于之前并没有用户登录,因而按照处理逻辑,系统将跳转到 login.jsp:
测试结果二:
直接在浏览器输入:http://192.168.1.110:8080/filterDemo/login.jsp,用户名:test,密码:123123,登录之后系统会自动跳转到success.jsp,此时在浏览器输入:http://192.168.1.110:8080/filterDemo/fail.jsp仍可访问:
说明:session对象用于存储特定的用户会话所需的信息。当用户在应用程序的web之间跳转时,存储在session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当一个用户首次访问服务器上的一个jsp页面时,jsp引擎产生一个session对象,同时分配一个String类型的ID号,jsp引擎发送该ID到客户端,存放在cookie中。当用户再访问链接该服务器的其他页面时,不再分配新的session对象。直到浏览器关闭后,该session对象才取消,下次访问,再创建新的session对象。
然而有时候我们希望不过滤一些页面或者action请求,允许某些特定的页面不用过滤就可以直接访问,如:index.jsp,error.jsp等,修改web.xml配置文件:
<span style="font-family:Microsoft YaHei;font-size:12px;"><filter>
<filter-name>requestCheck</filter-name>
<filter-class>filter.requestFilter</filter-class>
<init-param>
<param-name>notCheck</param-name>
<param-value>/error.jsp,/index.jsp,/login.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>requestCheck</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>requestCheck</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping></span>
可以看出与之前的配置文件相比,多了 init-param , param-name , param-value 等几项参数,用以初始化 filter 的参数,在实现该 filter 的 requestFilter.java 类中,可以方便的读出初始化的值,并进行随后的逻辑处理,修改后的 filter 实现类:
<span style="font-family:Microsoft YaHei;">public class requestFilter implements Filter{
protected FilterConfig filterConfig = null;
private List notCheckList = new ArrayList();
public void destroy() {
// TODO Auto-generated method stub
notCheckList.clear();
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession(false);
String uri = req.getRequestURI();
try{
if ((!notCheckRequest(req))&&(!uri.contains("/login.jsp"))) {
String tag=(String) session.getAttribute("tag");
if ((session == null)||(tag!=null)) {
resp.sendRedirect(req.getContextPath() + "/login.jsp");
return;
}
}
chain.doFilter(request, response);
}catch(Exception e){
resp.sendRedirect(req.getContextPath() + "/login.jsp");
}
}
@SuppressWarnings("unchecked")
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
this.filterConfig = filterConfig;
String notCheck = filterConfig.getInitParameter("notCheck");
if (notCheck != null) {
StringTokenizer st = new StringTokenizer(notCheck, ",");
notCheckList.clear();
while (st.hasMoreTokens()) {
notCheckList.add(st.nextToken());
}
}
}
private boolean notCheckRequest(HttpServletRequest request) {
String uri = request.getServletPath()
+ (request.getPathInfo() == null ? "" : request.getPathInfo());
return notCheckList.contains(uri);
}
}</span>
FilterConfig 对象提供对 servlet 环境及 web.xml 文件中指派的过滤器名的访问。它具有一个 getInitParameter() 方法,它能够访问部署描述符文件( web.xml )中分配的过滤器初始化参数。调用 filterConfig.getInitParameter( "notCheck" ); 得到 < param-value > /error.jsp,/index.jsp,/login.jsp </ param-value > 指定的值。然后将 request 中请求的路径与初始化值进行匹配,存在则放行,否者进入处理逻辑。
测试结果:
*工程所需jar包