java - 如何将 Spring 配置错误处理重定向到我的自定义错误处理?
问题描述
我想知道是否有一种巧妙的方法可以通过配置在 Spring 中处理异常。我可以直接从扩展 WebSecurityConfigurerAdapter 接口的类中抛出异常,但在我看来,如果我使用 exceptionHandling 方法,我无法使用它发送消息。但是,如果我删除了 conf,我就无法进行全局自定义异常配置。我想知道 Spring 是否可以将异常处理重定向到 @ControllerAdvice?
现在我的代码看起来像这样(我从代码中删除了无用的部分)
配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@FieldDefaults(level = PRIVATE, makeFinal = true)
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthFailureHandler authFailureHandler;
private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
new AntPathRequestMatcher("**", "OPTIONS"), // allow prefligh for now in debug
new AntPathRequestMatcher("/public/**")
);
private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);
TokenAuthenticationProvider provider;
SecurityConfig(AuthFailureHandler authFailureHandler, final TokenAuthenticationProvider provider) {
super();
this.authFailureHandler = authFailureHandler;
this.provider = requireNonNull(provider);
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) {
auth.authenticationProvider(provider);
}
@Override
public void configure(final WebSecurity web) {
web.ignoring().requestMatchers(PUBLIC_URLS);
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(STATELESS)
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
.and()
.authenticationProvider(provider)
.authorizeRequests()
.requestMatchers(PROTECTED_URLS)
.authenticated()
}
这里处理异常的代码是
.exceptionHandling()
.defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
.and()
.authenticationProvider(provider)
.authorizeRequests()
.requestMatchers(PROTECTED_URLS)
.authenticated()
问题是如果我引发异常,它会由默认的 ExceptionHandling 处理,我无法设置自定义错误消息或 http 错误代码,从而导致默认错误处理。如果我删除它,我必须在任何地方引发异常!
控制器 中的一个,但是像这样你有一个样本
@RestController
@RequestMapping("/public/users")
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@CrossOrigin
public class UserPublic {
@NonNull UserAuthenticationService authenticationService;
@PostMapping(value = "/login",
consumes="application/json",
produces="application/json")
UserDTO login(@RequestBody shortDTO dto) throws UserNotFoundException {
UserDTO userDTO = authenticationService.login(dto.email, dto.password);
if (userDTO == null) throw new UserNotFoundException("no User found with this email / password combination");
return userDTO;
}
例外
public class UserNotFoundException extends Exception {
public UserNotFoundException(String no_user_found) {
super(no_user_found);
}
}
异常处理程序
@ControllerAdvice
public class ServiceExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = {UserNotFoundException.class })
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ApiErrorResponse unknownException(Exception ex, WebRequest req) {
System.out.println("damn here we go again");
ex.printStackTrace();
return new ApiErrorResponse(ex.getMessage());
}
}
启用或禁用 conf 的 StackTrace 是
com.application.controller.user.UserNotFoundException: no User found with this email / password combination
....
但是使用 conf 我收到 403 错误而不是 500 (将更改但需要不同的错误代码)并且正文是空的。我怎样才能将两者结合起来?对于受保护的路由,我也有同样的问题,如果用户已登录并让 Spring 为我做这件事,我不想在每个控制器的每个函数中处理异常,只需将其重定向到我的自定义异常服务。提前致谢
解决方案
在您的 ExceptionHandler 建议中,您需要将 ApiErrorResponse 包装到 ResponseEntity 中并返回 new ResponseEntity<>(new ApiErrorResponse(ex.getMessage()), HttpStatus.BAD_REQUEST);
推荐阅读
- java - 开始会话时,Google Cast 发件人应用返回超时
- python - 如何在导入 win32api 时修复“ImportError: DLL load failed”
- android - 奥利奥及以上设备后台服务中的剪贴板监听器
- typescript - 使用 TypeScript 显式键入对象
- oauth-2.0 - 从 Keycloak 令牌端点获取授权码
- mongodb - MongoDB - 如何更新数组中的对象?
- actions-on-google - 无法点击 console.actions.google 上的任何地方进行测试
- java - 如何在java 8 Stream中定义自定义排序比较器以比较键和值
- python - 具有动态设置索引、值和dense_shape 的TensorFlow SparseTensor
- java - 使用批处理数据设计独立于数据源的应用程序