Struts2框架(七)
拦截器的应用
一般网站为了防止有人恶意登录(未登录就直接访问后台页面),都会用拦截器Interceptor来限制登录。
下边是一个拦截器登录限制和下载文件限制的一个例子,帮助理解和应用拦截器。
操作步骤如下:
第一步:创建一个登录页面login.html.代码如下。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="js/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="js/themes/icon.css">
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.easyui.min.js"></script>
<script type="text/javascript" src="js/easyui-lang-zh_CN.js"></script>
<script type="text/javascript">
$(function(){
//在这里编写jquery easyui的代码
$('#ff').dialog({
title: '登录界面',
width: 300,
height: 160,
closed: false,
cache: false,
modal: true,
buttons:[{
text:'登录',
handler:function(){
$('#ff').form('submit', {
url:"login",
onSubmit: function(){
if($("#name").val()=="") {
$.messager.alert('提示','用户名不能为空');
return false;
}
if($("#pass").val()=="") {
$.messager.alert('提示','用户密码不能为空');
return false;
}
},
success:function(data){
var data=eval("("+data+")");//把后台Action传送过来的json字符串”[{"mess":"登录成功","url":"http://localhost:8080/struts2Pro/download"}]“转换成json格式数据。
if(data[0]["mess"]==="登录成功"){//登录成功则关闭登录对话框,并跳转到前一个页面
$('#ff').dialog("close");
if(data[0]["url"]!=""){
window.location.href=data[0]["url"];//跳转到原来页面
}else{
window.location.href="index.html";//跳转主页面
}
}else{
alert(data[0]["mess"]);
$("#name").focus();
}
}
});
}
},{
text:'关闭',
handler:function(){
$('#ff').dialog("close");
}
}]
});
});
</script>
</head>
<body>
<form id="ff" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" id="name" name="name" />
</tr>
<tr>
<td>密码:</td>
<td><input type="password" id="pass" name="pass" />
</tr>
</table>
</form>
</body>
</html>
运行结果如下图所示。
第二步:创建接收登录表单的参数Action,LoginAction.java代码如下。
package action;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ModelDriven;
import bussiness.Blogin;
import entity.LoginEntity;
public class LoginAction implements ModelDriven {
private HttpServletResponse response;// 用于获取servlet中的请求对象。便于向客户反馈信息
private HttpServletRequest request;// 用于获取servlet中的请求对象。便于获取表单传送过来的各种数据,如删除或更新时传送过来的关键字id的值
private HttpSession session;//声明用户的会话,它用于记录用户的状态
private LoginEntity loginEntity=new LoginEntity();//在这里必须进行实例化
public LoginEntity getLoginEntity() {
return loginEntity;
}
public void setLoginEntity(LoginEntity loginEntity) {
this.loginEntity = loginEntity;
}
@Override
public Object getModel() {
// TODO Auto-generated method stub
return loginEntity;
}
public LoginAction(){
response=ServletActionContext.getResponse();//获取Response对象
request=ServletActionContext.getRequest();//获取Request对象
session=request.getSession();//创建用户会话,该对象是用于记录用户的状态
try {
request.setCharacterEncoding("utf-8");//设置接数据的编码为utf-8
response.setContentType("text/html;charset=utf-8");//设置输出编码为utf-8,以防出现乱码
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String execute() throws IOException{
//检测登录用户和密码是否是合法的用户,若是则把用户的信息保存起来
if(Blogin.checkUser(loginEntity.getName(), loginEntity.getPass())){
session.setAttribute("user", loginEntity);//把用户的信息保存起来
if(session.getAttribute("redirect")!=null){//判断是否是从其它页面跳转过来,若是则登录成功后返回原来的页面
response.getWriter().println("[{\"mess\":\"登录成功\",\"url\":\""+session.getAttribute("redirect")+"\"}]");
}else{
//登录成功但不是从其它的页面跳转过来的
response.getWriter().println("[{\"mess\":\"登录成功\",\"url\":\"\"}]");
}
}else{
//登录失败
response.getWriter().println("[{\"mess\":\"登录失败\",\"url\":\"\"}]");
}
return null;
}
}
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>
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="action.LoginAction">
</action>
</package>
</struts>
第三步:创建一个下载的页面(详细创建过程请看4.7节),download.html代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="download?fileName=aa.jpg">下载一张图片</a><br>
</body>
</html>
第四步:创建处理请求下载文件的Action(详细创建过程请看4.7节),DownloadAction.java代码如下:
package action;
import java.io.*;
import javax.servlet.http.*;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownloadAction extends ActionSupport {
private String fileName;//获取客户请求下载的fileName要一样,且对它进行封装
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
@Override
public String execute() throws Exception {
return "success";
}
public String input() throws Exception{
return INPUT;
}
public InputStream getInputStream() throws IOException {
//获取request对象,以便进行接收用户的请求参数,即请下载的文件
HttpServletRequest request = ServletActionContext.getRequest();
//获取下载图片的真实物理路径
String path = request.getRealPath("/download");
//创建输入流用于读到要下载的文件。
InputStream is = new FileInputStream(new File(path, fileName));
return is;
}
}
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>
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="action.LoginAction">
</action>
<action name="download" class="action.DownloadAction">
<!-- <result name="input">/login.html</result> -->
<result type="stream">
<!-- inputName默认就是InputStream,可以省略,也可以自己修改,如改成aaa, 则Action里的方法也要改成public
InputStream getAaa() -->
<param name="inputName">InputStream</param>
<param name="contentDisposition">attachment;fileName=${fileName}</param>
</result>
</action>
</package>
</struts>
第五步:在Java Resource/src目录下创建一个数据包,包名为interceptor
第六步:右击”interceptor“数据包,弹出的快捷菜单。
第七步:选择”new->class“创建一个拦截器,拦截器的名称为LoginInterceptor,并实现Interceptor接口 。
第八步:单击”Finish“,完成拦截器的创建。
为了拦截没有登录的用户进行系统,所以下面我们对它进行修改,完整代码如下。
package interceptor;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.Interceptor;
import action.LoginAction;
import bussiness.Blogin;
import entity.LoginEntity;
public class LoginInterceptor implements Interceptor {
private String INPUT;
@Override
public void destroy() {
System.out.println("拦截器销毁");
}
@Override
public void init() {
System.out.println("拦截器加载");
}
@Override
public String intercept(ActionInvocation arg0) throws Exception {
//获取内容对象,即会话对象session
HttpSession session=ServletActionContext.getRequest().getSession();
System.out.println("进入拦截器");
//如果是登录Action则不进行拦截
if(arg0.getAction() instanceof LoginAction){
return arg0.invoke();
}
//通过session获取登录用户的信息
LoginEntity loginEntity=(LoginEntity) session.getAttribute("user");
//若用户信息为null,说明用户没有登录,则返回到登录的页面,若存在则要检测用户是否是合法用户若是则允许进行下面内容,否则拦截不能进行下一面内容
if(loginEntity != null){
if(Blogin.checkUser(loginEntity.getName(), loginEntity.getPass())){
//如果用户已经登录,则把保存跳转页面的的会话属性设置为空
session.setAttribute("redirect",null);
return arg0.invoke();//允许进入下面的内容
}else{
//获取action
ActionSupport action = (ActionSupport) arg0.getAction();
//把请求Action的页面地址保存到属性名为redirect中
session.setAttribute("redirect",ServletActionContext.getRequest().getHeader("referer"));
return action.LOGIN;//设置Action返回值。即返回到login.html页面。
}
}else{
//获取action
ActionSupport action = (ActionSupport) arg0.getAction();
//把请求Action的页面地址保存到属性名为redirect中
session.setAttribute("redirect",ServletActionContext.getRequest().getHeader("referer"));
return action.LOGIN;//设置Action返回值。
}
}
}
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>
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<!-- 定义自己的拦截器 -->
<interceptor name="auth" class="interceptor.LoginInterceptor" />
<!--拦截器栈 -->
<interceptor-stack name="securityStack">
<!-- 系统默认拦截器栈 若没有在我们栏截器栈中指定默认栏截器它将不会被执行-->
<interceptor-ref name="defaultStack" />
<interceptor-ref name="auth" />
</interceptor-stack>
</interceptors>
<!-- 定义一个全局的返回类型 -->
<global-results>
<result name="login">/login.html</result
</global-results>
<action name="login" class="action.LoginAction">
</action>
<action name="download" class="action.DownloadAction">
<!-- <result name="input">/login.html</result> -->
<result type="stream">
<!-- inputName默认就是InputStream,可以省略,也可以自己修改,如改成aaa, 则Action里的方法也要改成public
InputStream getAaa() -->
<param name="inputName">InputStream</param>
<param name="contentDisposition">attachment;fileName=${fileName}</param>
</result>
<!-- 在此Action中使用拦截器 -->
<interceptor-ref name="securityStack" />
</action>
</package>
</struts>