struts2拦截器过滤放行后ajax请求后参数丢了

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了struts2拦截器过滤放行后ajax请求后参数丢了相关的知识,希望对你有一定的参考价值。

放行后回到action 相关的后台控制里,数据都没了。在拦截器里可以获取到AJAX的JSON参数,请问下怎么巴参数转发给放行的action中

在Session过期时,执行页面的ajax请求时,无法正常跳转到session过期提示页面,系统直接hold在那里不动,只有点击左侧菜单时,系统才能跳转到session过期提示页面。
经过调研,发现是拦截器的处理问题,拦截器只拦截了Http请求,而没有拦截Ajax请求,才导致出现上述Bug。
下面是解决办法:
首先,优化拦截器:
[java]
/**
* 拦截器
* @author lyh
* @version 2013-11-1
* @see LoginFilter
* @since
*/
public class LoginFilter implements Interceptor


/**
* 序列号
*/
private static final long serialVersionUID = -4979037503367919375L;

/**
* 日志
*/
private static final Logger LOG = Logger.getLogger(LoginFilter.class);

/**
* ajax session超时返回值
*/
private static String AJAX_TIME_OUT = null;

/**
* ajax 请求无权限返回值
*/
private static String AJAX_NO_LIMIT = null;

/**
* ajax 请求异常返回值 (在每个ajax请求中处理)
*/
//private static String AJAX_EXCEPTION = null;

/**
* 放行url
*/
private static List<String> awayUrls = null;

static

AJAX_TIME_OUT = "ajaxSessionTimeOut";
AJAX_NO_LIMIT = "ajaxNoLimit";
//AJAX_EXCEPTION = "ajaxException";

awayUrls = new LinkedList<String>();
//awayUrls.add("/login!userLogin.action");
//awayUrls.add("/custom!toLogin.action");
awayUrls.add("/equipment!upLoad.action");


@Override
public String intercept(ActionInvocation invocation)
throws Exception

//获取request域中信息
HttpServletRequest req = ServletActionContext.getRequest();

//获得当前请求url
String url = req.getServletPath();

//获得请求类型
String type = req.getHeader("X-Requested-With");

//Object object = (Object)invocation.getAction();

//如果当前url在放行url集合内 则直接放行
if (!awayUrls.contains(url))

UserInfoBean userinfo = (UserInfoBean)req.getSession().getAttribute(
CommonConstant.AUTH_SESSION_USER_KEY);

if (userinfo == null)

LOG.debug("用户登录会话已过期!");

//ajax请求 session过期时 返回字符串
if ("XMLHttpRequest".equalsIgnoreCase(type))

PrintWriter printWriter = ServletActionContext.getResponse().getWriter();
printWriter.print(AJAX_TIME_OUT);
printWriter.flush();
printWriter.close();

return null;

//普通http请求 直接返回页面
else

return "sessionTimeOut";


else

//鉴权结果
boolean authFlag = false;
try

//执行鉴权
authFlag = userManager_Service.isUrlInUserLimit(userinfo.getU_phone_num(),
url);

catch (Exception e)

LOG.error(" 鉴权出现异常!异常信息:" + e.toString() + ":" + e.getMessage());

//鉴权通过则放行 否则拦截
if (authFlag)

return invocation.invoke();

//鉴权不通过
else

//ajax请求 session过期时 返回字符串
if ("XMLHttpRequest".equalsIgnoreCase(type))

PrintWriter printWriter = ServletActionContext.getResponse().getWriter();
printWriter.print(AJAX_NO_LIMIT);
printWriter.flush();
printWriter.close();

return null;

//其他Http请求 直接返回页面
else

return "noLimit";




else

return invocation.invoke();



@Override
public void destroy()

//do yourself


@Override
public void init()

//do yourself




上述拦截器考虑了Ajax和Http两种情况,Http请求被拦截时,直接跳转到指定的全局页面,而Ajax请求被拦截时则采用Js方式提示用户。
[html]
<package name="self-default" extends="json-default">

<interceptors>
<interceptor name="loginFilter" class="xx.xx.LoginFilter" />

<interceptor-stack name="mydefault">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="tokenSession">
<param name="includeMethods">add*,update*,modify*,upload*</param>
</interceptor-ref>
<interceptor-ref name="loginFilter" />
</interceptor-stack>
</interceptors>

