Struts2自定义拦截器实现权限控制实例(非常详细)

网上购物对于人们并不陌生,当人们浏览购物网站,看中某个商品并选择购买后,如果之前用户没有登录该网站,则页面会跳转到登录页面并提示用户尚未登录;如果用户已登录并单击购买商品时,则会跳转到支付(或结算)页面中进行后续操作。

在上述需求中,对未登录用户的权限控制就可以通过拦截器实现。下面编写案例模拟购物网站流程,要求使用 Struts2 的拦截器实现对用户的权限控制。

1. 创建项目

在 MyEclipse 中创建一个 Web 项目 struts2Demo03,将 Struts2 框架所需的 JAR 包添加到项目 WEB-INF 目录下的 lib 文件夹中,并发布到类路径下。

2. 配置 web.xml 文件

在 web.xml 文件中配置过滤器和首页信息,其配置代码如下所示。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  3. <!-- 定义filter -->
  4. <filter>
  5. <!-- filter名字 -->
  6. <filter-name>struts2</filter-name>
  7. <!-- filter的实现类,此处是Struts2的核心过滤器 -->
  8. <filter-class>
  9. org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  10. </filter-class>
  11. </filter>
  12. <filter-mapping>
  13. <!-- filter的名字,必须是filter元素中已经声明过的过滤器的名字 -->
  14. <filter-name>struts2</filter-name>
  15. <!-- 定义filter负责拦截的URL地址 -->
  16. <url-pattern>/*</url-pattern>
  17. </filter-mapping>
  18. <!-- 首页 -->
  19. <welcome-file-list>
  20. <welcome-file>main.jsp</welcome-file>
  21. </welcome-file-list>
  22. </web-app>

3. 创建用户实体类

在 src 目录下创建一个名为 com.mengma.domain 的包,在该包下创建 User 类,如下所示。
  1. package com.mengma.domain;
  2.  
  3. public class User {
  4. private String username; // 用户名
  5. private String password; // 密码
  6.  
  7. public String getUsername() {
  8. return username;
  9. }
  10.  
  11. public void setUsername(String username) {
  12. this.username = username;
  13. }
  14.  
  15. public String getPassword() {
  16. return password;
  17. }
  18.  
  19. public void setPassword(String password) {
  20. this.password = password;
  21. }
  22. }
在 User 类中,定义了 username 和 password 两个属性,以及其 getter 和 setter 方法。

4. 创建 Action

1)创建登录 Action。在 src 目录下创建包 com.mengma.action,在该包下创建 LoginAction 类,编辑后如下所示。
  1. package com.mengma.action;
  2.  
  3. import com.mengma.domain.User;
  4. import com.opensymphony.xwork2.ActionContext;
  5. import com.opensymphony.xwork2.ActionSupport;
  6. import com.opensymphony.xwork2.ModelDriven;
  7.  
  8. public class LoginAction extends ActionSupport implements ModelDriven<User> {
  9.  
  10. private static final long serialVersionUID = -8493698886438630994L;
  11. private User user = new User();
  12.  
  13. @Override
  14. public User getModel() {
  15. return user;
  16. }
  17.  
  18. public String execute() throws Exception {
  19. // 获取ActionContext
  20. ActionContext actionContext = ActionContext.getContext();
  21. if ("admin".equals(user.getUsername())
  22. && "123456".equals(user.getPassword())) {
  23. // 将用户存储在session中
  24. actionContext.getSession().put("user", user);
  25. return SUCCESS;
  26. } else {
  27. actionContext.put("msg", "用户名或密码错误,请重新登录!");
  28. return INPUT;
  29. }
  30. }
  31. }
2)创建商品 Action。在 com.mengma.action 包下创建 BookAction 类,编辑后如下所示。
  1. package com.mengma.action;
  2.  
  3. import com.opensymphony.xwork2.ActionSupport;
  4. public class BookAction extends ActionSupport {
  5. private static final long serialVersionUID = 5640989517690867879L;
  6. // 购买图书
  7. public String buy() {
  8. return SUCCESS;
  9. }
  10. }

5. 创建拦截器

通过之前对拦截器的学习,可以将自定义拦截器的使用过程分为以下三步。
  1. 用户自定义的拦截器类,必须实现 Interceptor 接口或继承 AbstractInterceptor 类。
  2. 需要在 Struts.xml 中定义自定义的拦截器。
  3. 在 Struts.xml 中的 Action 中使用拦截器。

下面就按照上述步骤创建拦截器。

1)创建拦截器类。在 src 目录下创建一个名称为 com.mengma.interceptor 的包,在该包下创建一个名称为 PrivilegeInterceptor.java 的文件,如下所示。
  1. package com.mengma.interceptor;
  2.  
  3. import com.opensymphony.xwork2.Action;
  4. import com.opensymphony.xwork2.ActionContext;
  5. import com.opensymphony.xwork2.ActionInvocation;
  6. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
  7.  
  8. public class PrivilegeInterceptor extends AbstractInterceptor {
  9.  
  10. private static final long serialVersionUID = 193664972753450682L;
  11.  
  12. @Override
  13. public String intercept(ActionInvocation invocation) throws Exception {
  14. // 得到 ActionContext
  15. ActionContext actionContext = invocation.getInvocationContext();
  16. // 获取User对象
  17. Object user = actionContext.getSession().get("user");
  18. if (user != null) {
  19. return invocation.invoke(); // 继续向下执行
  20. } else {
  21. actionContext.put("msg", "您还未登录,请先登录!");
  22. return Action.LOGIN; // 如果用户不存在,则返回login值
  23. }
  24. }
  25. }
2)配置 struts.xml 文件。在 src 目录下创建 struts.xml 文件,此文件用于声明自定义拦截器、拦截器栈以及对 book 操作的 Action,其代码如下所示。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
  4. "http://struts.apache.org/dtds/struts-2.3.dtd">
  5. <struts>
  6. <package name="struts2" namespace="/" extends="struts-default">
  7. <!-- 声明拦截器 -->
  8. <interceptors>
  9. <interceptor name="privilege"
  10. class="com.mengma.interceptor.PrivilegeInterceptor" />
  11. <interceptor-stack name="myStack">
  12. <interceptor-ref name="defaultStak" />
  13. <interceptor-ref name="privilege" />
  14. </interceptor-stack>
  15. </interceptors>
  16. <!-- 用户登录操作 -->
  17. <action name="login" class="com.mengma.action.LoginAction">
  18. <result>/main.jsp</result>
  19. <result name="input">/login.jsp</result>
  20. </action>
  21. <!-- 关于book操作 -->
  22. <action name="book_*" class="com.mengma.action.BookAction"
  23. method="{1}">
  24. <result>/success.jsp</result>
  25. <result name="login">/login.jsp</result>
  26. <!-- 在action中使用自定义拦截器 -->
  27. <interceptor-ref name="myStack" />
  28. </action>
  29. </package>
  30. </struts>
在 struts.xml 中,首先声明了一个名称为 privilege 的拦截器,并将该拦截器放入自定义的拦截器栈 myStack 中;然后配置了用户登录的 action 信息;最后定义了关于对页面 book 操作的 action 信息,并在该 action 中引用自定义的拦截器栈 myStack。

6. 创建显示页面

在 WebContent 目录下创建三个视图页面,分别为主页 main.jsp、登录页面 login.jsp 和操作成功页面 success.jsp。其中主页 main.jsp 的代码如下所示。
  1. <%@ page language="java" contentType="text/html; charset=utf-8"
  2. pageEncoding="utf-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  7. <title>主页</title>
  8. </head>
  9. <body>
  10. <table border="0">
  11. <tr>
  12. <td>《SSH框架整合实战教程》</td>
  13. <td><a href="/struts2Demo03/book_buy">购买</a></td>
  14. </tr>
  15. </table>
  16. </body>
  17. </html>
登录页面 login.jsp 的代码如下所示。
  1. <%@ page language="java" contentType="text/html; charset=utf-8"
  2. pageEncoding="utf-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <title>登录</title>
  7. <style type="text/css">
  8. input[type=text],input[type=password]{width:150px}
  9. </style>
  10. </head>
  11. <body>
  12. <div align="center">
  13. <form action="/struts2Demo03/login.action" method="post">
  14. <table>
  15. <tr>
  16. <td><label style="text-align:right;">用戶名:</label></td>
  17. <td><input type="text" name="username"></td>
  18. <td><span style="color:#F00">${requestScope.msg }</span></td>
  19. </tr>
  20. <tr>
  21. <td><label style="text-align:right;">&nbsp;&nbsp;&nbsp;&nbsp;码:</label></td>
  22. <td><input type="password" name="password"></td>
  23. </tr>
  24. <tr>
  25. <td align="right" colspan="2"><input type="submit" value="登录"></td>
  26. </tr>
  27. </table>
  28. </form>
  29. </div>
  30. </body>
  31. </html>
操作成功页面 success.jsp 的代码如下所示。
  1. <%@ page language="java" contentType="text/html; charset=utf-8"
  2. pageEncoding="utf-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <title>成功页面</title>
  7. </head>
  8. <body>
  9. 尊敬的会员${user.username },您已成功购买商品,祝您购物愉快!
  10. </body>
  11. </html>

7. 运行项目并查看结果

启动 struts2Demo03 项目,在浏览器的地址栏中输入地址 http://localhost:8080/struts2Demo03/main.jsp 访问其主页,浏览器的显示结果如图 1 所示。

主页
图 1  主页

当单击购买链接后,页面将跳转到登录页面中,并提示用户登录,如图 2 所示。

登录页面
图 2  登录页面

如果输入错误的用户名和密码,将提示用户名或密码错误信息,如图 3 所示。

登录页面
图 3  登录页面

当输入正确的用户名和密码并登录成功后,会再次跳转到主页,此时如果单击购买链接,将提示用户已经成功购买商品,如图 4 所示。

成功页面
图 4  成功页面