前端的form表单提交,Ajax发送了一个post请求,后端控制器方法处理后,进行页面跳转时,发现无法进行自动跳转。
前端代码:
<form action="" method="post" id="form1">
<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() {
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{
String type = request.getHeader("X-Requested-With");
if ("XMLHttpRequest".equals(type)) {
response.setHeader("REDIRECT", "REDIRECT");
response.setHeader("CONTEXTPATH", "/account/enable");
} else {
response.sendRedirect("/account/enable");
function register() {
$.ajax({
type: "POST",
dataType: "",
url: "/account/saveUser",
data: $('#form1').serialize(),
complete: function (XMLHttpRequest) {
const REDIRECT = XMLHttpRequest.getResponseHeader("REDIRECT");
if (REDIRECT == "REDIRECT") {
window.location.href = XMLHttpRequest.getResponseHeader("CONTEXTPATH");
});
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";
@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, 表单才会提交。
阅读目录问题描述原因解析解决方法携带参数进行重定向RedirectAttributes的使用使用RedirectAttributes携带参数进行重定向例子小疑惑问题描述前端的form表单提交,Ajax发送了一个post请求,后端控制器方法处理后,进行页面跳转时,发现无法进行自动跳转。前端代码:<form action="" method="post" id="form1"><!-- 此处省略form表单中的内容--> <button id="regbtn" t