<!-- 拦截器应用到全部action -->
<default-interceptor-ref name="mydefault"/>

<global-results>
<!-- 普通http请求时 系统出现异常返回到错误页 -->
<result name="exception">/file/smartmanager/public/globalException.jsp</result>

<!-- 普通http请求时 无操作权限 -->
<result name="noLimit">/file/smartmanager/public/noLimit.jsp</result>

<!-- 普通http请求时 session过期 -->
<result name="sessionTimeOut">/file/smartmanager/public/sessionTimeOut.jsp</result>
</global-results>

<global-exception-mappings>
<!-- 全局异常返回exception字符串 -->
<exception-mapping exception="java.lang.Exception" result="exception" />
</global-exception-mappings>

</package>
下面是一个简单的Action例子:
[java]
public class MyAction


/**
* Http请求
* @return
* @throws Exception
* @see
*/
public String httpReqMethod()
throws Exception

try

//do yourself

catch(Exception e)

//捕获异常时抛出 触发global-results中的exception 然后跳转到提示页面
throw e;


return "httpReqMethod";


/**
* Ajax请求
* @return
* @throws Exception
* @see
*/
public String ajaxReqMethod()

try

//do yourself

catch(Exception e)

//no throw
//此处在捕获异常时 添加提示信息至json 方便在页面展示
//ajaxMap.put("success", false);
//ajaxMap.put("opMsg", ResultMsg.CHANGE_PWD_ERROR);


return "ajaxReqMethod";



配置此Action的xml(此Action需要被拦截 故extends定义的拦截器self-default):
[html]
<package name="willPackage" extends="self-default" namespace="/">
<action name="my_*" class="xx.xx.MyAction" method="1">
<result name="httpReqMethod">/file/smartmanager/main/httpReqMethod.jsp</result>
<result name="ajaxReqMethod" type="json">
<param name="root">ajaxMap</param>
</result>
</action>
</package>
全局提示页面,globalException.jsp:
[html]
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>xxx管理系统</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="icon" href="file/img/rhy.ico" type="image/x-icon" />
<link rel="shortcut icon" href="file/img/rhy.ico" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="$pageContext.request.contextPath/file/css/easyui.css" ></link>
<link rel="stylesheet" type="text/css" href="$pageContext.request.contextPath/file/css/icon.css" ></link>
<script type="text/javascript" src="$pageContext.request.contextPath/file/scripts/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="$pageContext.request.contextPath/file/scripts/jquery.easyui.min.js"></script>
<script type="text/javascript" src="$pageContext.request.contextPath/file/scripts/easyui-lang-zh_CN.js"></script>

<body>
<script type="text/javascript">
$(function()
$.messager.alert('操作提示','系统内部异常!请联系系统管理员!','warning');
);
</script>
</body>

全局ajax配置publicSetup.js:
[javascript]
//全局ajax控制,用于session超时 无权限时 提示
$.ajaxSetup(
cache: false, //close AJAX cache
contentType:"application/x-www-form-urlencoded;charset=utf-8",
complete:function(XHR,textStatus)
var resText = XHR.responseText;
if(resText=='ajaxSessionTimeOut')
sessionTimeOut();

else if(resText=='ajaxNoLimit')
noLimit();


);
参考技术A 你是用ajax调用add方法的,而你的add方法的返回是个redirect类型,这可能会发生意外结果。 一般ajax请求都通过json类型返回,否则在struts2里可能会得到不正常结果 你可以在jquery接收到json返回值以后,再在请求成功的函数里通过window.location来执行list访问请求,达到重定向效果 让action继承json-default包,或者自己加上json过滤器,返回类型是type="json"本回答被提问者和网友采纳

过滤器与拦截器的区别

过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(但要放行login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符

拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

 

拦截器与过滤器的区别 :

  1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。

 

 面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。
      但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
    也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。 
      一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。
这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。

以上是关于struts2拦截器过滤放行后ajax请求后参数丢了的主要内容,如果未能解决你的问题,请参考以下文章

struts2入门之拦截器

一些理解-过滤器,拦截器,ajax提交后不跳转,document.location.href无效,回调函数。

JavaWeb学习笔记-13过滤器

springboot 拦截器取不到 ajax跨域请求的header参数

过滤器和文件上传

Struts2