Spring拦截器针对Ajax请求进行个性化处理

2 篇文章 0 订阅
1 篇文章 0 订阅

使用场景

在Spring中使用拦截器时,有时候会拦截ajax请求,此时我们可能会根据权限等因素对ajax数据进行个性化返回,比如跳转到其他页面或者进行alert提示等,从response对象中是无法直接进行这些操作的,需经过前端页面的配合才行。

整体思路

  1. 前端要使用了 jQuery 才行,因为要用到 jQuery 的 $.ajaxSetup 。
  2. 前端需要对ajax进行个性化返回处理的页面添加ajax的全局设置 $.ajaxSetup ,以便在ajax动作的某一阶段介入来完成一些工作。
  3. 后端需要识别本次请求是否是ajax请求,如果是ajax请求,则进行定制化返回。(通过在response的header中添加属性可实现)
  4. 前端页面发起ajax请求,后端处理并返回给前端,前端会执行 $.ajaxSetup 中配置好的行为。

我们的整体思路

  1. 在需要对ajax进行个性化返回处理的页面添加$.ajaxSetup并设定complete行为。
  2. 在$.ajaxSetup的complete行为中使用我们自定义的header属性来完成一系列工作。
  3. 在后端进行请求类型的区分判断,如果是ajax请求,那么就在response的header中添加我们自定义的header属性并返回到前端,让前端的$.ajaxSetup的complete行为来处理。

实现代码

Alert版

  1. 在需要进行ajax返回定制化的页面设置$.ajaxSetup(更推荐将此代码单提出一个js文件以便多页面共享)
$.ajaxSetup({
    contentType: "application/x-www-form-urlencoded;charset=utf-8",
    complete: function (XMLHttpRequest, textStatus) {
        //通过XMLHttpRequest取得响应头,sessionstatus,
        var sessionstatus = XMLHttpRequest.getResponseHeader("sessionStatus");
        if (sessionstatus == "AlertMessage") {
            var alertMessageInfo = decodeURI(XMLHttpRequest.getResponseHeader("alertMessageInfo"));
            window.alert(alertMessageInfo);
        }
    }
});
  • $.ajaxSetup的主要功能为给所有的ajax请求进行统一设置
  • 我们为ajax请求统一设置了一个 complete 回调函数,complete 回调函数会在ajax完成后被调用,不论是error还是ok
  • 在complete回调函数中,我们拿到后端写好的两个请求头属性sessionStatus和alertMessageInfo来进行个性化处理
  • 本例中是通过window.alert来进行弹框提示,因为提示内容是中文,所以需要用decodeURI来进行中文解码
  1. 后端拦截器识别请求是否是ajax请求
public class LimitInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
    	if(需要拦截) {
            requestNeedLimit(response, request);
        }
        return true;
    }
    
	/**
     * 请求被拦截时的友情提示
     *
     * @param response
     * @param request
     * @throws IOException
     */
    private void requestNeedLimit(HttpServletResponse response, HttpServletRequest request) throws IOException {
        // 是ajax请求
        if (StringUtils.equals("XMLHttpRequest", request.getHeader("X-Requested-With"))) {
            // ajax请求
            response.setContentType("text/html");
            response.setHeader("sessionStatus", "AlertMessage");
            response.setHeader("alertMessageInfo", URLEncoder.encode("您的访问过于频繁,已被锁定,请等待解锁!", "UTF-8"));
        } else {
            // 不是ajax请求
            response.setContentType("text/html; charset=UTF-8");
            response.getWriter().print("<html><body><script type='text/javascript'>alert('您的访问过于频繁,已被锁定,请等待解锁!');</script></body></html>");
            response.getWriter().close();
            response.flushBuffer();
        }
    }
    
    // 其他代码
}
  • 如果是ajax请求,那么我们会为response设定两个自定的属性sessionStatus和alertMessageInfo
  • 因为alertMessageInfo是中文,所以需要URLEncoder.encode来进行中文编码
  • 如果不是ajax请求那么我们也会通过流的方式弹出alert进行提示

跳转版(可以跳转到页面或Controller)

  1. 在需要进行ajax返回定制化的页面设置$.ajaxSetup(更推荐将此代码单提出一个js文件以便多页面共享)
