上一篇博客中说了一点自定义拦截器的知识。这一篇记录一个自定义拦截器的应用示例,登录功能实现。
1.新建工程:SecondLearnStruts2Chap03;
2.新建一个com.test.model包,并在里面新建一个用户类User:
package com.test.model;
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3.新建一个包com.test.service,并在里面新建一个类UserService,用来判断用户输入的用户名和密码信息是否正确:
package com.test.service;
import com.test.model.User;
public class UserService {
public boolean login(User user){
if("test".equals(user.getUserName()) && "123456".equals(user.getPassword())){
return true;
}else{
return false;
}
}
}
4.新建一个com.test.action包,并新建两个处理类:UserAction和GirlAction
UserAction:
package com.test.action;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.test.model.User;
import com.test.service.UserService;
public class UserAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private UserService userService = new UserService();
private User user;
private String error;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
@Override
public String execute() throws Exception {
if(userService.login(user)){
ActionContext actionContext = ActionContext.getContext();
Map<String, Object> session = actionContext.getSession();
session.put("currentUser", user);
return SUCCESS;
}else{
this.error = "用户名或者密码错误";
return ERROR;
}
}
}
这个类中,如果用户输入的用户名和密码都正确的话,就把用户信息存储到session中并返回success,否则的话返回error。
GirlAction:
package com.test.action;
import com.opensymphony.xwork2.ActionSupport;
public class GirlAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String execute() throws Exception {
System.out.println("请求GirlAction成功");
return SUCCESS;
}
}
5.新建一个拦截器loginInteceptor:
package com.test.interceptor;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class LoginInterceptor implements Interceptor{
@Override
public void destroy() {
// 拦截器销毁时调用
System.out.println("LoginInterceptor销毁");
}
@Override
public void init() {
// 拦截器初始化时调用
System.out.println("LoginInterceptor初始化");
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// 拦截器处理逻辑
System.out.println("在action执行之前");
ActionContext actionContext = invocation.getInvocationContext();
Map<String, Object> session = actionContext.getSession();
Object currentUser = session.get("currentUser");
String result = null;
if(currentUser != null){
result = invocation.invoke();//执行action中的响应函数
}else{
HttpServletRequest request = (HttpServletRequest)invocation.getInvocationContext().get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("error", "请先登录!");
result = "error";
}
System.out.println("result="+result);
System.out.println("在action执行之后");
return result;
}
}
这个拦截器中首先判断session中是否存储了用户信息,如果没有代表用户还没有登录,把错误信息存储在request中并返回error。如果用户信息已经存在,则继续执行action中的响应函数。
6.配置struts.xml:
<struts>
<package name="manage" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="loginInterceptor" class="com.test.interceptor.LoginInterceptor"></interceptor>
</interceptors>
<action name="user" class="com.test.action.UserAction">
<result name="success">success.jsp</result>
<result name="error">error.jsp</result>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
<action name="girl" class="com.test.action.GirlAction">
<result name="success">success.jsp</result>
<result name="error">error.jsp</result>
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
</struts>
运行程序发现只有登录了之后才能够请求girl这个请求,否则都会跳转到error.jsp页面。
7.struts.xml配置文件的优化,这个才是写这篇博客的重点。
1.上面每个action中只要返回error,就会跳转到error.jsp页面。这里可以把跳转到error.jsp这个页面的result写成一个全局result;
<global-results>
<result name="error">error.jsp</result>
</global-results>
2.上面在请求girl的时候会被自定义的拦截器以及默认拦截器拦截,判断当前用户是否登录,只有用户登录后才能请求。如果有上百个请求的话,要引入上百个自定义拦截器以及默认拦截器,这样的话太麻烦。这里可以定义一个拦截器栈,把用到的拦截器都放在拦截器栈中:
<interceptors>
<interceptor name="loginInterceptor" class="com.test.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
这里定义了一个拦截器栈myStack,并在拦截器中引入了自定义拦截器和默认拦截器栈。
3.自定义了拦截器栈还不行,还要在package中使用这个拦截器栈:
<default-interceptor-ref name="myStack"></default-interceptor-ref>
这样的话,package下面所有的action如果没有指定拦截器的话,就会默认使用这个自定义的拦截器栈了。
经过修改后,struts.xml文件为:
<struts>
<package name="manage" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="loginInterceptor" class="com.test.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"></default-interceptor-ref>
<global-results>
<result name="error">error.jsp</result>
</global-results>
<action name="user" class="com.test.action.UserAction">
<result name="success">success.jsp</result>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
<action name="girl" class="com.test.action.GirlAction">
<result name="success">success.jsp</result>
</action>
</package>
</struts>
注意:上面的user请求中指定了使用默认的拦截器,这样的话请求user时就只会使用指定的拦截器而不会使用package中指定的拦截器了。如果不指定的话,请求user时会被自定义的拦截器拦截,判断用户是否登录成功,刚开始当然没有登录,从而会一直停留在登录和error.jsp页面,这样的话就会永远登录不了了。