Ajax发送Post请求,后端控制器使用重定向页面没有自动跳转

本文详细解析了Ajax请求后无法自动重定向的问题,探讨了原因并提供了前后端配合的解决方案,同时介绍了RedirectAttributes在携带参数重定向中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

前端的form表单提交,Ajax发送了一个post请求,后端控制器方法处理后,进行页面跳转时,发现无法进行自动跳转。
前端代码:

<form action="" method="post" id="form1">
<!-- 此处省略form表单中的内容-->
    <button id="regbtn" type="button" name="registerSubmit" onclick="register()"
            class="btn btn-primary">注册
    </button>
</form>
function register() {
    $.ajax({
        type: "POST",
        dataType: "",
        url: "/account/saveUser",
        data: $('#form1').serialize(),
    });
}

后端代码:

@GetMapping("/account/enable")
public String enable() {
    return "login/enable";
}

@PostMapping("/account/saveUser")
public String verify() {
	//doSomething...
	return "redirect:/account/enable";
}

需要说明的是如果直接访问/account/enable,可以跳转指定的页面,但如果通过ajax发起的请求,后端代码重定向的结果,浏览器并没有自动跳转到激活页面,还是在原来的注册页面,我们通过开发者工具查看请求的情况。
在这里插入图片描述
可以看到请求方法重定向和页面跳转的请求都是成功的,但是为什么浏览器的页面没有自动跳转呢?

原因解析

Ajax实际上是通过XMLHttpRequest来向服务器发送异步请求的,从服务器获取数据,然后使用JS来更新页面,这也就是常说的局部刷新实现方式,所以Ajax请求之后,服务器返回的都是纯文本流,客户端的浏览器在获取Ajax异步结果时,不是直接显示在页面上,而是要通过JS来进行处理,JS处理完以后才能显示在页面上。此处对应的JS处理就是在Ajax回调函数中执行window.location.href=path
在这里插入图片描述
在请求头信息中有这么一条:X-Requested-With: XMLHttpRequest,这就表明这是一个AJAX请求,我们可以通过这一信息来辨别请求是来自一般的HTTP请求还是Ajax请求。

解决方法

因为Ajax本身就是局部刷新,不会重新加载页面的。所以需要前后端一起配合解决。
后端:在控制器的方法再加个Ajax请求判断,判断是否是ajax请求不是就进行重定向是就直接转发,但是要添加自定义头部信息。
前端:在Ajax回调函数中进行判断,即判断请求头中是否包含了我们设置的信息,如果是,则执行跳转。

@GetMapping("/enable")
public String enable() {
    return "login/enable";
}

@PostMapping("/saveUser")
public void verify(HttpServletRequest request, HttpServletResponse response) 
		throws IOException{
		
	//doSomething...
	
	String type = request.getHeader("X-Requested-With");
	if ("XMLHttpRequest".equals(type)) {
    	//处理AJAX请求,设置响应头信息
   		response.setHeader("REDIRECT", "REDIRECT");
    	//需要跳转页面的URL
    	response.setHeader("CONTEXTPATH", "/account/enable");
	} else {
    	//其他的http请求,直接重定向就可以了
    	response.sendRedirect("/account/enable");
	}
}
function register() {
    $.ajax({
        type: "POST",
        dataType: "",
        url: "/account/saveUser",
        data: $('#form1').serialize(),
        complete: function (XMLHttpRequest) {
            // 通过xhr取得响应头
            const REDIRECT = XMLHttpRequest.getResponseHeader("REDIRECT");
            //如果响应头中包含 REDIRECT 则说明是我们需要进行重定向的
            if (REDIRECT == "REDIRECT") {
                window.location.href = XMLHttpRequest.getResponseHeader("CONTEXTPATH");
            }
        }
    });
}

携带参数进行重定向

RedirectAttributes的使用

RedirectAttributes是Spring mvc 3.1版本之后出来的一个功能,专门用于重定向之后还能带参数跳转的。
它有两种带参的方式:
第一种
attr.addAttribute("param", value);
这种方式就相当于重定向之后,在url后面拼接参数,这样在重定向之后的页面或者控制器再去获取url后面的参数就可以了,但这个方式因为是在url后面添加参数的方式,所以暴露了参数,有风险。
例:

attr.addAttribute("name", "123"); 
attr.addAttribute("success", "success");
return "redirect:/index";

相当于:return "redirect:/index?name=123&success=success"
第二种
attr.addFlashAttribute("param", value);
这种方式也能达到重新向带参,而且能隐藏参数,其原理就是放到session中,session在跳到页面后马上移除对象。所以你刷新一下后这个值就会丢掉。

attr.addFlashAttribute("status","999");
attr.addFlashAttribute("message","登录失败");
return "redirect:/toLogin";

使用RedirectAttributes携带参数进行重定向例子

@RequestMapping("/zh")
   public String reZh(RedirectAttributes attr){
       attr.addAttribute("time","ssssss");
       attr.addFlashAttribute("hi","hello");
       return "redirect:/date?time={time}";
 }
 
 
 @GetMapping("/date")
  public String toDate(@RequestParam(value = "time",required = false)String s,HttpServletRequest request){
       Object hi = RequestContextUtils.getInputFlashMap(request).get("hi");
       System.out.println(hi);
       return s;
   }

小疑惑

在上述解决重定向页面没有自动跳转的例子中,如果还需要传递参数,因为是在Ajax回调函数中进行的重定向,那么RedirectAttributes携带的参数也就失效了,那么就只能在访问路径后面拼接参数了,但是不是很优雅也不安全。有没有在Ajax回调函数里不是拼接参数的方法进行重定向的呢?不想使用localStorage或sessionStorage(因为不优雅不安全)。

如果是上面这种form表单检查提交的话,不使用Ajax请求,会更简单些。

<form action="/account/saveUser" method="post" id="form1>
    <button id="regbtn" type="submit" onclick="return doRegister()">注册</button>
</form>

只要在doRegister()方法进行检查不合格则返回false, 则表单不会进行提交;只有返回true, 表单才会提交。

根据引用\[1\]和引用\[2\]的内容,可以通过判断请求头中的X-Request-With字段是否等于"XMLHttpRequest"来判断是否是ajax请求。后端可以使用以下代码来实现判断: ``` if ("XMLHttpRequest".equals(request.getHeader("X-Request-With"))) { // 是ajax请求 // 进行登录验证的逻辑 } else { // 不是ajax请求 // 返回错误信息或者跳转到登录页面 } ``` 在ajax请求中,可以通过设置请求头的方式来传递登录信息,后端可以根据请求头中的信息进行登录验证。具体的实现方式可以根据后端框架和需求来确定。 #### 引用[.reference_title] - *1* *2* [前端发送Ajax请求,后端转发与重定向失效的问题分析与解决方案](https://blog.youkuaiyun.com/weixin_50550864/article/details/131095686)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Ajax请求后端接口(GET、POST、轮询请求)](https://blog.youkuaiyun.com/qq_41644069/article/details/120835244)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值