springboot前后端交互、全局异常处理:后端异常信息抛到前端显示弹窗_springboot抛出异常给前端-爱代码爱编程
前提是前端必须有接收后端信息的载体:比如:ajax的异步接收等等。
后端:
编写后端的统一返回信息类:
/**
* 后端统一返回结果
* @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="请输入账号和密码";
}
控制端:
@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">
<head>
<meta charset="UTF-8">
<title>欢迎登录公司员工考勤管理平台</title>
<link rel="shortcut icon" th:href="@{/images/icon.svg}">
<link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}">
<script th:src="@{/js/jquery-3.2.1.js}"></script>
<script th:src="@{/js/token.js}"></script>
<script type="text/javascript">
$(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";//也会经过拦截器
}else {
alert(result.msg);
}
}
});
});
$("#registry").click(function () {
location.href="/registry"
})
})
</script>
</head>
<body style="position: absolute;
top: 20%;
left: 38%;
transform: translate(40%,40%);
margin: 0;padding: 0">
<div>
<h2>登录页面</h2>
</div>
<div>
<label for="email"></label><input type="text" id="email" name="email" placeholder="E-mail address">
</div>
<div>
<label for="password"></label><input type="password" id="password" name="password" placeholder="Password"/>
</div>
<button id="login">登录</button>
<button id="registry">注册</button>
</body>
</html>
测试:
账号密码不为空:
后台:
账号不存在:
后台:
密码错误:
后台:
还有很多其他的情况......
Tips:其实有些情况可以直接在前端判断,没有必要全部都给到后台判断,这样会造成后台压力比较大;比如密码账号不为空,账号格式等等。
本期内容到这,如果帮到你了,或者你学到了新知识点,可以点赞收藏关注走一波,支持作者!作者后续会更新发布更多更加高质量的文章!谢谢!