$.ajaxSetup( {
	//设置ajax请求结束后的执行动作
    complete :
        function(XMLHttpRequest, textStatus) {
			// 通过XMLHttpRequest取得响应头,sessionstatus
            var sessionstatus = XMLHttpRequest.getResponseHeader("sessionstatus");
            if (sessionstatus == "needRedirect") {
                var win = window;
                while (win != win.top){
                    win = win.top;
                }
                win.location.href= XMLHttpRequest.getResponseHeader("CONTEXTPATH");
            }
        }
});
  • $.ajaxSetup的主要功能为给所有的ajax请求进行统一设置
  • 我们为ajax请求统一设置了一个 complete 回调函数,complete 回调函数会在ajax完成后被调用,不论是error还是ok
  • 在complete回调函数中,我们拿到后端写好的两个请求头属性sessionStatus和CONTEXTPATH(请求跳转路径,可以是jsp也可以是Controller的mapping路径)来进行个性化处理
  • 通过win.location.href来进行页面跳转
  1. 后端拦截器识别请求是否是ajax请求
public class LimitInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
    	if(需要拦截) {
            requestNeedLimit(response, request);
        }
        return true;
    }
    
    /**
     * 请求被拦截时的友情提示
     *
     * @param response
     * @param request
     * @throws IOException
     */
    private void requestNeedLimit(HttpServletResponse response, HttpServletRequest request) throws IOException {
        // 重定向用的服务基本路径
        String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort()+ request.getContextPath() + "/";
        // 是ajax请求
        if (StringUtils.equals("XMLHttpRequest", request.getHeader("X-Requested-With"))) {
            // ajax请求
            // 设定状态为超时
            response.setHeader("sessionstatus", "needRedirect");
            // 需要跳转的页面地址(请求跳转路径,可以是jsp也可以是Controller)
            response.setHeader("CONTEXTPATH", basePath+"index.jsp");
            //403 禁止
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        } else {
            // 不是ajax请求
            response.setContentType("text/html; charset=UTF-8");
            response.getWriter().print("<html><body><script type='text/javascript'>alert('您的访问过于频繁,已被锁定,请等待解锁!');</script></body></html>");
            response.getWriter().close();
            response.flushBuffer();
        }
    }
       
    // 其他代码
}
  • 如果是ajax请求,那么我们会为response设定两个自定的属性sessionStatus和CONTEXTPATH***(请求跳转路径,可以是jsp也可以是Controller)***
  • 如果不是ajax请求那么我们也会通过流的方式弹出alert进行提示

对layui请求的特殊处理

因为layui的ajax请求使用的其实是layui自身内置的JQuery,和普通的ajax请求不能兼容处理,需要额外使用layui的JQuery再设定一次$.ajaxSetup才行,示例代码如下(更推荐将此代码单提出一个js文件以便多页面共享):

if(typeof(layui)!="undefined") {
    setAjaxSetUp(layui.jquery);
}
if(typeof(jQuery)!="undefined") {
    setAjaxSetUp(jQuery);
}
function setAjaxSetUp(jQueryObject) {
    if(typeof(jQueryObject)!="undefined") {
        jQueryObject.ajaxSetup({
            contentType: "application/x-www-form-urlencoded;charset=utf-8",
            complete: function (XMLHttpRequest, textStatus) {
                //通过XMLHttpRequest取得响应头,sessionstatus,
                var sessionstatus = XMLHttpRequest.getResponseHeader("sessionStatus");
                if (sessionstatus == "AlertMessage") {
                    var alertMessageInfo = decodeURI(XMLHttpRequest.getResponseHeader("alertMessageInfo"));
                    window.alert(alertMessageInfo);
                }
            }
        });
    }
}

后端拦截器中对于前端请求的处理,和之前一样,没有区别:

public class LimitInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
    	if(需要拦截) {
            requestNeedLimit(response, request);
        }
        return true;
    }
    
    /**
     * 请求被拦截时的友情提示
     *
     * @param response
     * @param request
     * @throws IOException
     */
    private void requestNeedLimit(HttpServletResponse response, HttpServletRequest request) throws IOException {
        // 是ajax请求
        if (StringUtils.equals("XMLHttpRequest", request.getHeader("X-Requested-With"))) {
            // ajax请求
            response.setContentType("text/html");
            response.setHeader("sessionStatus", "AlertMessage");
            response.setHeader("alertMessageInfo", URLEncoder.encode("您的访问过于频繁,已被锁定,请等待解锁!", "UTF-8"));
        } else {
            // 不是ajax请求
            response.setContentType("text/html; charset=UTF-8");
            response.getWriter().print("<html><body><script type='text/javascript'>alert('您的访问过于频繁,已被锁定,请等待解锁!');</script></body></html>");
            response.getWriter().close();
            response.flushBuffer();
        }
    }
           
    // 其他代码
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值