需要实现的功能:判断用户是否已登录,未登录用户禁止访问任何页面或action,自动跳转到登录页面。
过程很艰辛,虽然是挺简单的应用,但是自己也弄了好久才有些许弄明白,结合网上搜索到的内容写下这篇总结,待日后可回头查看。
刚开始是先搜了拦截器如何拦截未登录用户的操作的,正是初生牛犊不怕虎,找到一篇文章就死怼,怼到后面发现不大对,虽然action是拦截掉了,但是jsp怎么样都拦截不到,直接输入.jsp的url还是能访问到网页。苦思冥想,想不出如何做才行。后面发现拦截器本就不能拦截jsp页面、图片等其他资源,拦截器由spring管理,只对action起作用。
于是搜索过滤器的内容,发现过滤器则能过滤所有内容,过滤器的范围要大于拦截器。那就把两者结合起来用吧,反正拦截器已写好,只需写过滤jsp页面的过滤器即可。
过滤器filter实现:
配置web.xml
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>xu.ssh.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
代码:
package xu.ssh.filter;
import java.io.IOException;
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.HttpServletResponse;
import javax.servlet.http.HttpSession;
import xu.ssh.domain.Employee;
public class LoginFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 获得在下面代码中要用的request,response,session对象
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
HttpSession session = servletRequest.getSession();
// 获得用户请求的URI
String path = servletRequest.getRequestURI();
// System.out.println(path);
// 从session里取员工工号信息
Employee employee = (Employee) session.getAttribute("existEmployee");
/*
* 创建类Constants.java,里面写的是无需过滤的页面 for (int i = 0; i <
* Constants.NoFilter_Pages.length; i++) { if
* (path.indexOf(Constants.NoFilter_Pages[i]) > -1) {
* chain.doFilter(servletRequest, servletResponse); return; } }
*/
// 登陆页面无需过滤
if (path.indexOf("/login.jsp") > -1) {
chain.doFilter(servletRequest, servletResponse);
return;
}
// 判断如果没有取到员工信息,就跳转到登陆页面
if ("".equals(employee) || employee == null) {
// 跳转到登陆页面
servletResponse.sendRedirect("/ssh_employee/login.jsp");
} else {
// 已经登陆,继续此次请求
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
配置中的filter-mapping,定义的是需过滤的请求类型,上面的配置即过滤所有对jsp页面的请求。过滤器的实现与struts2、spring框架无关,在用户请求被相应前执行,在过滤器中,可使用response.sendRedirect(“”)等方法
跳转到需要的链接,如登录页面、错误页面等,不需要跳转时,chain.doFilter(request, response);即可继续执行用户的请求。注意使用filter时避免连续两次跳转,否则会报java.lang.IllegalStateException错误,除非必要,不建议使用/*(过滤所有访问)的配置方式,这样配置,图片、js文件、css文件等访问都会被过滤
拦截器interceptor实现:
配置:struts.xml
<!-- 拦截器 -->
<interceptors>
<interceptor name="myInterceptor" class="xu.ssh.action.MyInterceptor"></interceptor>
<interceptor-stack name="myInterceptor">
<interceptor-ref name="myInterceptor">
<param name="excludeMethods">login</param><!-- 不拦截的方法-->
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 将上述拦截器设定为默认拦截器 ,这样在后续同一个package内部的所有Action执行之前都会被login拦截。-->
<default-interceptor-ref name="myInterceptor" />
代码:
package xu.ssh.action;
import org.apache.struts2.ServletActionContext;
import xu.ssh.domain.Employee;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class MyInterceptor extends MethodFilterInterceptor{
/**
* @param args
*/
@Override
protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
Employee employee = (Employee) ServletActionContext.getRequest().getSession().getAttribute("existEmployee");
if(employee!=null){
// is logined ,have the userinfo in the session
return actionInvocation.invoke();//递归调用拦截器
}else{
//is not logged
ActionSupport support = (ActionSupport) actionInvocation.getAction();
support.addActionError("请先登录:)");
return "loginfail";//返回到登录页面
}
}
}
拦截器截获用户对action的访问,如需要跳转,只需如action一样返回一个result,spring根据result的配置执行跳转。如无需跳转,可调用invocation.invoke();方法来执行用户请求的action。拦截器在action之前开始,在action完成后结束(如被拦截,action根本不执行)