Springboot拦截器拦截Ajax请求的处理方法

近期在写Springboot商城项目的时候,发现普通的URL地址请求可以被拦截,但是在用户未登录的情况下,添加收藏请求,拦截器能够成功拦截,但是无法返回结果给Ajax,从而无法进行请求拦截以后的页面跳转,报错内容:getWriter() has already been called for this response

通过查阅资料,找到解决办法,话不多说,解决过程如下:

(1)在拦截器中添加Ajax的拦截请求

这里我是在用户未登录的情况下,进行拦截特定的Ajax请求,仅针对用户未登录的情况下,且是Ajax请求才拦截。

完整的代码如下:

package com.study.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginHandlerInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(LoginHandlerInterceptor.class);

    /**
     * 拦截器
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getServletPath();
        logger.info("request请求地址path[{}] uri[{}]", request.getServletPath(),request.getRequestURI());
        Object type = request.getSession().getAttribute("type");//用户登录以后的标志。
        //如果是用户已经登录,或者请求部分功能如注册登录、首页查看等,均放行
        if (type != null || url.contains("Login") || url.contains("login") || url.contains("register")
            
        ) {
            return true;
        }
        //处理的是用户未登录的情况下,对于Ajax请求的拦截
      
            if (type == null&&request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with")
                    .equalsIgnoreCase("XMLHttpRequest")) {
                //如果是ajax请求响应头会有x-requested-with
                System.out.println("ajax请求被拦截");
                response.setHeader("Access-Control-Expose-Headers", "REDIRECT,CONTEXTPATH");
                //告诉ajax我是重定向
                response.setHeader("REDIRECT", "REDIRECT");
                //告诉ajax我重定向的路径
                response.setHeader("CONTEXTPATH", "outLogin");
                response.getWriter().write(1);
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            }
      
        //其余的一切请求均被拦截
        else{
            response.setCharacterEncoding("utf-8");
            response.getWriter().write("<script type='text/javascript'>alert('请先登录!');"
                    + "window.parent.location.href = 'outLogin'; </script>");
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {}

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {}


}

(2)在Ajax请求中添加complete方法

这里我是在ajax完成请求且接受到返回值后再做一个complete处理,对反馈的操作结果做处理,一般是success和error,error的情况下,做拦截,跳转到登录页面。

ajax部分的代码如下:


<script>
    function collect(id) {
     
                $.ajax({
                    cache: true,
                    url: "addCollect",
                    data: {"goods_id": id},
                    type: "post",
                    async: false,
                    success: function (data) {
                        if (data == 'yes') {
                            result.value && Swal.fire("收藏成功!", "操作完成", "success", ).then(function () {
                                document.location.reload()
                            })

                        } else  if (data == 'no') {
                            result.value && Swal.fire("收藏失败!", "请先登录", "error", ).then(function () {
                                document.location.reload()
                            })

                        }else  if (data == 'repeat') {
                            result.value && Swal.fire("收藏失败!", "您已收藏过了", "error", ).then(function () {
                                document.location.reload()
                            })
                        }
                    },
                    complete : function(xhr, status) {
                        if(status=='error'){
                            alert("请先登录!")
                        }
                        //拦截器实现超时跳转到登录页面
                        // 通过xhr取得响应头
                        var REDIRECT = xhr.getResponseHeader("REDIRECT");
                        //如果响应头中包含 REDIRECT 则说明是拦截器返回的需要重定向的请求
                        if (REDIRECT == "REDIRECT")
                        {
                            var win = window;
                            while (win != win.top)
                            {
                                win = win.top;
                            }
                            win.location.href = xhr.getResponseHeader("CONTEXTPATH");
                        }
                    }
                });
            }
    }

</script>

 (3)实现效果

在用户没有登录的情况下,点击收藏。

当用户点击确定时,提示登录,然后页面转发到登录页面。

猜你喜欢

转载自blog.csdn.net/qq_59059632/article/details/134678804