为了账号安全,请及时绑定邮箱和手机立即绑定

“Java+AI全栈工程师”问答01:Spring MVC登录页面错误提示

在“Java+AI全栈工程师”课程里面,有学员提到了这样一个问题:登录信息在showLoginForm验证,这不会导致第一次进登录页时就显示错误信息嘛?

这里就这位同学的问题,统一针对大家做下回复,便于其他同学参考学习。往期提问答,可以在我主页查到。

一、错题场景

1. 业务代码

登录页面 GET 请求跳转接口,用于展示登录页 + 接收登录失败后的错误提示:

@GetMapping("/login")
public String showLoginForm(Model model,
                            @RequestParam(required = false) String error,
                            @Valid @ModelAttribute("user") UserLoginDto loginDto,
                            BindingResult bindingResult) {
    model.addAttribute("user", loginDto);

    // 多种登录错误场景判断,手动绑定错误信息
    if (LoginErrorType.USERNAME_NOT_FOUND.equals(error)) {
        bindingResult.rejectValue("username", null, "该用户名未注册");
        return "login-form";
    }
    if (LoginErrorType.INCORRECT_PASSWORD.equals(error)) {
        bindingResult.rejectValue("password", null, "密码错误");
        return "login-form";
    }
    if (LoginErrorType.SESSION_INVALID.equals(error)) {
        bindingResult.rejectValue("username", null, "会话失效");
        return "login-form";
    }
    if (LoginErrorType.SESSION_EXPIRED.equals(error)) {
        bindingResult.rejectValue("username", null, "会话过期");
        return "login-form";
    }
    if (LoginErrorType.LOGOUT.equals(error)) {
        bindingResult.rejectValue("username", null, "已注销");
        return "login-form";
    }
    return "login-form";
}

2. 萌新疑问(核心误区)

登录校验逻辑写在页面展示的 GET 接口中,第一次直接访问登录页时,会不会直接触发错误提示,页面自带报错信息?

3. 错误预判(萌新默认误区)

误以为:接口带有 @Valid 校验 + 错误绑定逻辑,首次进入页面会触发校验、展示错误。

二、正确结论

首次访问登录页,完全不会显示任何错误信息,代码逻辑无问题。

三、核心原理解析(避错重点)

1. 首次访问无 error 参数,不会进入错误分支

接口中 @RequestParam\(required = false\) String error 代表该参数为非必传:

  • 首次直接访问 GET /login:无传参,error = null

  • 所有错误场景的 if 判断均不成立,不会执行 bindingResult\.rejectValue\(\)

  • 无任何错误信息绑定到视图,页面纯净无报错

只有登录失败重定向时才会触发报错:登录接口校验失败后,重定向地址会携带 error=xxx 参数(如 /login?error=USERNAME\_NOT\_FOUND),此时才会匹配错误分支,展示对应提示。

2. GET 请求下 @Valid 不会触发校验(最核心易错点)

很多萌新误以为 @Valid 只要标注就会校验,实际 SpringMVC 规则:

  • POST 表单提交:触发 @Valid 字段校验(非空、长度等注解校验)

  • GET 页面请求:仅用于数据回显,@Valid失效,不执行任何校验

因此首次访问时,空的loginDto 不会触发字段校验报错,无需手动 new 对象覆盖。

四、完整执行流程

1. 首次进入登录页(无错)

GET /login → error=null → 不执行任何错误绑定 → 直接返回登录页面 → 无错误提示

2. 登录失败回显(有错)

用户提交登录表单 → 后台校验失败 → 重定向 /login?error=对应错误码 → 匹配 if 分支 → 绑定对应错误信息 → 页面展示报错提示

五、代码存在问题与优化方案

1. 原有代码问题

多个错误判断分支代码高度重复,冗余度高,代码不优雅,维护性差。

2. 优化后精简代码

@GetMapping("/login")
public String showLoginForm(Model model,
                            @RequestParam(required = false) String error,
                            @Valid @ModelAttribute("user") UserLoginDto loginDto,
                            BindingResult bindingResult) {
    model.addAttribute("user", loginDto);

    // 枚举统一匹配错误信息,消除重复代码
    if (error != null) {
        LoginErrorType errorType = LoginErrorType.valueOf(error);
        switch (errorType) {
            case USERNAME_NOT_FOUND -> bindingResult.rejectValue("username", null, "该用户名未注册");
            case INCORRECT_PASSWORD -> bindingResult.rejectValue("password", null, "密码错误");
            case SESSION_INVALID -> bindingResult.rejectValue("username", null, "会话失效");
            case SESSION_EXPIRED -> bindingResult.rejectValue("username", null, "会话过期");
            case LOGOUT -> bindingResult.rejectValue("username", null, "已注销");
        }
    }
    return "login-form";
}

六、错题总结(必背知识点)

  1. @Valid 仅在 POST 表单提交时触发校验,GET 页面跳转不生效,不会出现首次页面报错。

  2. 非必传请求参数为空时,不会进入错误判断分支,无错误信息绑定。

  3. 登录页错误提示的核心逻辑:仅重定向携带 error 参数时,才展示报错信息

  4. 多分支相同逻辑,优先使用枚举+switch 优化,减少代码冗余。

如何系统学习Java+AI技能?

“Java+AI全栈工程师”课程24周系统化教学+12个月全程伴学,从零基础入门到高阶实战,手把手带你打通后端+前端+AI原生开发全场景,以企业级「仿某书」项目贯穿全程,完成从单体架构到分布式、前后端分离、微服务、AI融合、容器化部署的全链路实战,手敲代码锤炼真功夫,让你毕业即能独当一面,轻松拿下高薪offer!

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
全栈工程师
手记
粉丝
1.7万
获赞与收藏
2210

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消