查看本例之前首先要大概了解struts2的理论知识(点击查看)
本例实现了一个权限拦截器!
需求:要求用户登录,且必须为指定用户名才可以查看系统中的某个视图资源,如果不满足这两个条件,系统直接转入登录页面!
问题:怎样检查用户登录?
答:跟踪用户的HTTP Session
实现方式有两种:
1.在每个action执行处理逻辑之前,先执行权限检查!但是多了很多重复代码,这是我们不愿意看到的!
2.将权限检查逻辑放在拦截器中,解决了方法一种重复代码的问题!
下面以第二种实现方式实现这个实例:
步骤:
1.搭建struts2环境(点击查看详细搭建过程)
2.实现拦截器类(继承AbstractInterceptor)
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class AuthorityInterceptor extends AbstractInterceptor{
//拦截action处理的拦截方法
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//取得请求相关的ActionContext实例
ActionContext act=invocation.getInvocationContext();
//取出名为user的session属性
String user = (String)act.getSession().get("user");
//如果user不为空且用户名是test
if(user!=null&&"test".equals(user)){
//放行到下一个拦截器或者action中的方法
return invocation.invoke();
}
((ActionSupport)invocation.getAction()).addActionError("sorry,还没有登录");
//直接返回login逻辑视图
return Action.LOGIN;
}
}
3.实现Action
package action;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
/**
*
* @author User
*
*/
public class LoginAction extends ActionSupport{
private String userName;
private String pwd;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String execute() throws Exception {
//用户名是lee密码是123或者用户名是test密码是123都是正确的用户名和密码 if("lee".equals(getUserName())||"test".equals(getUserName())&&"123".equals(getPwd())){
//获取session
Map<String, Object> session = ActionContext.getContext().getSession();
session.put("user", getUserName());
return SUCCESS;
}else{
ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.set("error", "请输入正确的用户名和密码");
return INPUT;
}
}
//查看图书列表
public String view() throws Exception {
return SUCCESS;
}
}
4.编写jsp页面
4.1loginForm.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!--引入struts2标签 -->
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'traditional.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
${error}
<s:form action="test/loginPro" method="post">
<s:textfield name="userName" label="用户名"/>
<s:textfield name="pwd" label="密码"/>
<s:submit value="提交"/>
</s:form>
</body>
</html>
4.2viewBook.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!--引入struts2标签 -->
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'traditional.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
图书展示
</body>
</html>
4.3viewRequest.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!--引入struts2标签 -->
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'traditional.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<a href="test/viewBook">点击查看图书</a>
</body>
</html>
5.配置struts.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>
<!-- 包为lee -->
<package name="lee" extends="struts-default" namespace="/test" >
<!-- 配置拦截器 -->
<interceptors>
<interceptor name="authority" class="interceptor.AuthorityInterceptor"></interceptor>
</interceptors>
<!-- 定义全局result (因为大部分action都要跳到loginForm.jsp页面,避免写重复代码,所以定义全局result)-->
<global-results>
<result name="login">/WEB-INF/content/loginForm.jsp</result>
</global-results>
<!-- 配置action -->
<!-- 若没有指定class属性 默认使用ActionSupport -->
<action name="viewBook" class="action.LoginAction" method="view">
<!-- 通过拦截器的检查会调到viewBook.jsp页面 -->
<result name="success">/WEB-INF/content/viewBook.jsp</result>
<!-- 引用默认拦截器 因为action中显示应用了authority拦截器-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<!-- 使用自定义的拦截器 -->
<interceptor-ref name="authority">
</interceptor-ref>
</action>
<action name="loginPro" class="action.LoginAction">
<!-- 登录成功以后,转到下一个action -->
<result name="success" type="chain">viewBook</result>
<!-- 当输入的账号密码是错误的 跳到loginForm.jsp页面 -->
<result name="input">/WEB-INF/content/loginForm.jsp</result>
</action>
<!--配置action 这个action可以处理各种请求 目的是为了保护jsp页面 将jsp页面放在WEB-INF下 这个action一般放在所有action之后 -->
<action name="*">
<!--直接跳到*所代表的页面 -->
<result>/WEB-INF/content/{1}.jsp</result>
</action>
</package>
</struts>
代码编写完毕,查看文件结构(使用myEclipse作为开发工具,tomcat作为服务器)
发布以后测试:
测试分为六种情况
情况一:用户没有登录直接访问viewBook.jsp页面
地址:http://127.0.0.1:8080/struts2Study37/test/viewBook
结果:跳转到loginForm.jsp页面
分析:当输入这个地址以后,发送test/viewBook请求,该请求被权限拦截器拦截(struts.xml中配置了),拦截器检测到用户没有登录,执行拦截器中的return Action.LOGIN;代码,于是跳转到loginForm.jsp页面!
情况二:用户访问loginForm.jsp页面,输入错误的账号和密码
地址:http://127.0.0.1:8080/struts2Study37/test/loginForm
结果:仍在loginForm.jsp页面,提示请输入正确的账号和密码
分析:点击登录之后,发送的是test/loginPro请求,该请求拦截器不拦截(struts.xml配置了),执行loginAction中的execute方法,用户名和密码不匹配,执行execute方法中的return INPUT;代码,于是跳转到loginForm.jsp页面
情况三:用户访问loginForm.jsp页面,输入正确的账号和密码(账号是lee密码是123)
地址:http://127.0.0.1:8080/struts2Study37/test/loginForm
结果:仍在loginForm.jsp页面
分析:点击登录以后,发送test/loginPro请求,执行loginAction中的execute方法,用户名和密码匹配,执行execute方法中的return SUCCESS;代码,于是跳转到viewBook这个action(struts.xml中配置了),这个请求拦截器会进行拦截,检测到用户虽然登录,但是用户名不匹配,执行拦截器中的return Action.LOGIN;代码,于是跳转到loginForm.jsp页面!
情况四:用户访问loginForm.jsp页面,输入正确的账号和密码(账号是test密码是123)
地址:http://127.0.0.1:8080/struts2Study37/test/loginForm
结果:出现“图书展示”四个大字
分析:点击登录以后,发送test/loginPro请求,执行loginAction中的execute方法,用户名和密码匹配,执行execute方法中的return SUCCESS;代码,于是跳转到viewBook这个action(struts.xml中配置了),这个请求拦截器会进行拦截,检测到用户登录,而且用户名匹配,执行拦截器放行,执行loginAction中的view()方法,于是跳转到viewBook.jsp页面!
情况五:用户直接在地址栏中输入http://127.0.0.1:8080/struts2Study37/test/viewBook
结果:出现“图书展示”四个大字
分析:当输入这个地址以后,发送test/viewBook请求,该请求被权限拦截器拦截(struts.xml中配置了),拦截器检测到用户已经登录且用户名匹配,执行拦截器放行,执行loginAction中的view()方法,于是跳转到viewBook.jsp页面!
情况六:超过一定时间、服务器重启、浏览器关闭后,再输入http://127.0.0.1:8080/struts2Study37/test/viewBook
结果:跳转到loginForm.jsp页面
分析:session已经失效,若要出现情况五的结果,需要再次执行情况四的步骤!