Here is a interceptor example in ssh structure web application.
First of all, I write a login interceptor and add it into default interceptor stack. It only can print out on console without any other function as a demo how an interceptor works.
struts.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
4 "http://struts.apache.org/dtds/struts-2.0.dtd">
5 <struts>
6 <package name="sshlogin" extends="struts-default">
7 <interceptors>
8 <interceptor name="loginInterceptor" class="attempLoginIterceptor"></interceptor>
9 <interceptor-stack name="loginDefaultStack">
10 <interceptor-ref name="loginInterceptor"></interceptor-ref>
11 <interceptor-ref name="defaultStack"></interceptor-ref>
12 </interceptor-stack>
13 </interceptors>
14
15 <default-interceptor-ref name="loginDefaultStack"></default-interceptor-ref>
16
17 <action name="login" class="loginAction" method="login">
18 <result name="success">/user.jsp</result>
19 <result name="input">/login.jsp</result>
20 <interceptor-ref name="defaultStack"></interceptor-ref>
21 </action>
22
23 <action name="register" class="registerAction" method="register">
24 <result name="success">/user.jsp</result>
25 <result name="input">/register.jsp</result>
26 <interceptor-ref name="defaultStack"></interceptor-ref>
27 </action>
28
29 <action name="post" class="postAction" method="post">
30 <result name="success"></result>
31 <result name="login">/login.jsp</result>
32 <result name="input">/user.jsp</result>
33 </action>
34
35 <action name="logout" class="logoutAction" method="logout">
36 <result name="input">/login.jsp</result>
37 <result name="login">/login.jsp</result>
38 </action>
39 </package>
40 </struts>
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="
5 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
6
7 <!-- <bean/> definitions here -->
8 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
9 <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
10 <property name="url" value="jdbc:mysql://localhost:3306/blogjava"></property>
11 <property name="username" value="root"></property>
12 <property name="password" value="123456789"></property>
13 <property name="maxActive" value="100"></property>
14 <property name="maxIdle" value="30"></property>
15 <property name="maxWait" value="500"></property>
16 <property name="defaultAutoCommit" value="true"></property>
17 </bean>
18 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
19 <property name="dataSource" ref="dataSource"></property>
20 <property name="hibernateProperties">
21 <props>
22 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
23 <prop key="show_sql">true</prop>
24 </props>
25 </property>
26 <property name="mappingResources">
27 <list>
28 <value>com/ssh/bean/User.hbm.xml</value>
29 <value>com/ssh/bean/Poster.hbm.xml</value>
30 </list>
31 </property>
32 </bean>
33
34 <bean id="userDao" class="com.ssh.dao.impl.UserDaoImpl" scope="singleton">
35 <property name="sessionFactory">
36 <ref bean="sessionFactory"/>
37 </property>
38 </bean>
39
40 <bean id="userService" class="com.ssh.service.impl.UserServiceImpl">
41 <property name="userDao">
42 <ref bean="userDao"/>
43 </property>
44 </bean>
45
46 <bean id="loginAction" class="com.ssh.action.LoginAction" scope="prototype">
47 <property name="userService">
48 <ref bean="userService"/>
49 </property>
50 </bean>
51
52 <bean id="registerAction" class="com.ssh.action.RegisterAction" scope="prototype">
53 <property name="userService">
54 <ref bean="userService"></ref>
55 </property>
56 </bean>
57
58 <bean id="attempLoginIterceptor" class="com.ssh.interceptor.LoginInterceptor">
59 <property name="userService">
60 <ref bean="userService"/>
61 </property>
62 </bean>
63
64 <bean id="posterDao" class="com.ssh.dao.impl.PosterDaoImpl" scope="singleton">
65 <property name="sessionFactory">
66 <ref bean="sessionFactory"/>
67 </property>
68 </bean>
69
70 <bean id="posterService" class="com.ssh.service.impl.PosterServiceImpl">
71 <property name="posterDao">
72 <ref bean="posterDao"/>
73 </property>
74 </bean>
75
76 <bean id="postAction" class="com.ssh.action.PostAction" scope="prototype">
77 <property name="posterService">
78 <ref bean="posterService"/>
79 </property>
80 </bean>
81
82 <bean id="logoutAction" class="com.ssh.action.LogoutAction" scope="prototype"></bean>
83 </beans>
Notice: now I set default-interceptor-stack to newly defined interceptor stack 'loginDefaultStack'.
Create package com.ssh.interceptor and create LoginInterceptor extends AbstractInterceptor under this package.
LoginInterceptor.java
1 package com.ssh.interceptor;
2
3 import com.opensymphony.xwork2.ActionInvocation;
4 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
5
6 public class LoginInterceptor extends AbstractInterceptor {
7
8 @Override
9 public String intercept(ActionInvocation ai) throws Exception {
10 // TODO Auto-generated method stub
11 System.out.println("===============Interceptor===============");
12 return ai.invoke();
13 }
14 }
After each login action, ===============Interceptor=============== is printed out on console.
The real function of logininteceptor can do a lot more than simply printing. When web browser is trying to open certain pages, first check this browser whether it has already login, if it has, then alow this browser continuing browse this page, however, if it hasn't, then application needs to have a function that block the browser to open this page and redirect it to login page, let the user login first.
Now, I will introduce it by using struts2 interceptor and javax.servlet.http.Cookie;
Let's create interceptor first. Create package com.ssh.interceptor and create LoginInterceptor.java under it. This interceptor can interceptor all the actions except login action itself, of course, it's a dead loop if interceptor block all the action. Meanwhile, register action which allow any new user registering on server isn't intercepted neither.
LoginInterceptor.java
1 package com.ssh.interceptor;
2 /**
3 * qsl
4 * Jun-25-2009
5 *
6 * session is only for current session which means the current opened browser.
7 * cookies is for 'remember me' option at user side. User can choose to decide
8 * whether they want to save their login information at client side.
9 * */
10 import java.util.Map;
11 import javax.servlet.http.Cookie;
12 import javax.servlet.http.HttpServletRequest;
13 import org.apache.commons.lang.StringUtils;
14 import org.apache.struts2.StrutsStatics;
15 import com.ssh.exception.UserNotFoundException;
16 import com.ssh.bean.User;
17 import com.ssh.service.UserService;
18 import com.opensymphony.xwork2.ActionContext;
19 import com.opensymphony.xwork2.ActionInvocation;
20 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
21
22
23 public class LoginInterceptor extends AbstractInterceptor {
24 private UserService userService;
25
26 public static final String USER_SESSION_KEY="usersession";
27 public static final String COOKIE_REMEMBERME_KEY="rememberme";
28 public static final String GOING_TO_URL_KEY="GOINGTO";
29
30 public void setUserService(UserService userService) {
31 this.userService = userService;
32 }
33 private void setGoingToURL(Map session, ActionInvocation invocation){
34 String url = "";
35 String namespace = invocation.getProxy().getNamespace();
36 if (StringUtils.isNotBlank(namespace) && !namespace.equals("/")){
37 url = url + namespace;
38 }
39 String actionName = invocation.getProxy().getActionName();
40 if (StringUtils.isNotBlank(actionName)){
41 url = url + "/" + actionName + ".action";
42 }
43 session.put(GOING_TO_URL_KEY, url);
44 }
45 @Override
46 public String intercept(ActionInvocation invocation) throws Exception {
47 // TODO Auto-generated method stub
48 ActionContext actionContext = invocation.getInvocationContext();
49 HttpServletRequest request= (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
50
51 /**
52 * if user still stays in the current session, continue allowing user's action
53 * */
54 Map session = actionContext.getSession();
55 if (session != null && session.get(USER_SESSION_KEY) != null){
56 return invocation.invoke();
57 }
58
59 /**
60 * if user is not in the current session, but user have chosen 'remember me' and save
61 * their username and password in their cookies, read the corresponding cookies' value.
62 *
63 * Cons: not very safe.
64 */
65 Cookie[] cookies = request.getCookies();
66 if (cookies!=null) {
67 for (Cookie cookie : cookies) {
68 if (COOKIE_REMEMBERME_KEY.equals(cookie.getName())) {
69 String value = cookie.getValue();
70 if (StringUtils.isNotBlank(value)) {
71 String[] split = value.split("==");
72 String userName = split[0];
73 String password = split[1];
74 try {
75 User user = userService
76 .attemptLogin(userName, password);
77 session.put(USER_SESSION_KEY, user);
78 } catch (UserNotFoundException e) {
79 setGoingToURL(session, invocation);
80 return "login";
81 }
82 } else {
83 setGoingToURL(session, invocation);
84 return "login";
85 }
86 return invocation.invoke();
87 }
88 }
89 }
90 setGoingToURL(session, invocation);
91 return "login";
92 }
93 }
Edit LoginAction.java:
1 package com.ssh.action;
2 /**
3 * qsl
4 * Jun-25-2009
5 *
6 * session is only for current session which means the current opened browser.
7 * cookies is for 'remember me' option at user side. User can choose to decide
8 * whether they want to save their login information at client side.
9 * */
10 import java.util.List;
11 import java.util.Map;
12
13 import javax.servlet.http.Cookie;
14 import javax.servlet.http.HttpServletRequest;
15 import javax.servlet.http.HttpServletResponse;
16
17 import org.apache.struts2.interceptor.CookiesAware;
18 import org.apache.struts2.interceptor.ServletRequestAware;
19 import org.apache.struts2.interceptor.ServletResponseAware;
20 import org.apache.struts2.interceptor.SessionAware;
21
22 import com.opensymphony.xwork2.ActionSupport;
23 import com.ssh.bean.User;
24 import com.ssh.interceptor.LoginInterceptor;
25 import com.ssh.service.UserService;
26
27 public class LoginAction extends ActionSupport implements ServletResponseAware,
28 ServletRequestAware, SessionAware, CookiesAware{
29 private UserService userService;
30 private User user;
31 private HttpServletResponse response;
32 private HttpServletRequest request;
33 private Map session;
34 private Map cookies;
35 private String goingToURL;
36
37 public void setUserService(UserService userService) {
38 this.userService = userService;
39 }
40
41 public User getUser() {
42 return user;
43 }
44
45 public void setUser(User user) {
46 this.user = user;
47 }
48
49 public String getGoingToURL() {
50 return goingToURL;
51 }
52
53 public void setGoingToURL(String goingToURL) {
54 this.goingToURL = goingToURL;
55 }
56
57 @Override
58 public void setCookiesMap(Map cookies) {
59 // TODO Auto-generated method stub
60 this.cookies = cookies;
61 }
62
63 @Override
64 public void setServletResponse(HttpServletResponse response) {
65 // TODO Auto-generated method stub
66 this.response = response;
67 }
68
69 @Override
70 public void setServletRequest(HttpServletRequest request) {
71 // TODO Auto-generated method stub
72 this.request = request;
73 }
74
75 @Override
76 public void setSession(Map<String, Object> session) {
77 // TODO Auto-generated method stub
78 this.session = session;
79 }
80
81 public String login(){
82 List<User> users = this.userService.findAll();
83 if(users == null || users.isEmpty())
84 return INPUT;
85 for(int i=0; i<users.size(); i++){
86 User u = users.get(i);
87 if(u.getUsername().equals(user.getUsername())){
88 if(u.getPassword().equals(user.getPassword())){
89 Cookie cookie = new Cookie(LoginInterceptor.COOKIE_REMEMBERME_KEY,
90 user.getUsername() + "==" + user.getPassword());
91 cookie.setMaxAge(60 * 60 * 24 * 14);
92 response.addCookie(cookie);
93 session.put(LoginInterceptor.USER_SESSION_KEY, user);
94 return SUCCESS;
95 }
96 else
97 continue;
98 }else
99 continue;
100 }
101 return INPUT;
102 }
103 /*
104 @Override
105 public void validate() {
106 // TODO Auto-generated method stub
107 if(null == this.user.getUsername() || "".equals(this.user.getUsername()))
108 this.addFieldError("username", "username is null");
109 if(null == this.user.getPassword() || "".equals(this.user.getPassword()))
110 this.addFieldError("password", "password is null");
111 }
112 */
113 }
114
Now create a page which can post an artile on server, but the post action is intecepted, which means only the login user can post articles. If browser didn't login, then application jumps to login page.
User.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
3 <%@ taglib prefix="s" uri="/struts-tags"%>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5 <html>
6 <head>
7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8 <title>User</title>
9 </head>
10 <body>
11 <h2 align="center">Poster</h2>
12 <s:set name="user" value="%{#session.usersession}"></s:set>
13 <s:if test="#user != null">
14 Welcome, ${sessionScope.usersession.username } <br>
15 <s:a href="logout.action">logout</s:a>
16 </s:if>
17 <s:else>
18 <s:a href="login.jsp">Please login first</s:a>
19 </s:else>
20 <s:form action="post" theme="simple">
21 <table style="border-collapse: collapse" align="center"
22 bordercolor=#3f8805 cellspacing=0 cellpadding=0 width="50%" border=1>
23 <tr>
24 <td>title</td>
25 <td><s:fielderror cssStyle="color:red">
26 <s:param>poster.title</s:param>
27 </s:fielderror> <s:textfield name="poster.title"></s:textfield></td>
28 </tr>
29
30 <tr>
31 <td>content</td>
32 <td><s:fielderror cssStyle="color:red">
33 <s:param>poster.content</s:param>
34 </s:fielderror> <s:textarea name="poster.content" cols="60" rows="5"
35 maxlength="5000"></s:textarea></td>
36 </tr>
37 <tr>
38 <td></td>
39 <td><s:submit></s:submit> <s:reset></s:reset></td>
40 </tr>
41 </table>
42 </s:form>
43 </body>
44 </html>
In this User.jsp, I use <s:if> to check whether the user has login or not. If login, then, display Welcome, username. If not, there's a link to login.jsp.
If user doesn't login and try to submit article, then inteceptor will block current operation and lead user to login.jsp.
LogoutAction.java
1 package com.ssh.action;
2
3 import javax.servlet.http.Cookie;
4 import javax.servlet.http.HttpServletRequest;
5 import javax.servlet.http.HttpServletResponse;
6 import javax.servlet.http.HttpSession;
7
8 import org.apache.struts2.interceptor.ServletRequestAware;
9 import org.apache.struts2.interceptor.ServletResponseAware;
10
11 import com.opensymphony.xwork2.ActionSupport;
12 import com.ssh.interceptor.LoginInterceptor;
13
14 public class LogoutAction extends ActionSupport implements ServletRequestAware,
15 ServletResponseAware {
16 private HttpServletRequest request;
17 private HttpServletResponse response;
18
19 public String logout() throws Exception {
20 HttpSession session = request.getSession(false);
21 if (session != null)
22 session.removeAttribute(LoginInterceptor.USER_SESSION_KEY);
23
24 Cookie[] cookies = request.getCookies();
25 if (cookies != null) {
26 for (Cookie cookie : cookies) {
27 if (LoginInterceptor.COOKIE_REMEMBERME_KEY.equals(cookie
28 .getName())) {
29 cookie.setValue("");
30 cookie.setMaxAge(0);
31 response.addCookie(cookie);
32 return "login";
33 }
34 }
35 }
36 return "login";
37 }
38
39 public void setServletRequest(HttpServletRequest request) {
40 this.request = request;
41 }
42
43 public void setServletResponse(HttpServletResponse response) {
44 this.response = response;
45 }
46 }
login.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
3 <%@ taglib prefix="s" uri="/struts-tags"%>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5 <html>
6 <head>
7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8 <title>Login</title>
9 </head>
10 <body>
11 <%-- action="login" actually can work with this error. --%>
12 <s:form action="login" theme="simple">
13 <table style="border-collapse: collapse" align="left"
14 bordercolor=#3f8805 cellspacing=0 cellpadding=0 width="20%" border=1>
15 <tr>
16 <td>username</td>
17 <td>
18 <s:fielderror name="user" cssStyle="color:red">
19 <s:param>user.username</s:param>
20 </s:fielderror>
21 <s:textfield name="user.username"></s:textfield>
22 </td>
23 </tr>
24
25 <tr>
26 <td>password</td>
27 <td>
28 <s:fielderror name="user" cssStyle="color:red">
29 <s:param>user.password</s:param>
30 </s:fielderror>
31 <s:password name="user.password"></s:password>
32 </td>
33 </tr>
34 <tr>
35 <td></td>
36 <td>
37 <s:submit></s:submit>
38 <s:reset></s:reset>
39 </td>
40 </tr>
41 </table>
42 </s:form>
43 </body>
44 </html>
struts.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
4 "http://struts.apache.org/dtds/struts-2.0.dtd">
5 <struts>
6 <package name="sshlogin" extends="struts-default">
7 <interceptors>
8 <interceptor name="loginInterceptor" class="attempLoginIterceptor"></interceptor>
9 <interceptor-stack name="loginDefaultStack">
10 <interceptor-ref name="loginInterceptor"></interceptor-ref>
11 <interceptor-ref name="defaultStack"></interceptor-ref>
12 </interceptor-stack>
13 </interceptors>
14
15 <default-interceptor-ref name="loginDefaultStack"></default-interceptor-ref>
16
17 <action name="login" class="loginAction" method="login">
18 <result name="success">/user.jsp</result>
19 <result name="input">/login.jsp</result>
20 <interceptor-ref name="defaultStack"></interceptor-ref>
21 </action>
22
23 <action name="register" class="registerAction" method="register">
24 <result name="success">/user.jsp</result>
25 <result name="input">/register.jsp</result>
26 <interceptor-ref name="defaultStack"></interceptor-ref>
27 </action>
28
29 <action name="post" class="postAction" method="post">
30 <result name="success"></result>
31 <result name="login">/login.jsp</result>
32 <result name="input">/user.jsp</result>
33 </action>
34
35 <action name="logout" class="logoutAction" method="logout">
36 <result name="input">/login.jsp</result>
37 <result name="login">/login.jsp</result>
38 </action>
39 </package>
40 </struts>