提交 bb816c12 编写于 作者: R Rossen Stoyanchev

Use MessageSource in HandlerMethod for error reason

Closes gh-27156
上级 33f3aa9b
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -29,6 +29,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
......@@ -70,6 +72,9 @@ public class HandlerMethod {
@Nullable
private final BeanFactory beanFactory;
@Nullable
private final MessageSource messageSource;
private final Class<?> beanType;
private final Method method;
......@@ -101,6 +106,7 @@ public class HandlerMethod {
Assert.notNull(method, "Method is required");
this.bean = bean;
this.beanFactory = null;
this.messageSource = null;
this.beanType = ClassUtils.getUserClass(bean);
this.method = method;
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
......@@ -118,6 +124,7 @@ public class HandlerMethod {
Assert.notNull(methodName, "Method name is required");
this.bean = bean;
this.beanFactory = null;
this.messageSource = null;
this.beanType = ClassUtils.getUserClass(bean);
this.method = bean.getClass().getMethod(methodName, parameterTypes);
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method);
......@@ -132,11 +139,23 @@ public class HandlerMethod {
* re-create the {@code HandlerMethod} with an initialized bean.
*/
public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
this(beanName, beanFactory, null, method);
}
/**
* Variant of {@link #HandlerMethod(String, BeanFactory, Method)} that
* also accepts a {@link MessageSource}.
*/
public HandlerMethod(
String beanName, BeanFactory beanFactory,
@Nullable MessageSource messageSource, Method method) {
Assert.hasText(beanName, "Bean name is required");
Assert.notNull(beanFactory, "BeanFactory is required");
Assert.notNull(method, "Method is required");
this.bean = beanName;
this.beanFactory = beanFactory;
this.messageSource = messageSource;
Class<?> beanType = beanFactory.getType(beanName);
if (beanType == null) {
throw new IllegalStateException("Cannot resolve bean type for bean with name '" + beanName + "'");
......@@ -156,6 +175,7 @@ public class HandlerMethod {
Assert.notNull(handlerMethod, "HandlerMethod is required");
this.bean = handlerMethod.bean;
this.beanFactory = handlerMethod.beanFactory;
this.messageSource = handlerMethod.messageSource;
this.beanType = handlerMethod.beanType;
this.method = handlerMethod.method;
this.bridgedMethod = handlerMethod.bridgedMethod;
......@@ -174,6 +194,7 @@ public class HandlerMethod {
Assert.notNull(handler, "Handler object is required");
this.bean = handler;
this.beanFactory = handlerMethod.beanFactory;
this.messageSource = handlerMethod.messageSource;
this.beanType = handlerMethod.beanType;
this.method = handlerMethod.method;
this.bridgedMethod = handlerMethod.bridgedMethod;
......@@ -199,8 +220,13 @@ public class HandlerMethod {
annotation = AnnotatedElementUtils.findMergedAnnotation(getBeanType(), ResponseStatus.class);
}
if (annotation != null) {
String reason = annotation.reason();
String resolvedReason = (StringUtils.hasText(reason) && this.messageSource != null ?
this.messageSource.getMessage(reason, null, reason, LocaleContextHolder.getLocale()) :
reason);
this.responseStatus = annotation.code();
this.responseStatusReason = annotation.reason();
this.responseStatusReason = resolvedReason;
}
}
......
......@@ -258,7 +258,9 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
if (handler instanceof String) {
return new HandlerMethod((String) handler,
obtainApplicationContext().getAutowireCapableBeanFactory(), method);
obtainApplicationContext().getAutowireCapableBeanFactory(),
obtainApplicationContext(),
method);
}
return new HandlerMethod(handler, method);
}
......
......@@ -337,7 +337,9 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
if (handler instanceof String) {
return new HandlerMethod((String) handler,
obtainApplicationContext().getAutowireCapableBeanFactory(), method);
obtainApplicationContext().getAutowireCapableBeanFactory(),
obtainApplicationContext(),
method);
}
return new HandlerMethod(handler, method);
}
......
......@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletResponse;
......@@ -29,6 +30,9 @@ import javax.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AliasFor;
......@@ -47,12 +51,14 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.filter.ShallowEtagHeaderFilter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.web.testfixture.method.ResolvableMethod;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
......@@ -180,6 +186,39 @@ public class ServletInvocableHandlerMethodTests {
.as("When a status reason w/ used, the request is handled").isTrue();
}
@Test
public void invokeAndHandle_responseStatusAndReasonCode() throws Exception {
Locale locale = Locale.ENGLISH;
String beanName = "handler";
StaticApplicationContext context = new StaticApplicationContext();
context.registerBean(beanName, Handler.class);
context.addMessage("BadRequest.error", locale, "Bad request message");
context.refresh();
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
System.out.println(beanFactory.getType(beanName));
LocaleContextHolder.setLocale(locale);
try {
Method method = ResolvableMethod.on(Handler.class)
.named("responseStatusWithReasonCode")
.resolveMethod();
HandlerMethod handlerMethod = new HandlerMethod(beanName, beanFactory, context, method);
handlerMethod = handlerMethod.createWithResolvedBean();
new ServletInvocableHandlerMethod(handlerMethod)
.invokeAndHandle(this.webRequest, this.mavContainer);
}
finally {
LocaleContextHolder.resetLocaleContext();
}
assertThat(this.response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value());
assertThat(this.response.getErrorMessage()).isEqualTo("Bad request message");
}
@Test // gh-23775, gh-24635
public void invokeAndHandle_ETagFilterHasNoImpactWhenETagPresent() throws Exception {
......@@ -417,6 +456,11 @@ public class ServletInvocableHandlerMethodTests {
return "foo";
}
@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "BadRequest.error")
public String responseStatusWithReasonCode() {
return "foo";
}
@ComposedResponseStatus(responseStatus = HttpStatus.BAD_REQUEST)
public void composedResponseStatus() {
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册