提交 f2be4e93 编写于 作者: Y Yanming Zhou 提交者: Rossen Stoyanchev

Use MessageSource for @ExceptionHandler methods

Follow-up for commit bb816c12

See gh-27203
上级 5b3f11c5
......@@ -102,11 +102,20 @@ public class HandlerMethod {
* Create an instance from a bean instance and a method.
*/
public HandlerMethod(Object bean, Method method) {
this(bean, method, null);
}
/**
* Variant of {@link #HandlerMethod(Object, Method)} that
* also accepts a {@link MessageSource}.
*/
public HandlerMethod(Object bean, Method method, @Nullable MessageSource messageSource) {
Assert.notNull(bean, "Bean is required");
Assert.notNull(method, "Method is required");
this.bean = bean;
this.beanFactory = null;
this.messageSource = null;
this.messageSource = messageSource;
this.beanType = ClassUtils.getUserClass(bean);
this.method = method;
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
......
......@@ -20,6 +20,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.context.MessageSource;
import org.springframework.core.CoroutinesUtils;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.KotlinDetector;
......@@ -71,6 +72,14 @@ public class InvocableHandlerMethod extends HandlerMethod {
super(bean, method);
}
/**
* Variant of {@link #InvocableHandlerMethod(Object, Method)} that
* also accepts a {@link MessageSource}.
*/
public InvocableHandlerMethod(Object bean, Method method, @Nullable MessageSource messageSource) {
super(bean, method, messageSource);
}
/**
* Construct a new handler method with the given bean instance, method name and parameters.
* @param bean the object bean
......
......@@ -483,7 +483,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
}
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method);
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method, this.applicationContext);
}
// For advice applicability check below (involving base packages, assignable types
// and annotation presence), use target class instead of interface-based proxy.
......@@ -498,7 +498,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
ExceptionHandlerMethodResolver resolver = entry.getValue();
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(advice.resolveBean(), method);
return new ServletInvocableHandlerMethod(advice.resolveBean(), method, this.applicationContext);
}
}
}
......
......@@ -25,6 +25,7 @@ import java.util.concurrent.Callable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.MessageSource;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
......@@ -68,6 +69,13 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
/**
* Variant of {@link #ServletInvocableHandlerMethod(Object, Method)} that
* also accepts a {@link MessageSource}.
*/
public ServletInvocableHandlerMethod(Object handler, Method method, @Nullable MessageSource messageSource) {
super(handler, method, messageSource);
}
/**
* Creates an instance from the given handler and method.
......
......@@ -19,7 +19,9 @@ package org.springframework.web.servlet.mvc.method.annotation;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.SocketTimeoutException;
import java.util.Collections;
import java.util.Locale;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
......@@ -30,8 +32,11 @@ import org.springframework.beans.FatalBeanException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
......@@ -42,6 +47,7 @@ import org.springframework.util.ClassUtils;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.support.WebApplicationObjectSupport;
import org.springframework.web.method.HandlerMethod;
......@@ -333,6 +339,28 @@ public class ExceptionHandlerExceptionResolverTests {
assertThat(this.response.getContentAsString()).isEqualTo(rootCause.toString());
}
@Test //gh-27156
void resolveExceptionWithReasonResovledByMessageSource() throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
StaticApplicationContext context = new StaticApplicationContext(ctx);
Locale locale = Locale.ENGLISH;
context.addMessage("gateway.timeout", locale, "Gateway Timeout");
context.refresh();
LocaleContextHolder.setLocale(locale);
this.resolver.setApplicationContext(context);
this.resolver.afterPropertiesSet();
SocketTimeoutException ex = new SocketTimeoutException();
HandlerMethod handlerMethod = new HandlerMethod(new ResponseBodyController(), "handle");
ModelAndView mav = this.resolver.resolveException(this.request, this.response, handlerMethod, ex);
assertThat(mav).as("Exception was not handled").isNotNull();
assertThat(mav.isEmpty()).isTrue();
assertThat(this.response.getStatus()).isEqualTo(HttpStatus.GATEWAY_TIMEOUT.value());
assertThat(this.response.getErrorMessage()).isEqualTo("Gateway Timeout");
assertThat(this.response.getContentAsString()).isEqualTo("");
}
@Test
void resolveExceptionControllerAdviceHandler() throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyControllerAdviceConfig.class);
......@@ -530,6 +558,16 @@ public class ExceptionHandlerExceptionResolverTests {
}
}
@RestControllerAdvice
@Order(3)
static class ResponseStatusTestExceptionResolver {
@ExceptionHandler(SocketTimeoutException.class)
@ResponseStatus(code = HttpStatus.GATEWAY_TIMEOUT, reason = "gateway.timeout")
public void handleException(SocketTimeoutException ex) {
}
}
@Configuration
static class MyConfig {
......@@ -543,6 +581,11 @@ public class ExceptionHandlerExceptionResolverTests {
public AnotherTestExceptionResolver anotherTestExceptionResolver() {
return new AnotherTestExceptionResolver();
}
@Bean
public ResponseStatusTestExceptionResolver responseStatusTestExceptionResolver() {
return new ResponseStatusTestExceptionResolver();
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册