SpringBoot前后端交互、全局异常处理:后端异常信息抛到前端显示弹窗

我恨我痴心Jack 2024-09-05 12:03:01 阅读 97

前提是前端必须有接收后端信息的载体:比如:ajax的异步接收等等。

后端:

编写后端的统一返回信息类:

<code>

/**

* 后端统一返回结果

* @param <T>

*/

@Data

public class Result<T> implements Serializable {

private Integer code;//1成功,0和其他数字为失败。

private String msg;//错误信息

private T data;//数据

public static <T> Result<T> success(){

Result<T> result = new Result<T>();

result.code=1;

return result;

}

public static <T> Result<T> success(T object){

Result<T> result = new Result<T>();

result.data=object;

result.code=1;

return result;

}

public static <T> Result<T> error(String msg){

Result<T> result = new Result<T>();

result.code=0;

result.msg=msg;

return result;

}

}

异常基础类:

/**

* 业务异常

*/

public class BaseException extends RuntimeException{

public BaseException(String message) {

super(message);

}

public BaseException() {

}

}

账号不存在异常:

/**

* 账号不存在异常

*/

public class AccountNotFoundException extends BaseException {

public AccountNotFoundException() {

}

public AccountNotFoundException(String msg) {

super(msg);

}

}

账号密码为空异常:

/**

* 账号密码为空

*/

public class InputAccountAndPassword extends BaseException{

public InputAccountAndPassword(String message) {

super(message);

}

}

 登录失败异常:

/**

* 登录失败

*/

public class LoginFailedException extends BaseException{

public LoginFailedException(String msg){

super(msg);

}

}

 密码错误:

/**

* 密码错误异常

*/

public class PasswordErrorException extends BaseException {

public PasswordErrorException() {

}

public PasswordErrorException(String msg) {

super(msg);

}

}

全局异常类:

/**

* 全局异常处理

*/

//@ControllerAdvice(annotations = {RestController.class,Controller.class})

//@ResponseBody

@Slf4j

@RestControllerAdvice

public class GlobalExceptionHandler {

/**

* 业务异常

* @param ex 异常信息

* @return 封装、抛出给前端

*/

@ExceptionHandler

public Result<String> exceptionHandler(BaseException ex){

log.error(ex.getMessage());

return Result.error(ex.getMessage());

}

@ExceptionHandler

public Result<String> exceptionHandler(ExpiredJwtException ex){

String message=ex.getMessage();

if (message.contains("expired")){

return Result.error("登录过期!");

}

return null;

}

}

举例:

登录的服务

@Service

@Slf4j

public class LoginServiceImpl implements LoginService {

@Autowired(required = false)

private LoginMapper loginMapper;

/**

* 用户登录

* @param user 用户

*/

public void userLogin(User user) {

String email = user.getEmail();

String password = user.getPassword();

if (email.isEmpty() || password.isEmpty()) {

//账号密码为空

throw new InputAccountAndPassword(MessageConstant.ACCOUNT_PASSWORD_EMPTY);

}

//账号密码不为空

else {

//验证账号

int i = loginMapper.userExist(email);

//账号存在

if (i > 0) {

//验证密码

int p = loginMapper.loginCheck(email, password);

//密码正确

if (p == 1) {

//准许登录 state==1

loginMapper.login(email);

}

else {

//密码错误

throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);

}

}

//账号不存在

else {

throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);

}

}

}

}

异常提示常量类MessageConstant:

/**

* 信息提示常量类

*/

public class MessageConstant {

public static final String PASSWORD_ERROR = "密码错误";

public static final String ACCOUNT_NOT_FOUND = "账号不存在";

public static final String LOGIN_FAILED = "登录失败";

public static final String ACCOUNT_PASSWORD_EMPTY="请输入账号和密码";code>

}

控制端:

@RestController

@RequestMapping("/login")

@Slf4j

public class LoginController {

@Autowired(required = false)

private LoginService loginService;

@Autowired

private JwtProperties jwtProperties;

@PostMapping("/userlogin")

public Result login(@RequestBody User user){

log.info("开始登录:email:{},password:{}",user.getEmail(),user.getPassword());

log.info("{}",user);

loginService.userLogin(user);

//登录成功后,生成jwt令牌

Map<String, Object>claims=new HashMap<>();

claims.put("userId",1L);

claims.put("email",user.getEmail());

String token= JwtUtil.createJWT(

jwtProperties.getUserSecretKey(),

jwtProperties.getUserTtl(),

claims);

UserDTO userDTO = new UserDTO();

userDTO.setToken(token);

log.info("生成的token是:{}",token);

return Result.success(userDTO);

}

}

前端登录页面以及ajax的测试用例:

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">code>

<head>

<meta charset="UTF-8">code>

<title>欢迎登录公司员工考勤管理平台</title>

<link rel="shortcut icon" th:href="@{/images/icon.svg}">code>

<link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}">code>

<script th:src="@{/js/jquery-3.2.1.js}"></script>code>

<script th:src="@{/js/token.js}"></script>code>

<script type="text/javascript">code>

$(function () {

let token=null;

//登录按钮

$("#login").click(function () {

let email=$('#email').val();

let password=$('#password').val();

$.ajax({

type:"post",

url:"/login/userlogin",

contentType:"application/json",

data:JSON.stringify({"email":email,"password":password}),

success:function (result) {

if (result.code===1){

token=result.data.token;

alert("登录成功");

// 收到Token,开始存储token

localStorage.setItem('token',token);

alert("token值为:"+token+"!");

//返回Token给后端

//返回后端

location.href="/main";//也会经过拦截器code>

}else {

alert(result.msg);

}

}

});

});

$("#registry").click(function () {

location.href="/registry"code>

})

})

</script>

</head>

<body style="position: absolute;

top: 20%;

left: 38%;

transform: translate(40%,40%);

margin: 0;padding: 0">code>

<div>

<h2>登录页面</h2>

</div>

<div>

<label for="email"></label><input type="text" id="email" name="email" placeholder="E-mail address">code>

</div>

<div>

<label for="password"></label><input type="password" id="password" name="password" placeholder="Password"/>code>

</div>

<button id="login">登录</button>code>

<button id="registry">注册</button>code>

</body>

</html>

测试:

账号密码不为空:

后台:

账号不存在:

后台:

密码错误:

后台:

还有很多其他的情况......

Tips:其实有些情况可以直接在前端判断,没有必要全部都给到后台判断,这样会造成后台压力比较大;比如密码账号不为空,账号格式等等。

本期内容到这,如果帮到你了,或者你学到了新知识点,可以点赞收藏关注走一波,支持作者!作者后续会更新发布更多更加高质量的文章!谢谢!



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。