spring-boot 整合 JWT+SpringSecurity 进行登录认证
spring-boot
spring-projects/spring-boot: 是一个用于简化Spring应用开发的框架。适合用于需要快速开发企业级Java应用的项目。特点是可以提供自动配置、独立运行和内置的Tomcat服务器,简化Spring应用的构建和部署。
项目地址:https://gitcode.com/gh_mirrors/sp/spring-boot
免费下载资源
·
简要
1、SpringSecurity简要
- 认证 (你是谁)
- 授权 (你能干什么)
- 攻击防护 (防止伪造身份)
其核心就是一组过滤器链,项目启动后将会自动配置。最核心的就是 Basic Authentication Filter 用来认证用户的身份,一个在spring security中一种过滤器处理一种认证方式。
2、JWT 简要
-
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
-
JSON Web Token由三部分组成,它们之间用圆点(.)连接
第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).
3、本文代码执行流程图大致如下
画图有点费时间。画的不好,见谅,主要为代码执行流程
登录
认证
4、pom.xml
加入必备依赖
<!-- spring-security 5.2.0-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--jwt-->
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
一、配置SpringSecurity
类结构
1、SecurityUser
这里继承了UserAdmin (原用户类所有属性)和 UserDetails 权限判断属性( Security框架)
package com.ws.ldy.config.springSecurity.entity;
import com.ws.ldy.admin.model.entity.UserAdmin;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
* SecurityUser 权限判断类 (用户信息子类)
*/
@Data
public class SecurityUser extends UserAdmin implements UserDetails {
private static final long serialVersionUID = 1L;
//账户是否未过期,过期无法验证,在springSecurity 验证中自动调用
boolean isAccountNonExpired;
//指定用户是否解锁,锁定的用户无法进行身份验证,在springSecurity 验证中自动调用
boolean isAccountNonLocked;
//指示是否已过期的用户的凭据(密码),过期的凭据防止认证,在springSecurity 验证中自动调用
boolean isCredentialsNonExpired;
//是否可用 ,禁用的用户不能身份验证,在springSecurity 验证中自动调用
boolean isEnabled;
//登录用户名
private String username;
//登录密码
private String password;
//权限列表
private Collection<? extends GrantedAuthority> authorities;
}
2、XiJiaUserDetailsServiceImpl
继承 UserDetailsService ,登录认证方法,由SecurityConfig 来配置指定此类来认证
package com.ws.ldy.config.springSecurity.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ws.ldy.admin.mapper.AuthorityAdminMapper;
import com.ws.ldy.admin.mapper.UserAdminMapper;
import com.ws.ldy.admin.model.entity.AuthorityAdmin;
import com.ws.ldy.admin.model.entity.UserAdmin;
import com.ws.ldy.config.springSecurity.entity.SecurityUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* TODO 登录逻辑
*/
@Component
public class XiJiaUserDetailsServiceImpl implements UserDetailsService {
// 用户表
@Autowired
private UserAdminMapper userAdminMapper;
// 权限表
@Autowired
private AuthorityAdminMapper authorityAdminMapper;
// 登录
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 账号查询( 账号必须唯一)
UserAdmin userAdmin = userAdminMapper.selectOne(new LambdaQueryWrapper<UserAdmin>().eq(UserAdmin::getUsername, username));
if (userAdmin == null) {
return null;
}
// 账号密码及禁用过期等, // 状态 false, springSecurity 将验证失败,并返回不同的异常,失败方法根据不同异常返回不同的提示信息
SecurityUser userDetail = userAdmin.convert(SecurityUser.class);
userDetail.setUsername(userAdmin.getUsername());
userDetail.setPassword(userAdmin.getPassword());
userDetail.setAccountNonExpired(true); // 是否过期
userDetail.setAccountNonLocked(true); // 是否解锁
userDetail.setCredentialsNonExpired(true); // 凭据(密码)是否过期
userDetail.setEnabled(true); // 是否禁用
// 查询权限并添加权限到userDetail
List<AuthorityAdmin> userIdRoleAuthority = authorityAdminMapper.findUserIdRoleAuthority(userAdmin.getId());
List<GrantedAuthority> authorities = new ArrayList<>();
for (AuthorityAdmin authority : userIdRoleAuthority) {
authorities.add(new SimpleGrantedAuthority(authority.getUrl()));
}
userDetail.setAuthorities(authorities);
return userDetail;
}
}
3、SecurityConfig 配置类
package com.ws.ldy.config.springSecurity.config;
import com.ws.ldy.admin.mapper.AuthorityAdminMapper;
import com.ws.ldy.admin.model.entity.AuthorityAdmin;
import com.ws.ldy.config.jwt.filter.JWTLoginFilter;
import com.ws.ldy.config.jwt.filter.JWTValidFilter;
import com.ws.ldy.config.springSecurity.service.impl.XiJiaUserDetailsServiceImpl;
import com.ws.ldy.common.utils.auth.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.HandlerExceptionResolver;
import java.util.List;
/**
* TODO TODO Security配置文件,项目启动时就加载了
*
* @date 2020/7/5 0005 20:44
* @return
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 登录-认证方法->loadUserByUsername
@Autowired
private XiJiaUserDetailsServiceImpl xiJiaUserDetailsService;
// 异常处理类,在 filter无法使用全局异常,在 .addFilter(new JWTValidFilter 中传递该对象过去,便于返回异常信息
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
// 当前系统权限表
@Autowired
private AuthorityAdminMapper authorityAdminMapper;
/**
* 认证
*
* @return
*/
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
//对默认的UserDetailsService进行覆盖
authenticationProvider.setUserDetailsService(xiJiaUserDetailsService);
authenticationProvider.setPasswordEncoder(new PasswordEncoder() {
// 对密码MD5
@Override
public String encode(CharSequence rawPassword) {
return MD5Util.encode((String) rawPassword);
}
// 判断密码是否正确, rawPassword 用户输入的密码, encodedPassword 数据库DB的密码,当 XiJiaUserDetailsServiceImpl的loadUserByUsername方法执行完后执行
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
//String rawPass = MD5Util.encode((String) rawPassword);
boolean result = rawPassword.equals(encodedPassword);
return result;
}
});
return authenticationProvider;
}
/**
* TODO 授权
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// 只拦截需要拦截的所有接口, 拦截数据库权限表中的所有接口
List<AuthorityAdmin> authoritys = authorityAdminMapper.selectList(null);
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry eiur = http.authorizeRequests();
authoritys.forEach((auth) -> {
eiur.antMatchers(auth.getUrl()).hasAnyAuthority(auth.getUrl());
});
// 配置token验证及登录认证,过滤器
eiur
// 登录接口不需要权限控制,可删除,目前该接口不在权限列表中
.antMatchers("/auth/login", "POST").permitAll()
// 设置JWT过滤器
.and()
.addFilter(new JWTValidFilter(authenticationManager(), resolver))
.addFilter(new JWTLoginFilter(authenticationManager(), resolver)).csrf().disable()
// 剔除session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 开启跨域访问
http.cors().disable();
// 开启模拟请求,比如API POST测试工具的测试,不开启时,API POST为报403错误
http.csrf().disable();
// iframe 跳转错误处理 Refused to display 'url' in a frame because it set 'X-Frame-Options' to 'deny'
http.headers().frameOptions().disable();
}
/**
* There is no PasswordEncoder mapped for the id "null"
* 原因:升级为Security5.0以上密码支持多中加密方式,恢复以前模式
*
* @return
*/
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}
二、JWT 配置
1、登录 filter
package com.ws.ldy.config.jwt.filter;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ws.ldy.config.error.ErrorException;
import com.ws.ldy.common.utils.auth.JwtUtil;
import com.ws.ldy.config.springSecurity.entity.SecurityUser;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/***
* TODO 登录 ===> POST请求( 账号:username=?, 密码:password=?)
*
* 登录会调用springSecurity的登录方法进行验证
*<p>
* ===== 登录成功
* http状态status状态返回200,并且自定义响应状态code返回200,响应头存放token,key = token,value = jwt生成的token内容
* ===== 登录失败
* http状态status状态返回401,并且自定义响应状态code返回401,并提示对应的内容
* ===== 权限不足
* http状态status状态返回403,并且自定义响应状态code返回403,并提示对应的内容
* </p>
* @author 王松
* @mail 1720696548@qq.com
* @date 2020/7/5 0005 17:29
*/
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {
/**
* 获取授权管理, 创建JWTLoginFilter时获取
*/
private AuthenticationManager authenticationManager;
/**
* 异常处理类
*/
private HandlerExceptionResolver resolver;
/**
* 创建JWTLoginFilter,构造器,定义后端登陆接口-【/auth/login】,当调用该接口直接执行 attemptAuthentication 方法
*
* @param authenticationManager
*/
public JWTLoginFilter(AuthenticationManager authenticationManager, HandlerExceptionResolver resolver) {
this.authenticationManager = authenticationManager;
this.resolver = resolver;
super.setFilterProcessesUrl("/auth/login");
}
/**
* TODO 一旦调用登录接口 /auth/login,立即执行该方法
*
* @param request
* @param response
* @return
* @throws AuthenticationException
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
SecurityUser user = null;
try {
user = new ObjectMapper().readValue(request.getInputStream(), SecurityUser.class);
} catch (IOException e) {
// e.printStackTrace();
resolver.resolveException(request, response, null, new ErrorException(401, "没有传递对应的参数"));
return null;
}
// 调用springSecurity的 XiJiaUserDetailsServiceImpl 的 loadUserByUsername 方法进行登录认证,传递账号密码
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
}
/**
* TODO 一旦调用 springSecurity认证登录成功,立即执行该方法
*
* @param request
* @param response
* @param chain
* @param authResult
* @throws IOException
* @throws ServletException
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException {
// 生成jwt 放入 Header
SecurityUser userEntity = (SecurityUser) authResult.getPrincipal();
String jwtToken = JwtUtil.generateToken(userEntity);
response.addHeader("token", jwtToken);
// 响应
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
PrintWriter out = response.getWriter();
Map<String, Object> map = new HashMap<String, Object>();
map.put("code", 200);
map.put("message", "登录成功!");
out.write(JSON.toJSONString(map));
out.flush();
out.close();
}
/**
* TODO 一旦调用 springSecurity认证失败 ,立即执行该方法
*
* @param request
* @param response
* @param ex
* @throws IOException
* @throws ServletException
*/
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException ex) {
if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) {
resolver.resolveException(request, response, null, new ErrorException(401, "用户名或密码错误"));
} else if (ex instanceof InternalAuthenticationServiceException) {
resolver.resolveException(request, response, null, new ErrorException(401, "没有账号信息"));
} else if (ex instanceof DisabledException) {
resolver.resolveException(request, response, null, new ErrorException(401, "账户被禁用"));
} else {
resolver.resolveException(request, response, null, new ErrorException(401, "登录失败!"));
}
}
}
2、认证 filter
package com.ws.ldy.config.jwt.filter;
import com.ws.ldy.config.error.ErrorException;
import com.ws.ldy.common.utils.auth.JwtUtil;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* TODO jwt --> token 信息认证
*
* @author 王松
* @mail 1720696548@qq.com
* @date 2020/7/5 0005 17:29
*/
@Slf4j
public class JWTValidFilter extends BasicAuthenticationFilter {
// 异常处理类
private HandlerExceptionResolver resolver;
/**
* SecurityConfig 配置中创建该类实例
*/
public JWTValidFilter(AuthenticationManager authenticationManager, HandlerExceptionResolver resolver) {
// 获取授权管理
super(authenticationManager);
// 获取异常处理类
this.resolver = resolver;
this.resolver = resolver;
}
/**
* 拦截请求
*
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("请求方式:{} 请求URL:{} ", request.getMethod(), request.getServletPath());
// 获取token, 没有token直接放行
String token = request.getHeader("token");
if (StringUtils.isBlank(token) || "null".equals(token)) {
super.doFilterInternal(request, response, chain);
return;
}
// 有token进行权限验证
List<SimpleGrantedAuthority> userAuthList = null;
String username = null;
try {
// 权限列表
userAuthList = JwtUtil.getUserAuth(token);
// 获取账号
username = JwtUtil.getUsername(token);
} catch (SignatureException ex) {
resolver.resolveException(request, response, null, new ErrorException(10000, "JWT签名与本地计算签名不匹配"));
return;
} catch (ExpiredJwtException ex) {
resolver.resolveException(request, response, null, new ErrorException(10000, "登录过期"));
return;
} catch (Exception e) {
resolver.resolveException(request, response, null, new ErrorException(10000, "JWT解析错误"));
return;
}
// 添加账户的权限信息,和账号是否为空,然后保存到Security的Authentication授权管理器中
if (StringUtils.isNotBlank(username) && userAuthList != null) {
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, userAuthList));
}
super.doFilterInternal(request, response, chain);
}
}
3、JWT生成工具类
package com.ws.ldy.common.utils.auth;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ws.ldy.config.springSecurity.entity.SecurityUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.Date;
import java.util.List;
/***
* TODO jwt 工具类
* @author 王松
* @mail 1720696548@qq.com
* @date 2020/7/5 0005 19:13
*/
public class JwtUtil {
// 主题
private static final String SUBJECT = "xijia";
// jwt的token有效期,
//private static final long EXPIRITION = 1000L * 60 * 60 * 24 * 7;//7天
private static final long EXPIRITION = 1000L * 60 * 30; // 半小时
// 加密key(黑客没有该值无法篡改token内容)
private static final String APPSECRET_KEY = "xijia";
// 用户url权限列表key
private static final String AUTH_CLAIMS = "auth";
/**
* TODO 生成token
*
* @param user
* @return java.lang.String
* @date 2020/7/6 0006 9:26
*/
public static String generateToken(SecurityUser user) {
String token = Jwts
.builder()
// 主题
.setSubject(SUBJECT)
// 添加jwt自定义值
.claim(AUTH_CLAIMS, user.getAuthorities())
.claim("username", user.getUsername())
.claim("userId", user.getId())
.claim("head", user.getHead())
.setIssuedAt(new Date())
// 过期时间
.setExpiration(new Date(System.currentTimeMillis() + EXPIRITION))
// 加密方式,加密key
.signWith(SignatureAlgorithm.HS256, APPSECRET_KEY).compact();
return token;
}
// public static Claims checkJWT(String token) {
// try {
// final Claims claims = Jwts.parser().setSigningKey(APPSECRET_KEY).parseClaimsJws(token).getBody();
// return claims;
// } catch (Exception e) {
// e.printStackTrace();
// return null;
// }
// }
/**
* 获取用户Id
*
* @param token
* @return
*/
public static String getUserId(String token) {
Claims claims = Jwts.parser().setSigningKey(APPSECRET_KEY).parseClaimsJws(token).getBody();
return claims.get("userId").toString();
}
/**
* 获取用户名
*
* @param token
* @return
*/
public static String getUsername(String token) {
Claims claims = Jwts.parser().setSigningKey(APPSECRET_KEY).parseClaimsJws(token).getBody();
return claims.get("username").toString();
}
/**
* 获取用户角色的权限列表, 没有返回空
*
* @param token
* @return
*/
public static List<SimpleGrantedAuthority> getUserAuth(String token) {
Claims claims = Jwts.parser().setSigningKey(APPSECRET_KEY).parseClaimsJws(token).getBody();
List auths = (List) claims.get(AUTH_CLAIMS);
String json = JSONArray.toJSONString(auths);
List<SimpleGrantedAuthority> grantedAuthorityList = JSON.parseArray(json, SimpleGrantedAuthority.class);
return grantedAuthorityList;
}
/**
* 是否过期
*
* @param token
* @return
*/
public static boolean isExpiration(String token) {
Claims claims = Jwts.parser().setSigningKey(APPSECRET_KEY).parseClaimsJws(token).getBody();
System.out.println("过期时间: " + claims.getExpiration());
return claims.getExpiration().before(new Date());
}
}
三、系统错误配置
1、WebServerAutoConfiguration (系统异常转发)
package com.ws.ldy.config.error;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
@Configuration
public class WebServerAutoConfiguration {
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400");
ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401");
ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403");
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500);
return factory;
}
}
2、ErrorController (返回前端错误信息)
我这里抛的自定义异常走全局异常类,可以自己修改一下
package com.ws.ldy.config.error;
import com.ws.ldy.base.controller.BaseController;
import com.ws.ldy.common.result.EnumUtils;
import com.ws.ldy.common.result.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* TODO WebServerAutoConfiguration 转发异常转发过来的信息,返回 json参数
*
* @author 王松
* @mail 1720696548@qq.com
* @date 2019/11/19 9:43
* 方式1、直接跳转到具体错误页面
* 方式2、返回json格式数据,由前端处理
*/
@SuppressWarnings("all")
@Controller
@Slf4j
public class ErrorController extends BaseController {
/**
* TODO 方式2:系统错误返回json
*
* @param code 对应错误码,ErrorPageConfig配置
* @return java.util.Map<java.lang.String, java.lang.Object>
* @date 2019/11/18 21:14
*/
@RequestMapping(value = "/error/{code}")
@ResponseBody
public void error(@PathVariable int code) {
// 根据状态值查询对应的枚举
ResultEnum errorConstantEnum = EnumUtils.getByCode(Integer.valueOf(code), ResultEnum.class);
// 返回对应提示
if (errorConstantEnum != null) {
throw new ErrorException(errorConstantEnum);
}
//返回500错误
throw new ErrorException(ResultEnum.SYS_ERROR_CODE_500);
}
}
本文到此结束,如果觉得有用,动动小手点赞或关注一下呗,将不定时持续更新更多的内容…,感谢大家的观看!
GitHub 加速计划 / sp / spring-boot
73.97 K
40.4 K
下载
spring-projects/spring-boot: 是一个用于简化Spring应用开发的框架。适合用于需要快速开发企业级Java应用的项目。特点是可以提供自动配置、独立运行和内置的Tomcat服务器,简化Spring应用的构建和部署。
最近提交(Master分支:1 个月前 )
fdf24c6c
Closes gh-42976
6 天前
3c42ba8c
* pr/42974:
Fix copyright year of updated file
Polish
Closes gh-42974
6 天前
更多推荐
已为社区贡献7条内容
所有评论(0)