@Nullable all the way: null-safety at field level
This commits extends nullability declarations to the field level, formalizing the interaction between methods and their underlying fields and therefore avoiding any nullability mismatch. Issue: SPR-15720
This commit is contained in:
@@ -307,30 +307,39 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
private boolean cleanupAfterInclude = true;
|
||||
|
||||
/** MultipartResolver used by this servlet */
|
||||
@Nullable
|
||||
private MultipartResolver multipartResolver;
|
||||
|
||||
/** LocaleResolver used by this servlet */
|
||||
@Nullable
|
||||
private LocaleResolver localeResolver;
|
||||
|
||||
/** ThemeResolver used by this servlet */
|
||||
@Nullable
|
||||
private ThemeResolver themeResolver;
|
||||
|
||||
/** List of HandlerMappings used by this servlet */
|
||||
@Nullable
|
||||
private List<HandlerMapping> handlerMappings;
|
||||
|
||||
/** List of HandlerAdapters used by this servlet */
|
||||
@Nullable
|
||||
private List<HandlerAdapter> handlerAdapters;
|
||||
|
||||
/** List of HandlerExceptionResolvers used by this servlet */
|
||||
@Nullable
|
||||
private List<HandlerExceptionResolver> handlerExceptionResolvers;
|
||||
|
||||
/** RequestToViewNameTranslator used by this servlet */
|
||||
@Nullable
|
||||
private RequestToViewNameTranslator viewNameTranslator;
|
||||
|
||||
/** FlashMapManager used by this servlet */
|
||||
@Nullable
|
||||
private FlashMapManager flashMapManager;
|
||||
|
||||
/** List of ViewResolvers used by this servlet */
|
||||
@Nullable
|
||||
private List<ViewResolver> viewResolvers;
|
||||
|
||||
|
||||
@@ -893,12 +902,14 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
|
||||
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
|
||||
|
||||
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
|
||||
if (inputFlashMap != null) {
|
||||
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
|
||||
if (this.flashMapManager != null) {
|
||||
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
|
||||
if (inputFlashMap != null) {
|
||||
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
|
||||
}
|
||||
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
|
||||
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
|
||||
}
|
||||
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
|
||||
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
|
||||
|
||||
try {
|
||||
doDispatch(request, response);
|
||||
@@ -941,7 +952,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
|
||||
// Determine handler for the current request.
|
||||
mappedHandler = getHandler(processedRequest);
|
||||
if (mappedHandler == null || mappedHandler.getHandler() == null) {
|
||||
if (mappedHandler == null) {
|
||||
noHandlerFound(processedRequest, response);
|
||||
return;
|
||||
}
|
||||
@@ -1076,11 +1087,12 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
*/
|
||||
@Override
|
||||
protected LocaleContext buildLocaleContext(final HttpServletRequest request) {
|
||||
if (this.localeResolver instanceof LocaleContextResolver) {
|
||||
return ((LocaleContextResolver) this.localeResolver).resolveLocaleContext(request);
|
||||
LocaleResolver lr = this.localeResolver;
|
||||
if (lr instanceof LocaleContextResolver) {
|
||||
return ((LocaleContextResolver) lr).resolveLocaleContext(request);
|
||||
}
|
||||
else {
|
||||
return () -> localeResolver.resolveLocale(request);
|
||||
return () -> (lr != null ? lr.resolveLocale(request) : request.getLocale());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1140,10 +1152,12 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
* @see MultipartResolver#cleanupMultipart
|
||||
*/
|
||||
protected void cleanupMultipart(HttpServletRequest request) {
|
||||
MultipartHttpServletRequest multipartRequest =
|
||||
WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
|
||||
if (multipartRequest != null) {
|
||||
this.multipartResolver.cleanupMultipart(multipartRequest);
|
||||
if (this.multipartResolver != null) {
|
||||
MultipartHttpServletRequest multipartRequest =
|
||||
WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
|
||||
if (multipartRequest != null) {
|
||||
this.multipartResolver.cleanupMultipart(multipartRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1155,14 +1169,16 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
*/
|
||||
@Nullable
|
||||
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
|
||||
for (HandlerMapping hm : this.handlerMappings) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(
|
||||
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
|
||||
}
|
||||
HandlerExecutionChain handler = hm.getHandler(request);
|
||||
if (handler != null) {
|
||||
return handler;
|
||||
if (this.handlerMappings != null) {
|
||||
for (HandlerMapping hm : this.handlerMappings) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(
|
||||
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
|
||||
}
|
||||
HandlerExecutionChain handler = hm.getHandler(request);
|
||||
if (handler != null) {
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1194,12 +1210,14 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
|
||||
*/
|
||||
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
|
||||
for (HandlerAdapter ha : this.handlerAdapters) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Testing handler adapter [" + ha + "]");
|
||||
}
|
||||
if (ha.supports(handler)) {
|
||||
return ha;
|
||||
if (this.handlerAdapters != null) {
|
||||
for (HandlerAdapter ha : this.handlerAdapters) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Testing handler adapter [" + ha + "]");
|
||||
}
|
||||
if (ha.supports(handler)) {
|
||||
return ha;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ServletException("No adapter for handler [" + handler +
|
||||
@@ -1222,10 +1240,12 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
|
||||
// Check registered HandlerExceptionResolvers...
|
||||
ModelAndView exMv = null;
|
||||
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
|
||||
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
|
||||
if (exMv != null) {
|
||||
break;
|
||||
if (this.handlerExceptionResolvers != null) {
|
||||
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
|
||||
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
|
||||
if (exMv != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exMv != null) {
|
||||
@@ -1261,7 +1281,8 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
*/
|
||||
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
// Determine locale for request and apply it to the response.
|
||||
Locale locale = this.localeResolver.resolveLocale(request);
|
||||
Locale locale =
|
||||
(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
|
||||
response.setLocale(locale);
|
||||
|
||||
View view;
|
||||
@@ -1310,7 +1331,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
*/
|
||||
@Nullable
|
||||
protected String getDefaultViewName(HttpServletRequest request) throws Exception {
|
||||
return this.viewNameTranslator.getViewName(request);
|
||||
return (this.viewNameTranslator != null ? this.viewNameTranslator.getViewName(request) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1331,10 +1352,12 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
|
||||
Locale locale, HttpServletRequest request) throws Exception {
|
||||
|
||||
for (ViewResolver viewResolver : this.viewResolvers) {
|
||||
View view = viewResolver.resolveViewName(viewName, locale);
|
||||
if (view != null) {
|
||||
return view;
|
||||
if (this.viewResolvers != null) {
|
||||
for (ViewResolver viewResolver : this.viewResolvers) {
|
||||
View view = viewResolver.resolveViewName(viewName, locale);
|
||||
if (view != null) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.util.StringUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public final class FlashMap extends HashMap<String, Object> implements Comparable<FlashMap> {
|
||||
|
||||
@Nullable
|
||||
private String targetRequestPath;
|
||||
|
||||
private final MultiValueMap<String, String> targetRequestParams = new LinkedMultiValueMap<>(4);
|
||||
@@ -90,8 +91,8 @@ public final class FlashMap extends HashMap<String, Object> implements Comparabl
|
||||
|
||||
/**
|
||||
* Provide a request parameter identifying the request for this FlashMap.
|
||||
* @param name the expected parameter name (skipped if empty or {@code null})
|
||||
* @param value the expected value (skipped if empty or {@code null})
|
||||
* @param name the expected parameter name (skipped if empty)
|
||||
* @param value the expected value (skipped if empty)
|
||||
*/
|
||||
public FlashMap addTargetRequestParam(String name, String value) {
|
||||
if (StringUtils.hasText(name) && StringUtils.hasText(value)) {
|
||||
|
||||
@@ -164,18 +164,22 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
|
||||
|
||||
/** ServletContext attribute to find the WebApplicationContext in */
|
||||
@Nullable
|
||||
private String contextAttribute;
|
||||
|
||||
/** WebApplicationContext implementation class to create */
|
||||
private Class<?> contextClass = DEFAULT_CONTEXT_CLASS;
|
||||
|
||||
/** WebApplicationContext id to assign */
|
||||
@Nullable
|
||||
private String contextId;
|
||||
|
||||
/** Namespace for this servlet */
|
||||
@Nullable
|
||||
private String namespace;
|
||||
|
||||
/** Explicit context config location */
|
||||
@Nullable
|
||||
private String contextConfigLocation;
|
||||
|
||||
/** Actual ApplicationContextInitializer instances to apply to the context */
|
||||
@@ -183,6 +187,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
new ArrayList<>();
|
||||
|
||||
/** Comma-delimited ApplicationContextInitializer class names set through init param */
|
||||
@Nullable
|
||||
private String contextInitializerClasses;
|
||||
|
||||
/** Should we publish the context as a ServletContext attribute? */
|
||||
@@ -201,6 +206,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
private boolean dispatchTraceRequest = false;
|
||||
|
||||
/** WebApplicationContext for this servlet */
|
||||
@Nullable
|
||||
private WebApplicationContext webApplicationContext;
|
||||
|
||||
/** If the WebApplicationContext was injected via {@link #setApplicationContext} */
|
||||
@@ -769,6 +775,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
/**
|
||||
* Return this servlet's WebApplicationContext.
|
||||
*/
|
||||
@Nullable
|
||||
public final WebApplicationContext getWebApplicationContext() {
|
||||
return this.webApplicationContext;
|
||||
}
|
||||
@@ -1065,7 +1072,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
private void publishRequestHandledEvent(HttpServletRequest request, HttpServletResponse response,
|
||||
long startTime, @Nullable Throwable failureCause) {
|
||||
|
||||
if (this.publishEvents) {
|
||||
if (this.publishEvents && this.webApplicationContext != null) {
|
||||
// Whether or not we succeeded, publish an event.
|
||||
long processingTime = System.currentTimeMillis() - startTime;
|
||||
this.webApplicationContext.publishEvent(
|
||||
|
||||
@@ -42,8 +42,10 @@ public class HandlerExecutionChain {
|
||||
|
||||
private final Object handler;
|
||||
|
||||
@Nullable
|
||||
private HandlerInterceptor[] interceptors;
|
||||
|
||||
@Nullable
|
||||
private List<HandlerInterceptor> interceptorList;
|
||||
|
||||
private int interceptorIndex = -1;
|
||||
@@ -53,7 +55,7 @@ public class HandlerExecutionChain {
|
||||
* Create a new HandlerExecutionChain.
|
||||
* @param handler the handler object to execute
|
||||
*/
|
||||
public HandlerExecutionChain(@Nullable Object handler) {
|
||||
public HandlerExecutionChain(Object handler) {
|
||||
this(handler, (HandlerInterceptor[]) null);
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ public class HandlerExecutionChain {
|
||||
* @param interceptors the array of interceptors to apply
|
||||
* (in the given order) before the handler itself executes
|
||||
*/
|
||||
public HandlerExecutionChain(@Nullable Object handler, @Nullable HandlerInterceptor... interceptors) {
|
||||
public HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors) {
|
||||
if (handler instanceof HandlerExecutionChain) {
|
||||
HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
|
||||
this.handler = originalChain.getHandler();
|
||||
@@ -80,9 +82,7 @@ public class HandlerExecutionChain {
|
||||
|
||||
/**
|
||||
* Return the handler object to execute.
|
||||
* @return the handler object (may be {@code null})
|
||||
*/
|
||||
@Nullable
|
||||
public Object getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
@@ -207,9 +207,6 @@ public class HandlerExecutionChain {
|
||||
@Override
|
||||
public String toString() {
|
||||
Object handler = getHandler();
|
||||
if (handler == null) {
|
||||
return "HandlerExecutionChain with no handler";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("HandlerExecutionChain with handler [").append(handler).append("]");
|
||||
HandlerInterceptor[] interceptors = getInterceptors();
|
||||
|
||||
@@ -84,6 +84,7 @@ public abstract class HttpServletBean extends HttpServlet implements Environment
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Nullable
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
private final Set<String> requiredProperties = new HashSet<>(4);
|
||||
|
||||
@@ -47,12 +47,15 @@ import org.springframework.util.CollectionUtils;
|
||||
public class ModelAndView {
|
||||
|
||||
/** View instance or view name String */
|
||||
@Nullable
|
||||
private Object view;
|
||||
|
||||
/** Model Map */
|
||||
@Nullable
|
||||
private ModelMap model;
|
||||
|
||||
/** Optional HTTP status for the response */
|
||||
@Nullable
|
||||
private HttpStatus status;
|
||||
|
||||
/** Indicates whether or not this instance has been cleared with a call to {@link #clear()} */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -35,7 +35,7 @@ public interface RequestToViewNameTranslator {
|
||||
* Translate the given {@link HttpServletRequest} into a view name.
|
||||
* @param request the incoming {@link HttpServletRequest} providing
|
||||
* the context from which a view name is to be resolved
|
||||
* @return the view name (or {@code null} if no default found)
|
||||
* @return the view name, or {@code null} if no default found
|
||||
* @throws Exception if view name translation fails
|
||||
*/
|
||||
@Nullable
|
||||
|
||||
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.support.ServletContextResource;
|
||||
@@ -103,14 +104,18 @@ public class ResourceServlet extends HttpServletBean {
|
||||
public static final String RESOURCE_PARAM_NAME = "resource";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String defaultUrl;
|
||||
|
||||
@Nullable
|
||||
private String allowedResources;
|
||||
|
||||
@Nullable
|
||||
private String contentType;
|
||||
|
||||
private boolean applyLastModified = false;
|
||||
|
||||
@Nullable
|
||||
private PathMatcher pathMatcher;
|
||||
|
||||
private long startupTime;
|
||||
@@ -267,9 +272,12 @@ public class ResourceServlet extends HttpServletBean {
|
||||
StringUtils.tokenizeToStringArray(resourceUrl, RESOURCE_URL_DELIMITERS);
|
||||
for (String url : resourceUrls) {
|
||||
// check whether URL matches allowed resources
|
||||
if (this.allowedResources != null && !this.pathMatcher.match(this.allowedResources, url)) {
|
||||
throw new ServletException("Resource [" + url +
|
||||
"] does not match allowed pattern [" + this.allowedResources + "]");
|
||||
if (this.allowedResources != null) {
|
||||
Assert.state(this.pathMatcher != null, "No PathMatcher available");
|
||||
if (!this.pathMatcher.match(this.allowedResources, url)) {
|
||||
throw new ServletException("Resource [" + url +
|
||||
"] does not match allowed pattern [" + this.allowedResources + "]");
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Including resource [" + url + "]");
|
||||
|
||||
@@ -96,8 +96,10 @@ public class ContentNegotiationConfigurer {
|
||||
/**
|
||||
* Class constructor with {@link javax.servlet.ServletContext}.
|
||||
*/
|
||||
public ContentNegotiationConfigurer(ServletContext servletContext) {
|
||||
this.factory.setServletContext(servletContext);
|
||||
public ContentNegotiationConfigurer(@Nullable ServletContext servletContext) {
|
||||
if (servletContext != null) {
|
||||
this.factory.setServletContext(servletContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ public class DefaultServletHandlerConfigurer {
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
@Nullable
|
||||
private DefaultServletHttpRequestHandler handler;
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -44,6 +44,7 @@ public class InterceptorRegistration {
|
||||
|
||||
private int order = 0;
|
||||
|
||||
@Nullable
|
||||
private PathMatcher pathMatcher;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.config.annotation;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.mvc.ParameterizableViewController;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
@@ -49,7 +50,6 @@ public class RedirectViewControllerRegistration {
|
||||
|
||||
/**
|
||||
* Set the specific redirect 3xx status code to use.
|
||||
*
|
||||
* <p>If not set, {@link org.springframework.web.servlet.view.RedirectView}
|
||||
* will select {@code HttpStatus.MOVED_TEMPORARILY (302)} by default.
|
||||
*/
|
||||
@@ -63,7 +63,6 @@ public class RedirectViewControllerRegistration {
|
||||
* Whether to interpret a given redirect URL that starts with a slash ("/")
|
||||
* as relative to the current ServletContext, i.e. as relative to the web
|
||||
* application root.
|
||||
*
|
||||
* <p>Default is {@code true}.
|
||||
*/
|
||||
public RedirectViewControllerRegistration setContextRelative(boolean contextRelative) {
|
||||
@@ -74,7 +73,6 @@ public class RedirectViewControllerRegistration {
|
||||
/**
|
||||
* Whether to propagate the query parameters of the current request through
|
||||
* to the target redirect URL.
|
||||
*
|
||||
* <p>Default is {@code false}.
|
||||
*/
|
||||
public RedirectViewControllerRegistration setKeepQueryParams(boolean propagate) {
|
||||
@@ -82,7 +80,7 @@ public class RedirectViewControllerRegistration {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setApplicationContext(ApplicationContext applicationContext) {
|
||||
protected void setApplicationContext(@Nullable ApplicationContext applicationContext) {
|
||||
this.controller.setApplicationContext(applicationContext);
|
||||
this.redirectView.setApplicationContext(applicationContext);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -22,8 +22,9 @@ import java.util.List;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.resource.PathResourceResolver;
|
||||
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
|
||||
|
||||
@@ -43,10 +44,13 @@ public class ResourceHandlerRegistration {
|
||||
|
||||
private final List<Resource> locations = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private Integer cachePeriod;
|
||||
|
||||
@Nullable
|
||||
private CacheControl cacheControl;
|
||||
|
||||
@Nullable
|
||||
private ResourceChainRegistration resourceChainRegistration;
|
||||
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ public class ResourceHandlerRegistry {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
@Nullable
|
||||
private final ContentNegotiationManager contentNegotiationManager;
|
||||
|
||||
private final List<ResourceHandlerRegistration> registrations = new ArrayList<>();
|
||||
@@ -142,9 +143,11 @@ public class ResourceHandlerRegistry {
|
||||
for (ResourceHandlerRegistration registration : this.registrations) {
|
||||
for (String pathPattern : registration.getPathPatterns()) {
|
||||
ResourceHttpRequestHandler handler = registration.getRequestHandler();
|
||||
if (this.contentNegotiationManager != null) {
|
||||
handler.setContentNegotiationManager(this.contentNegotiationManager);
|
||||
}
|
||||
handler.setServletContext(this.servletContext);
|
||||
handler.setApplicationContext(this.applicationContext);
|
||||
handler.setContentNegotiationManager(this.contentNegotiationManager);
|
||||
try {
|
||||
handler.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.config.annotation;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.RequestToViewNameTranslator;
|
||||
import org.springframework.web.servlet.mvc.ParameterizableViewController;
|
||||
@@ -44,7 +45,6 @@ public class ViewControllerRegistration {
|
||||
|
||||
/**
|
||||
* Set the status code to set on the response. Optional.
|
||||
*
|
||||
* <p>If not set the response status will be 200 (OK).
|
||||
*/
|
||||
public ViewControllerRegistration setStatusCode(HttpStatus statusCode) {
|
||||
@@ -54,19 +54,17 @@ public class ViewControllerRegistration {
|
||||
|
||||
/**
|
||||
* Set the view name to return. Optional.
|
||||
*
|
||||
* <p>If not specified, the view controller will return {@code null} as the
|
||||
* view name in which case the configured {@link RequestToViewNameTranslator}
|
||||
* will select the view name. The {@code DefaultRequestToViewNameTranslator}
|
||||
* for example translates "/foo/bar" to "foo/bar".
|
||||
*
|
||||
* @see org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
|
||||
*/
|
||||
public void setViewName(String viewName) {
|
||||
this.controller.setViewName(viewName);
|
||||
}
|
||||
|
||||
protected void setApplicationContext(ApplicationContext applicationContext) {
|
||||
protected void setApplicationContext(@Nullable ApplicationContext applicationContext) {
|
||||
this.controller.setApplicationContext(applicationContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,11 @@ public class ViewControllerRegistry {
|
||||
|
||||
private final List<ViewControllerRegistration> registrations = new ArrayList<>(4);
|
||||
|
||||
private final List<RedirectViewControllerRegistration> redirectRegistrations =
|
||||
new ArrayList<>(10);
|
||||
private final List<RedirectViewControllerRegistration> redirectRegistrations = new ArrayList<>(10);
|
||||
|
||||
private int order = 1;
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ public class ViewControllerRegistry {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
protected void setApplicationContext(ApplicationContext applicationContext) {
|
||||
protected void setApplicationContext(@Nullable ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
@@ -53,14 +54,18 @@ import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
|
||||
*/
|
||||
public class ViewResolverRegistry {
|
||||
|
||||
@Nullable
|
||||
private ContentNegotiatingViewResolver contentNegotiatingResolver;
|
||||
|
||||
private final List<ViewResolver> viewResolvers = new ArrayList<>(4);
|
||||
|
||||
@Nullable
|
||||
private Integer order;
|
||||
|
||||
@Nullable
|
||||
private ContentNegotiationManager contentNegotiationManager;
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
@@ -98,15 +103,14 @@ public class ViewResolverRegistry {
|
||||
* media types requested by the client (e.g. in the Accept header).
|
||||
* <p>If invoked multiple times the provided default views will be added to
|
||||
* any other default views that may have been configured already.
|
||||
*
|
||||
* @see ContentNegotiatingViewResolver#setDefaultViews
|
||||
*/
|
||||
public void enableContentNegotiation(boolean useNotAcceptableStatus, View... defaultViews) {
|
||||
initContentNegotiatingViewResolver(defaultViews);
|
||||
this.contentNegotiatingResolver.setUseNotAcceptableStatusCode(useNotAcceptableStatus);
|
||||
ContentNegotiatingViewResolver vr = initContentNegotiatingViewResolver(defaultViews);
|
||||
vr.setUseNotAcceptableStatusCode(useNotAcceptableStatus);
|
||||
}
|
||||
|
||||
private void initContentNegotiatingViewResolver(View[] defaultViews) {
|
||||
private ContentNegotiatingViewResolver initContentNegotiatingViewResolver(View[] defaultViews) {
|
||||
// ContentNegotiatingResolver in the registry: elevate its precedence!
|
||||
this.order = (this.order != null ? this.order : Ordered.HIGHEST_PRECEDENCE);
|
||||
|
||||
@@ -123,8 +127,11 @@ public class ViewResolverRegistry {
|
||||
this.contentNegotiatingResolver = new ContentNegotiatingViewResolver();
|
||||
this.contentNegotiatingResolver.setDefaultViews(Arrays.asList(defaultViews));
|
||||
this.contentNegotiatingResolver.setViewResolvers(this.viewResolvers);
|
||||
this.contentNegotiatingResolver.setContentNegotiationManager(this.contentNegotiationManager);
|
||||
if (this.contentNegotiationManager != null) {
|
||||
this.contentNegotiatingResolver.setContentNegotiationManager(this.contentNegotiationManager);
|
||||
}
|
||||
}
|
||||
return this.contentNegotiatingResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +169,7 @@ public class ViewResolverRegistry {
|
||||
* {@link org.springframework.web.servlet.view.tiles3.TilesConfigurer} bean.
|
||||
*/
|
||||
public UrlBasedViewResolverRegistration tiles() {
|
||||
if (this.applicationContext != null && !hasBeanOfType(TilesConfigurer.class)) {
|
||||
if (!checkBeanOfType(TilesConfigurer.class)) {
|
||||
throw new BeanInitializationException("In addition to a Tiles view resolver " +
|
||||
"there must also be a single TilesConfigurer bean in this web application context " +
|
||||
"(or its parent).");
|
||||
@@ -179,7 +186,7 @@ public class ViewResolverRegistry {
|
||||
* {@link org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer} bean.
|
||||
*/
|
||||
public UrlBasedViewResolverRegistration freeMarker() {
|
||||
if (this.applicationContext != null && !hasBeanOfType(FreeMarkerConfigurer.class)) {
|
||||
if (!checkBeanOfType(FreeMarkerConfigurer.class)) {
|
||||
throw new BeanInitializationException("In addition to a FreeMarker view resolver " +
|
||||
"there must also be a single FreeMarkerConfig bean in this web application context " +
|
||||
"(or its parent): FreeMarkerConfigurer is the usual implementation. " +
|
||||
@@ -195,7 +202,7 @@ public class ViewResolverRegistry {
|
||||
* prefix and a default suffix of ".tpl".
|
||||
*/
|
||||
public UrlBasedViewResolverRegistration groovy() {
|
||||
if (this.applicationContext != null && !hasBeanOfType(GroovyMarkupConfigurer.class)) {
|
||||
if (!checkBeanOfType(GroovyMarkupConfigurer.class)) {
|
||||
throw new BeanInitializationException("In addition to a Groovy markup view resolver " +
|
||||
"there must also be a single GroovyMarkupConfig bean in this web application context " +
|
||||
"(or its parent): GroovyMarkupConfigurer is the usual implementation. " +
|
||||
@@ -211,7 +218,7 @@ public class ViewResolverRegistry {
|
||||
* @since 4.2
|
||||
*/
|
||||
public UrlBasedViewResolverRegistration scriptTemplate() {
|
||||
if (this.applicationContext != null && !hasBeanOfType(ScriptTemplateConfigurer.class)) {
|
||||
if (!checkBeanOfType(ScriptTemplateConfigurer.class)) {
|
||||
throw new BeanInitializationException("In addition to a script template view resolver " +
|
||||
"there must also be a single ScriptTemplateConfig bean in this web application context " +
|
||||
"(or its parent): ScriptTemplateConfigurer is the usual implementation. " +
|
||||
@@ -262,11 +269,12 @@ public class ViewResolverRegistry {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
protected boolean hasBeanOfType(Class<?> beanType) {
|
||||
return !ObjectUtils.isEmpty(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.applicationContext, beanType, false, false));
|
||||
}
|
||||
|
||||
private boolean checkBeanOfType(Class<?> beanType) {
|
||||
return (this.applicationContext == null ||
|
||||
!ObjectUtils.isEmpty(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.applicationContext, beanType, false, false)));
|
||||
}
|
||||
|
||||
protected int getOrder() {
|
||||
return (this.order != null ? this.order : Ordered.LOWEST_PRECEDENCE);
|
||||
|
||||
@@ -25,8 +25,6 @@ import java.util.Map;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
@@ -58,6 +56,7 @@ import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConve
|
||||
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.validation.Errors;
|
||||
@@ -198,22 +197,31 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
ClassUtils.isPresent("javax.json.bind.Jsonb", WebMvcConfigurationSupport.class.getClassLoader());
|
||||
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Nullable
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Nullable
|
||||
private List<Object> interceptors;
|
||||
|
||||
@Nullable
|
||||
private PathMatchConfigurer pathMatchConfigurer;
|
||||
|
||||
@Nullable
|
||||
private ContentNegotiationManager contentNegotiationManager;
|
||||
|
||||
@Nullable
|
||||
private List<HandlerMethodArgumentResolver> argumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private List<HandlerMethodReturnValueHandler> returnValueHandlers;
|
||||
|
||||
@Nullable
|
||||
private List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
@Nullable
|
||||
private Map<String, CorsConfiguration> corsConfigurations;
|
||||
|
||||
|
||||
@@ -229,7 +237,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
* Return the associated Spring {@link ApplicationContext}.
|
||||
* @since 4.2
|
||||
*/
|
||||
public ApplicationContext getApplicationContext() {
|
||||
@Nullable
|
||||
public final ApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
@@ -246,7 +255,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
* Return the associated {@link javax.servlet.ServletContext}.
|
||||
* @since 4.2
|
||||
*/
|
||||
public ServletContext getServletContext() {
|
||||
@Nullable
|
||||
public final ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
@@ -383,7 +393,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
try {
|
||||
this.contentNegotiationManager = configurer.getContentNegotiationManager();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanInitializationException("Could not create ContentNegotiationManager", ex);
|
||||
}
|
||||
}
|
||||
@@ -465,6 +475,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
*/
|
||||
@Bean
|
||||
public HandlerMapping resourceHandlerMapping() {
|
||||
Assert.state(this.applicationContext != null, "No ApplicationContext set");
|
||||
Assert.state(this.servletContext != null, "No ServletContext set");
|
||||
|
||||
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
|
||||
this.servletContext, mvcContentNegotiationManager());
|
||||
addResourceHandlers(registry);
|
||||
@@ -514,7 +527,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
*/
|
||||
@Bean
|
||||
public HandlerMapping defaultServletHandlerMapping() {
|
||||
DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(servletContext);
|
||||
Assert.state(this.servletContext != null, "No ServletContext set");
|
||||
DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(this.servletContext);
|
||||
configureDefaultServletHandling(configurer);
|
||||
AbstractHandlerMapping handlerMapping = configurer.getHandlerMapping();
|
||||
handlerMapping = handlerMapping != null ? handlerMapping : new EmptyHandlerMapping();
|
||||
@@ -785,16 +799,22 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
}
|
||||
|
||||
if (jackson2XmlPresent) {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.xml().applicationContext(this.applicationContext).build();
|
||||
messageConverters.add(new MappingJackson2XmlHttpMessageConverter(objectMapper));
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
|
||||
}
|
||||
else if (jaxb2Present) {
|
||||
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jackson2Present) {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().applicationContext(this.applicationContext).build();
|
||||
messageConverters.add(new MappingJackson2HttpMessageConverter(objectMapper));
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
|
||||
}
|
||||
else if (gsonPresent) {
|
||||
messageConverters.add(new GsonHttpMessageConverter());
|
||||
@@ -804,12 +824,18 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
}
|
||||
|
||||
if (jackson2SmilePresent) {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.smile().applicationContext(this.applicationContext).build();
|
||||
messageConverters.add(new MappingJackson2SmileHttpMessageConverter(objectMapper));
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
|
||||
}
|
||||
if (jackson2CborPresent) {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.cbor().applicationContext(this.applicationContext).build();
|
||||
messageConverters.add(new MappingJackson2CborHttpMessageConverter(objectMapper));
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -911,7 +937,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
exceptionHandlerResolver.setResponseBodyAdvice(
|
||||
Collections.singletonList(new JsonViewResponseBodyAdvice()));
|
||||
}
|
||||
exceptionHandlerResolver.setApplicationContext(this.applicationContext);
|
||||
if (this.applicationContext != null) {
|
||||
exceptionHandlerResolver.setApplicationContext(this.applicationContext);
|
||||
}
|
||||
exceptionHandlerResolver.afterPropertiesSet();
|
||||
exceptionResolvers.add(exceptionHandlerResolver);
|
||||
|
||||
@@ -947,7 +975,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
public ViewResolver mvcViewResolver() {
|
||||
ViewResolverRegistry registry = new ViewResolverRegistry();
|
||||
registry.setContentNegotiationManager(mvcContentNegotiationManager());
|
||||
registry.setApplicationContext(this.applicationContext);
|
||||
if (this.applicationContext != null) {
|
||||
registry.setApplicationContext(this.applicationContext);
|
||||
}
|
||||
configureViewResolvers(registry);
|
||||
|
||||
if (registry.getViewResolvers().isEmpty()) {
|
||||
@@ -962,7 +992,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
composite.setOrder(registry.getOrder());
|
||||
composite.setViewResolvers(registry.getViewResolvers());
|
||||
composite.setApplicationContext(this.applicationContext);
|
||||
composite.setServletContext(this.servletContext);
|
||||
if (this.servletContext != null) {
|
||||
composite.setServletContext(this.servletContext);
|
||||
}
|
||||
return composite;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -51,10 +51,13 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
@Nullable
|
||||
private Set<?> mappedHandlers;
|
||||
|
||||
@Nullable
|
||||
private Class<?>[] mappedHandlerClasses;
|
||||
|
||||
@Nullable
|
||||
private Log warnLogger;
|
||||
|
||||
private boolean preventResponseCaching = false;
|
||||
@@ -101,7 +104,6 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||
* <p>Default is no warn logging. Specify this setting to activate warn logging into a specific
|
||||
* category. Alternatively, override the {@link #logException} method for custom logging.
|
||||
* @see org.apache.commons.logging.LogFactory#getLog(String)
|
||||
* @see org.apache.log4j.Logger#getLogger(String)
|
||||
* @see java.util.logging.Logger#getLogger(String)
|
||||
*/
|
||||
public void setWarnLogCategory(String loggerName) {
|
||||
|
||||
@@ -69,6 +69,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
|
||||
|
||||
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
|
||||
|
||||
@Nullable
|
||||
private Object defaultHandler;
|
||||
|
||||
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
@@ -481,6 +482,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
|
||||
|
||||
private class PreFlightHandler implements HttpRequestHandler, CorsConfigurationSource {
|
||||
|
||||
@Nullable
|
||||
private final CorsConfiguration config;
|
||||
|
||||
public PreFlightHandler(@Nullable CorsConfiguration config) {
|
||||
@@ -501,6 +503,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
|
||||
|
||||
private class CorsInterceptor extends HandlerInterceptorAdapter implements CorsConfigurationSource {
|
||||
|
||||
@Nullable
|
||||
private final CorsConfiguration config;
|
||||
|
||||
public CorsInterceptor(@Nullable CorsConfiguration config) {
|
||||
|
||||
@@ -88,6 +88,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||
|
||||
private boolean detectHandlerMethodsInAncestorContexts = false;
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodMappingNamingStrategy<T> namingStrategy;
|
||||
|
||||
private final MappingRegistry mappingRegistry = new MappingRegistry();
|
||||
@@ -683,6 +684,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||
|
||||
private final List<String> directUrls;
|
||||
|
||||
@Nullable
|
||||
private final String mappingName;
|
||||
|
||||
public MappingRegistration(T mapping, HandlerMethod handlerMethod,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -34,18 +34,11 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
*/
|
||||
public class HandlerExceptionResolverComposite implements HandlerExceptionResolver, Ordered {
|
||||
|
||||
@Nullable
|
||||
private List<HandlerExceptionResolver> resolvers;
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of exception resolvers to delegate to.
|
||||
@@ -58,21 +51,30 @@ public class HandlerExceptionResolverComposite implements HandlerExceptionResolv
|
||||
* Return the list of exception resolvers to delegate to.
|
||||
*/
|
||||
public List<HandlerExceptionResolver> getExceptionResolvers() {
|
||||
return Collections.unmodifiableList(resolvers);
|
||||
return (this.resolvers != null ? Collections.unmodifiableList(this.resolvers) : Collections.emptyList());
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve the exception by iterating over the list of configured exception resolvers.
|
||||
* The first one to return a ModelAndView instance wins. Otherwise {@code null} is returned.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public ModelAndView resolveException(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@Nullable Object handler,
|
||||
Exception ex) {
|
||||
if (resolvers != null) {
|
||||
for (HandlerExceptionResolver handlerExceptionResolver : resolvers) {
|
||||
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
|
||||
@Nullable Object handler,Exception ex) {
|
||||
|
||||
if (this.resolvers != null) {
|
||||
for (HandlerExceptionResolver handlerExceptionResolver : this.resolvers) {
|
||||
ModelAndView mav = handlerExceptionResolver.resolveException(request, response, handler, ex);
|
||||
if (mav != null) {
|
||||
return mav;
|
||||
|
||||
@@ -45,12 +45,15 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
*/
|
||||
public final class MappedInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Nullable
|
||||
private final String[] includePatterns;
|
||||
|
||||
@Nullable
|
||||
private final String[] excludePatterns;
|
||||
|
||||
private final HandlerInterceptor interceptor;
|
||||
|
||||
@Nullable
|
||||
private PathMatcher pathMatcher;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,7 +21,6 @@ import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -49,16 +48,21 @@ public class SimpleMappingExceptionResolver extends AbstractHandlerExceptionReso
|
||||
public static final String DEFAULT_EXCEPTION_ATTRIBUTE = "exception";
|
||||
|
||||
|
||||
@Nullable
|
||||
private Properties exceptionMappings;
|
||||
|
||||
@Nullable
|
||||
private Class<?>[] excludedExceptions;
|
||||
|
||||
@Nullable
|
||||
private String defaultErrorView;
|
||||
|
||||
@Nullable
|
||||
private Integer defaultStatusCode;
|
||||
|
||||
private Map<String, Integer> statusCodes = new HashMap<>();
|
||||
|
||||
@Nullable
|
||||
private String exceptionAttribute = DEFAULT_EXCEPTION_ATTRIBUTE;
|
||||
|
||||
|
||||
|
||||
@@ -69,8 +69,10 @@ public class SimpleServletPostProcessor implements
|
||||
|
||||
private boolean useSharedServletConfig = true;
|
||||
|
||||
@Nullable
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Nullable
|
||||
private ServletConfig servletConfig;
|
||||
|
||||
|
||||
@@ -140,9 +142,10 @@ public class SimpleServletPostProcessor implements
|
||||
|
||||
private final String servletName;
|
||||
|
||||
@Nullable
|
||||
private final ServletContext servletContext;
|
||||
|
||||
public DelegatingServletConfig(String servletName, ServletContext servletContext) {
|
||||
public DelegatingServletConfig(String servletName, @Nullable ServletContext servletContext) {
|
||||
this.servletName = servletName;
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
@@ -153,6 +156,7 @@ public class SimpleServletPostProcessor implements
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,6 +21,8 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Interceptor that checks the authorization of the current user via the
|
||||
* user's roles, as evaluated by HttpServletRequest's isUserInRole method.
|
||||
@@ -31,6 +33,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
*/
|
||||
public class UserRoleAuthorizationInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
@Nullable
|
||||
private String[] authorizedRoles;
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
@@ -87,8 +88,10 @@ import org.springframework.web.util.WebUtils;
|
||||
*/
|
||||
public class ServletForwardingController extends AbstractController implements BeanNameAware {
|
||||
|
||||
@Nullable
|
||||
private String servletName;
|
||||
|
||||
@Nullable
|
||||
private String beanName;
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@@ -84,14 +85,18 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
public class ServletWrappingController extends AbstractController
|
||||
implements BeanNameAware, InitializingBean, DisposableBean {
|
||||
|
||||
@Nullable
|
||||
private Class<? extends Servlet> servletClass;
|
||||
|
||||
@Nullable
|
||||
private String servletName;
|
||||
|
||||
private Properties initParameters = new Properties();
|
||||
|
||||
@Nullable
|
||||
private String beanName;
|
||||
|
||||
@Nullable
|
||||
private Servlet servletInstance;
|
||||
|
||||
|
||||
@@ -156,6 +161,7 @@ public class ServletWrappingController extends AbstractController
|
||||
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
|
||||
throws Exception {
|
||||
|
||||
Assert.state(this.servletInstance != null, "No Servlet instance");
|
||||
this.servletInstance.service(request, response);
|
||||
return null;
|
||||
}
|
||||
@@ -167,7 +173,9 @@ public class ServletWrappingController extends AbstractController
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.servletInstance.destroy();
|
||||
if (this.servletInstance != null) {
|
||||
this.servletInstance.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -179,6 +187,7 @@ public class ServletWrappingController extends AbstractController
|
||||
private class DelegatingServletConfig implements ServletConfig {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getServletName() {
|
||||
return servletName;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -56,6 +55,7 @@ import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
|
||||
*/
|
||||
public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver implements MessageSourceAware {
|
||||
|
||||
@Nullable
|
||||
private MessageSource messageSource;
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.condition;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Supports "name=value" style expressions as described in:
|
||||
* {@link org.springframework.web.bind.annotation.RequestMapping#params()} and
|
||||
@@ -31,6 +33,7 @@ abstract class AbstractNameValueExpression<T> implements NameValueExpression<T>
|
||||
|
||||
protected final String name;
|
||||
|
||||
@Nullable
|
||||
protected final T value;
|
||||
|
||||
protected final boolean isNegated;
|
||||
@@ -40,12 +43,12 @@ abstract class AbstractNameValueExpression<T> implements NameValueExpression<T>
|
||||
int separator = expression.indexOf('=');
|
||||
if (separator == -1) {
|
||||
this.isNegated = expression.startsWith("!");
|
||||
this.name = isNegated ? expression.substring(1) : expression;
|
||||
this.name = (this.isNegated ? expression.substring(1) : expression);
|
||||
this.value = null;
|
||||
}
|
||||
else {
|
||||
this.isNegated = (separator > 0) && (expression.charAt(separator - 1) == '!');
|
||||
this.name = isNegated ? expression.substring(0, separator - 1) : expression.substring(0, separator);
|
||||
this.name = (this.isNegated ? expression.substring(0, separator - 1) : expression.substring(0, separator));
|
||||
this.value = parseValue(expression.substring(separator + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.InvalidMediaTypeException;
|
||||
@@ -90,7 +89,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
||||
if (headers != null) {
|
||||
for (String header : headers) {
|
||||
HeaderExpression expr = new HeaderExpression(header);
|
||||
if ("Content-Type".equalsIgnoreCase(expr.name)) {
|
||||
if ("Content-Type".equalsIgnoreCase(expr.name) && expr.value != null) {
|
||||
for (MediaType mediaType : MediaType.parseMediaTypes(expr.value)) {
|
||||
result.add(new ConsumeMediaTypeExpression(mediaType, expr.isNegated));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.cors.CorsUtils;
|
||||
|
||||
@@ -156,12 +157,12 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
|
||||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return request.getHeader(name) != null;
|
||||
return (request.getHeader(this.name) != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(HttpServletRequest request) {
|
||||
return value.equals(request.getHeader(name));
|
||||
return ObjectUtils.nullSafeEquals(this.value, request.getHeader(this.name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.condition;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
@@ -24,7 +25,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*
|
||||
* @see RequestMapping#params()
|
||||
* @see RequestMapping#headers()
|
||||
*/
|
||||
@@ -32,6 +32,7 @@ public interface NameValueExpression<T> {
|
||||
|
||||
String getName();
|
||||
|
||||
@Nullable
|
||||
T getValue();
|
||||
|
||||
boolean isNegated();
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
@@ -141,12 +142,12 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
|
||||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return WebUtils.hasSubmitParameter(request, name);
|
||||
return WebUtils.hasSubmitParameter(request, this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(HttpServletRequest request) {
|
||||
return value.equals(request.getParameter(name));
|
||||
return ObjectUtils.nullSafeEquals(this.value, request.getParameter(this.name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
||||
if (headers != null) {
|
||||
for (String header : headers) {
|
||||
HeaderExpression expr = new HeaderExpression(header);
|
||||
if ("Accept".equalsIgnoreCase(expr.name)) {
|
||||
if ("Accept".equalsIgnoreCase(expr.name) && expr.value != null) {
|
||||
for (MediaType mediaType : MediaType.parseMediaTypes(expr.value)) {
|
||||
result.add(new ProduceMediaTypeExpression(mediaType, expr.isNegated));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.web.servlet.mvc.condition;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -39,6 +38,7 @@ import org.springframework.lang.Nullable;
|
||||
*/
|
||||
public final class RequestConditionHolder extends AbstractRequestCondition<RequestConditionHolder> {
|
||||
|
||||
@Nullable
|
||||
private final RequestCondition<Object> condition;
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
assertEqualConditionTypes(other);
|
||||
assertEqualConditionTypes(this.condition, other.condition);
|
||||
RequestCondition<?> combined = (RequestCondition<?>) this.condition.combine(other.condition);
|
||||
return new RequestConditionHolder(combined);
|
||||
}
|
||||
@@ -96,9 +96,9 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
||||
/**
|
||||
* Ensure the held request conditions are of the same type.
|
||||
*/
|
||||
private void assertEqualConditionTypes(RequestConditionHolder other) {
|
||||
Class<?> clazz = this.condition.getClass();
|
||||
Class<?> otherClazz = other.condition.getClass();
|
||||
private void assertEqualConditionTypes(RequestCondition<?> thisCondition, RequestCondition<?> otherCondition) {
|
||||
Class<?> clazz = thisCondition.getClass();
|
||||
Class<?> otherClazz = otherCondition.getClass();
|
||||
if (!clazz.equals(otherClazz)) {
|
||||
throw new ClassCastException("Incompatible request conditions: " + clazz + " and " + otherClazz);
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
assertEqualConditionTypes(other);
|
||||
assertEqualConditionTypes(this.condition, other.condition);
|
||||
return this.condition.compareTo(other.condition, request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
*/
|
||||
public final class RequestMappingInfo implements RequestCondition<RequestMappingInfo> {
|
||||
|
||||
@Nullable
|
||||
private final String name;
|
||||
|
||||
private final PatternsRequestCondition patternsCondition;
|
||||
@@ -418,8 +419,10 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
|
||||
private String[] produces = new String[0];
|
||||
|
||||
@Nullable
|
||||
private String mappingName;
|
||||
|
||||
@Nullable
|
||||
private RequestCondition<?> customCondition;
|
||||
|
||||
private BuilderConfiguration options = new BuilderConfiguration();
|
||||
@@ -511,8 +514,10 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
*/
|
||||
public static class BuilderConfiguration {
|
||||
|
||||
@Nullable
|
||||
private UrlPathHelper urlPathHelper;
|
||||
|
||||
@Nullable
|
||||
private PathMatcher pathMatcher;
|
||||
|
||||
private boolean trailingSlashMatch = true;
|
||||
@@ -521,6 +526,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
|
||||
private boolean registeredSuffixPatternMatch = false;
|
||||
|
||||
@Nullable
|
||||
private ContentNegotiationManager contentNegotiationManager;
|
||||
|
||||
/**
|
||||
@@ -614,7 +620,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
*/
|
||||
@Nullable
|
||||
public List<String> getFileExtensions() {
|
||||
if (useRegisteredSuffixPatternMatch() && getContentNegotiationManager() != null) {
|
||||
if (useRegisteredSuffixPatternMatch() && this.contentNegotiationManager != null) {
|
||||
return this.contentNegotiationManager.getAllFileExtensions();
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
@@ -302,6 +303,7 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||
|
||||
private final HttpHeaders headers;
|
||||
|
||||
@Nullable
|
||||
private final InputStream body;
|
||||
|
||||
public EmptyBodyCheckingHttpInputMessage(HttpInputMessage inputMessage) throws IOException {
|
||||
@@ -332,7 +334,7 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||
|
||||
@Override
|
||||
public InputStream getBody() {
|
||||
return this.body;
|
||||
return (this.body != null ? this.body : StreamUtils.emptyInput());
|
||||
}
|
||||
|
||||
public boolean hasBody() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -33,10 +33,11 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
*/
|
||||
public class AsyncTaskMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
|
||||
@Nullable
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
|
||||
public AsyncTaskMethodReturnValueHandler(BeanFactory beanFactory) {
|
||||
public AsyncTaskMethodReturnValueHandler(@Nullable BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@@ -56,7 +57,9 @@ public class AsyncTaskMethodReturnValueHandler implements HandlerMethodReturnVal
|
||||
}
|
||||
|
||||
WebAsyncTask<?> webAsyncTask = (WebAsyncTask<?>) returnValue;
|
||||
webAsyncTask.setBeanFactory(this.beanFactory);
|
||||
if (this.beanFactory != null) {
|
||||
webAsyncTask.setBeanFactory(this.beanFactory);
|
||||
}
|
||||
WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(webAsyncTask, mavContainer);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,12 +75,16 @@ import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver
|
||||
implements ApplicationContextAware, InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodArgumentResolverComposite argumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
|
||||
|
||||
private List<HttpMessageConverter<?>> messageConverters;
|
||||
@@ -89,6 +93,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
|
||||
|
||||
private final List<Object> responseBodyAdvice = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache =
|
||||
@@ -374,8 +379,12 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
|
||||
return null;
|
||||
}
|
||||
|
||||
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
|
||||
if (this.argumentResolvers != null) {
|
||||
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
}
|
||||
if (this.returnValueHandlers != null) {
|
||||
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
|
||||
}
|
||||
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request, response);
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
@@ -51,7 +50,7 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
* @param objectName the name of the target object
|
||||
* @see #DEFAULT_OBJECT_NAME
|
||||
*/
|
||||
public ExtendedServletRequestDataBinder(@Nullable Object target, @Nullable String objectName) {
|
||||
public ExtendedServletRequestDataBinder(@Nullable Object target, String objectName) {
|
||||
super(target, objectName);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
|
||||
*/
|
||||
public class ModelAndViewResolverMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
|
||||
@Nullable
|
||||
private final List<ModelAndViewResolver> mavResolvers;
|
||||
|
||||
private final ModelAttributeMethodProcessor modelAttributeProcessor = new ModelAttributeMethodProcessor(true);
|
||||
|
||||
@@ -717,21 +717,14 @@ public class MvcUriComponentsBuilder {
|
||||
private static class ControllerMethodInvocationInterceptor
|
||||
implements org.springframework.cglib.proxy.MethodInterceptor, MethodInterceptor {
|
||||
|
||||
private static final Method getControllerMethod =
|
||||
ReflectionUtils.findMethod(MethodInvocationInfo.class, "getControllerMethod");
|
||||
|
||||
private static final Method getArgumentValues =
|
||||
ReflectionUtils.findMethod(MethodInvocationInfo.class, "getArgumentValues");
|
||||
|
||||
private static final Method getControllerType =
|
||||
ReflectionUtils.findMethod(MethodInvocationInfo.class, "getControllerType");
|
||||
private final Class<?> controllerType;
|
||||
|
||||
@Nullable
|
||||
private Method controllerMethod;
|
||||
|
||||
@Nullable
|
||||
private Object[] argumentValues;
|
||||
|
||||
private Class<?> controllerType;
|
||||
|
||||
ControllerMethodInvocationInterceptor(Class<?> controllerType) {
|
||||
this.controllerType = controllerType;
|
||||
}
|
||||
@@ -739,13 +732,13 @@ public class MvcUriComponentsBuilder {
|
||||
@Override
|
||||
@Nullable
|
||||
public Object intercept(Object obj, Method method, Object[] args, @Nullable MethodProxy proxy) {
|
||||
if (method.equals(getControllerMethod)) {
|
||||
if (method.getName().equals("getControllerMethod")) {
|
||||
return this.controllerMethod;
|
||||
}
|
||||
else if (method.equals(getArgumentValues)) {
|
||||
else if (method.getName().equals("getArgumentValues")) {
|
||||
return this.argumentValues;
|
||||
}
|
||||
else if (method.equals(getControllerType)) {
|
||||
else if (method.getName().equals("getControllerType")) {
|
||||
return this.controllerType;
|
||||
}
|
||||
else if (ReflectionUtils.isObjectMethod(method)) {
|
||||
|
||||
@@ -180,10 +180,12 @@ class ReactiveTypeHandler {
|
||||
|
||||
private final TaskExecutor taskExecutor;
|
||||
|
||||
@Nullable
|
||||
private Subscription subscription;
|
||||
|
||||
private final AtomicReference<Object> elementRef = new AtomicReference<>();
|
||||
|
||||
@Nullable
|
||||
private Throwable error;
|
||||
|
||||
private volatile boolean terminated;
|
||||
@@ -219,7 +221,7 @@ class ReactiveTypeHandler {
|
||||
terminate();
|
||||
this.emitter.complete();
|
||||
});
|
||||
this.emitter.onError(t -> this.emitter.completeWithError(t));
|
||||
this.emitter.onError(this.emitter::completeWithError);
|
||||
subscription.request(1);
|
||||
}
|
||||
|
||||
@@ -276,6 +278,7 @@ class ReactiveTypeHandler {
|
||||
Object element = this.elementRef.get();
|
||||
if (element != null) {
|
||||
this.elementRef.lazySet(null);
|
||||
Assert.state(this.subscription != null, "No subscription");
|
||||
try {
|
||||
send(element);
|
||||
this.subscription.request(1);
|
||||
@@ -317,7 +320,9 @@ class ReactiveTypeHandler {
|
||||
|
||||
private void terminate() {
|
||||
this.done = true;
|
||||
this.subscription.cancel();
|
||||
if (this.subscription != null) {
|
||||
this.subscription.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ public class RedirectAttributesMethodArgumentResolver implements HandlerMethodAr
|
||||
|
||||
ModelMap redirectAttributes;
|
||||
if (binderFactory != null) {
|
||||
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
|
||||
redirectAttributes = new RedirectAttributesModelMap(dataBinder);
|
||||
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, DataBinder.DEFAULT_OBJECT_NAME);
|
||||
redirectAttributes = new RedirectAttributesModelMap(dataBinder);
|
||||
}
|
||||
else {
|
||||
redirectAttributes = new RedirectAttributesModelMap();
|
||||
|
||||
@@ -116,16 +116,22 @@ import org.springframework.web.util.WebUtils;
|
||||
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
implements BeanFactoryAware, InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodArgumentResolverComposite argumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
|
||||
|
||||
@Nullable
|
||||
private List<ModelAndViewResolver> modelAndViewResolvers;
|
||||
|
||||
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
|
||||
@@ -134,10 +140,12 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
|
||||
private List<Object> requestResponseBodyAdvice = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private WebBindingInitializer webBindingInitializer;
|
||||
|
||||
private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync");
|
||||
|
||||
@Nullable
|
||||
private Long asyncRequestTimeout;
|
||||
|
||||
private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0];
|
||||
@@ -156,21 +164,19 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
|
||||
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
@Nullable
|
||||
private ConfigurableBeanFactory beanFactory;
|
||||
|
||||
|
||||
private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache =
|
||||
new ConcurrentHashMap<>(64);
|
||||
private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64);
|
||||
|
||||
private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);
|
||||
|
||||
private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache =
|
||||
new LinkedHashMap<>();
|
||||
private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>();
|
||||
|
||||
private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);
|
||||
|
||||
private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache =
|
||||
new LinkedHashMap<>();
|
||||
private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();
|
||||
|
||||
|
||||
public RequestMappingHandlerAdapter() {
|
||||
@@ -284,7 +290,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
*/
|
||||
@Nullable
|
||||
public List<HandlerMethodReturnValueHandler> getReturnValueHandlers() {
|
||||
return this.returnValueHandlers.getHandlers();
|
||||
return (this.returnValueHandlers != null ? this.returnValueHandlers.getHandlers() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +316,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
*/
|
||||
@Nullable
|
||||
public List<ModelAndViewResolver> getModelAndViewResolvers() {
|
||||
return modelAndViewResolvers;
|
||||
return this.modelAndViewResolvers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -827,8 +833,12 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
|
||||
|
||||
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
|
||||
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
|
||||
if (this.argumentResolvers != null) {
|
||||
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
}
|
||||
if (this.returnValueHandlers != null) {
|
||||
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
|
||||
}
|
||||
invocableMethod.setDataBinderFactory(binderFactory);
|
||||
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
|
||||
|
||||
@@ -905,7 +915,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
|
||||
private InvocableHandlerMethod createModelAttributeMethod(WebDataBinderFactory factory, Object bean, Method method) {
|
||||
InvocableHandlerMethod attrMethod = new InvocableHandlerMethod(bean, method);
|
||||
attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
if (this.argumentResolvers != null) {
|
||||
attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
}
|
||||
attrMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
|
||||
attrMethod.setDataBinderFactory(factory);
|
||||
return attrMethod;
|
||||
@@ -937,7 +949,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
|
||||
private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
|
||||
InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);
|
||||
binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
|
||||
if (this.initBinderArgumentResolvers != null) {
|
||||
binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
|
||||
}
|
||||
binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
|
||||
binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
|
||||
return binderMethod;
|
||||
|
||||
@@ -64,6 +64,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||
|
||||
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
|
||||
|
||||
@Nullable
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
private RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();
|
||||
|
||||
@@ -63,14 +63,17 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
public class ResponseBodyEmitter {
|
||||
|
||||
@Nullable
|
||||
private final Long timeout;
|
||||
|
||||
private final Set<DataWithMediaType> earlySendAttempts = new LinkedHashSet<>(8);
|
||||
|
||||
@Nullable
|
||||
private Handler handler;
|
||||
|
||||
private boolean complete;
|
||||
|
||||
@Nullable
|
||||
private Throwable failure;
|
||||
|
||||
private final DefaultCallback timeoutCallback = new DefaultCallback();
|
||||
@@ -270,6 +273,7 @@ public class ResponseBodyEmitter {
|
||||
|
||||
private final Object data;
|
||||
|
||||
@Nullable
|
||||
private final MediaType mediaType;
|
||||
|
||||
public DataWithMediaType(Object data, @Nullable MediaType mediaType) {
|
||||
@@ -290,6 +294,7 @@ public class ResponseBodyEmitter {
|
||||
|
||||
private class DefaultCallback implements Runnable {
|
||||
|
||||
@Nullable
|
||||
private Runnable delegate;
|
||||
|
||||
public void setDelegate(Runnable delegate) {
|
||||
@@ -308,6 +313,7 @@ public class ResponseBodyEmitter {
|
||||
|
||||
private class ErrorCallback implements Consumer<Throwable> {
|
||||
|
||||
@Nullable
|
||||
private Consumer<Throwable> delegate;
|
||||
|
||||
public void setDelegate(Consumer<Throwable> callback) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@@ -60,6 +61,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||
|
||||
private static final Method CALLABLE_METHOD = ClassUtils.getMethod(Callable.class, "call");
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
|
||||
|
||||
|
||||
@@ -112,6 +114,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||
}
|
||||
|
||||
mavContainer.setRequestHandled(false);
|
||||
Assert.state(this.returnValueHandlers != null, "No return value handlers");
|
||||
try {
|
||||
this.returnValueHandlers.handleReturnValue(
|
||||
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
|
||||
@@ -188,20 +191,19 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||
private final MethodParameter returnType;
|
||||
|
||||
public ConcurrentResultHandlerMethod(final Object result, ConcurrentResultMethodParameter returnType) {
|
||||
super(new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
if (result instanceof Exception) {
|
||||
throw (Exception) result;
|
||||
}
|
||||
else if (result instanceof Throwable) {
|
||||
throw new NestedServletException("Async processing failed", (Throwable) result);
|
||||
}
|
||||
return result;
|
||||
super((Callable<Object>) () -> {
|
||||
if (result instanceof Exception) {
|
||||
throw (Exception) result;
|
||||
}
|
||||
else if (result instanceof Throwable) {
|
||||
throw new NestedServletException("Async processing failed", (Throwable) result);
|
||||
}
|
||||
return result;
|
||||
}, CALLABLE_METHOD);
|
||||
|
||||
setHandlerMethodReturnValueHandlers(ServletInvocableHandlerMethod.this.returnValueHandlers);
|
||||
if (ServletInvocableHandlerMethod.this.returnValueHandlers != null) {
|
||||
setHandlerMethodReturnValueHandlers(ServletInvocableHandlerMethod.this.returnValueHandlers);
|
||||
}
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
@@ -247,6 +249,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||
*/
|
||||
private class ConcurrentResultMethodParameter extends HandlerMethodParameter {
|
||||
|
||||
@Nullable
|
||||
private final Object returnValue;
|
||||
|
||||
private final ResolvableType returnType;
|
||||
|
||||
@@ -128,7 +128,7 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
|
||||
* @throws Exception
|
||||
*/
|
||||
@Nullable
|
||||
protected Object createAttributeFromRequestValue(String sourceValue, @Nullable String attributeName,
|
||||
protected Object createAttributeFromRequestValue(String sourceValue, String attributeName,
|
||||
MethodParameter methodParam, WebDataBinderFactory binderFactory, NativeWebRequest request)
|
||||
throws Exception {
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ServletRequestDataBinderFactory extends InitBinderDataBinderFactory
|
||||
*/
|
||||
@Override
|
||||
protected ServletRequestDataBinder createBinderInstance(
|
||||
@Nullable Object target, @Nullable String objectName, NativeWebRequest request) throws Exception {
|
||||
@Nullable Object target, String objectName, NativeWebRequest request) throws Exception {
|
||||
|
||||
return new ExtendedServletRequestDataBinder(target, objectName);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
*/
|
||||
public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
@Nullable
|
||||
private static final Method newPushBuilderMethod =
|
||||
ClassUtils.getMethodIfAvailable(HttpServletRequest.class, "newPushBuilder");
|
||||
|
||||
|
||||
@@ -189,6 +189,7 @@ public class SseEmitter extends ResponseBodyEmitter {
|
||||
|
||||
private final Set<DataWithMediaType> dataToSend = new LinkedHashSet<>(4);
|
||||
|
||||
@Nullable
|
||||
private StringBuilder sb;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.validation.DataBinder;
|
||||
@SuppressWarnings("serial")
|
||||
public class RedirectAttributesModelMap extends ModelMap implements RedirectAttributes {
|
||||
|
||||
@Nullable
|
||||
private final DataBinder dataBinder;
|
||||
|
||||
private final ModelMap flashAttributes = new ModelMap();
|
||||
|
||||
@@ -217,6 +217,7 @@ public class AppCacheManifestTransformer extends ResourceTransformerSupport {
|
||||
|
||||
private final String line;
|
||||
|
||||
@Nullable
|
||||
private final Resource resource;
|
||||
|
||||
public LineOutput(String line, @Nullable Resource resource) {
|
||||
|
||||
@@ -100,14 +100,19 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
|
||||
private final List<ResourceTransformer> resourceTransformers = new ArrayList<>(4);
|
||||
|
||||
@Nullable
|
||||
private ResourceHttpMessageConverter resourceHttpMessageConverter;
|
||||
|
||||
@Nullable
|
||||
private ResourceRegionHttpMessageConverter resourceRegionHttpMessageConverter;
|
||||
|
||||
@Nullable
|
||||
private ContentNegotiationManager contentNegotiationManager;
|
||||
|
||||
@Nullable
|
||||
private PathExtensionContentNegotiationStrategy contentNegotiationStrategy;
|
||||
|
||||
@Nullable
|
||||
private CorsConfiguration corsConfiguration;
|
||||
|
||||
|
||||
@@ -176,14 +181,15 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
* <p>By default a {@link ResourceHttpMessageConverter} will be configured.
|
||||
* @since 4.3
|
||||
*/
|
||||
public void setResourceHttpMessageConverter(ResourceHttpMessageConverter resourceHttpMessageConverter) {
|
||||
this.resourceHttpMessageConverter = resourceHttpMessageConverter;
|
||||
public void setResourceHttpMessageConverter(ResourceHttpMessageConverter messageConverter) {
|
||||
this.resourceHttpMessageConverter = messageConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured resource converter.
|
||||
* @since 4.3
|
||||
*/
|
||||
@Nullable
|
||||
public ResourceHttpMessageConverter getResourceHttpMessageConverter() {
|
||||
return this.resourceHttpMessageConverter;
|
||||
}
|
||||
@@ -193,14 +199,15 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
* <p>By default a {@link ResourceRegionHttpMessageConverter} will be configured.
|
||||
* @since 4.3
|
||||
*/
|
||||
public void setResourceRegionHttpMessageConverter(ResourceRegionHttpMessageConverter resourceRegionHttpMessageConverter) {
|
||||
this.resourceRegionHttpMessageConverter = resourceRegionHttpMessageConverter;
|
||||
public void setResourceRegionHttpMessageConverter(ResourceRegionHttpMessageConverter messageConverter) {
|
||||
this.resourceRegionHttpMessageConverter = messageConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured resource region converter.
|
||||
* @since 4.3
|
||||
*/
|
||||
@Nullable
|
||||
public ResourceRegionHttpMessageConverter getResourceRegionHttpMessageConverter() {
|
||||
return this.resourceRegionHttpMessageConverter;
|
||||
}
|
||||
@@ -368,10 +375,12 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
|
||||
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
|
||||
if (request.getHeader(HttpHeaders.RANGE) == null) {
|
||||
Assert.state(this.resourceHttpMessageConverter != null, "Not initialized");
|
||||
setHeaders(response, resource, mediaType);
|
||||
this.resourceHttpMessageConverter.write(resource, mediaType, outputMessage);
|
||||
}
|
||||
else {
|
||||
Assert.state(this.resourceRegionHttpMessageConverter != null, "Not initialized");
|
||||
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
|
||||
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(request);
|
||||
try {
|
||||
@@ -516,7 +525,8 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
*/
|
||||
@Nullable
|
||||
protected MediaType getMediaType(HttpServletRequest request, Resource resource) {
|
||||
return this.contentNegotiationStrategy.getMediaTypeForResource(resource);
|
||||
return (this.contentNegotiationStrategy != null ?
|
||||
this.contentNegotiationStrategy.getMediaTypeForResource(resource) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class ResourceTransformerSupport implements ResourceTransformer {
|
||||
|
||||
@Nullable
|
||||
private ResourceUrlProvider resourceUrlProvider;
|
||||
|
||||
|
||||
@@ -43,15 +44,15 @@ public abstract class ResourceTransformerSupport implements ResourceTransformer
|
||||
* URL of links in a transformed resource (e.g. import links in a CSS file).
|
||||
* This is required only for links expressed as full paths and not for
|
||||
* relative links.
|
||||
* @param resourceUrlProvider the URL provider to use
|
||||
*/
|
||||
public void setResourceUrlProvider(ResourceUrlProvider resourceUrlProvider) {
|
||||
this.resourceUrlProvider = resourceUrlProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the configured {@code ResourceUrlProvider}.
|
||||
* Return the configured {@code ResourceUrlProvider}.
|
||||
*/
|
||||
@Nullable
|
||||
public ResourceUrlProvider getResourceUrlProvider() {
|
||||
return this.resourceUrlProvider;
|
||||
}
|
||||
|
||||
@@ -66,9 +66,10 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean {
|
||||
private final HttpServletRequest request;
|
||||
|
||||
/* Cache the index and prefix of the path within the DispatcherServlet mapping */
|
||||
@Nullable
|
||||
private Integer indexLookupPath;
|
||||
|
||||
private String prefixLookupPath;
|
||||
private String prefixLookupPath = "";
|
||||
|
||||
public ResourceUrlEncodingResponseWrapper(HttpServletRequest request, HttpServletResponse wrapped) {
|
||||
super(wrapped);
|
||||
@@ -83,11 +84,11 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean {
|
||||
return super.encodeURL(url);
|
||||
}
|
||||
|
||||
initLookupPath(resourceUrlProvider);
|
||||
int index = initLookupPath(resourceUrlProvider);
|
||||
if (url.startsWith(this.prefixLookupPath)) {
|
||||
int suffixIndex = getQueryParamsIndex(url);
|
||||
String suffix = url.substring(suffixIndex);
|
||||
String lookupPath = url.substring(this.indexLookupPath, suffixIndex);
|
||||
String lookupPath = url.substring(index, suffixIndex);
|
||||
lookupPath = resourceUrlProvider.getForLookupPath(lookupPath);
|
||||
if (lookupPath != null) {
|
||||
return super.encodeURL(this.prefixLookupPath + lookupPath + suffix);
|
||||
@@ -103,14 +104,13 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean {
|
||||
ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR);
|
||||
}
|
||||
|
||||
private void initLookupPath(ResourceUrlProvider urlProvider) {
|
||||
private int initLookupPath(ResourceUrlProvider urlProvider) {
|
||||
if (this.indexLookupPath == null) {
|
||||
UrlPathHelper pathHelper = urlProvider.getUrlPathHelper();
|
||||
String requestUri = pathHelper.getRequestUri(this.request);
|
||||
String lookupPath = pathHelper.getLookupPathForRequest(this.request);
|
||||
this.indexLookupPath = requestUri.lastIndexOf(lookupPath);
|
||||
this.prefixLookupPath = requestUri.substring(0, this.indexLookupPath);
|
||||
|
||||
if ("/".equals(lookupPath) && !"/".equals(requestUri)) {
|
||||
String contextPath = pathHelper.getContextPath(this.request);
|
||||
if (requestUri.equals(contextPath)) {
|
||||
@@ -119,6 +119,7 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean {
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.indexLookupPath;
|
||||
}
|
||||
|
||||
private int getQueryParamsIndex(String url) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,11 +20,12 @@ import java.io.IOException;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* An extension of {@link org.springframework.core.io.ByteArrayResource}
|
||||
* that a {@link ResourceTransformer} can use to represent an original
|
||||
* resource preserving all other information except the content.
|
||||
* An extension of {@link ByteArrayResource} that a {@link ResourceTransformer}
|
||||
* can use to represent an original resource preserving all other information
|
||||
* except the content.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author Rossen Stoyanchev
|
||||
@@ -32,6 +33,7 @@ import org.springframework.core.io.Resource;
|
||||
*/
|
||||
public class TransformedResource extends ByteArrayResource {
|
||||
|
||||
@Nullable
|
||||
private final String filename;
|
||||
|
||||
private final long lastModified;
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.context.NoSuchMessageException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
@@ -54,24 +55,33 @@ public class BindStatus {
|
||||
|
||||
private final boolean htmlEscape;
|
||||
|
||||
@Nullable
|
||||
private final String expression;
|
||||
|
||||
@Nullable
|
||||
private final Errors errors;
|
||||
|
||||
@Nullable
|
||||
private BindingResult bindingResult;
|
||||
|
||||
@Nullable
|
||||
private Object value;
|
||||
|
||||
@Nullable
|
||||
private Class<?> valueType;
|
||||
|
||||
@Nullable
|
||||
private Object actualValue;
|
||||
|
||||
@Nullable
|
||||
private PropertyEditor editor;
|
||||
|
||||
@Nullable
|
||||
private List<? extends ObjectError> objectErrors;
|
||||
|
||||
private String[] errorCodes;
|
||||
private String[] errorCodes = new String[0];
|
||||
|
||||
@Nullable
|
||||
private String[] errorMessages;
|
||||
|
||||
|
||||
@@ -133,7 +143,7 @@ public class BindStatus {
|
||||
else {
|
||||
this.objectErrors = this.errors.getGlobalErrors();
|
||||
}
|
||||
initErrorCodes();
|
||||
initErrorCodes(this.objectErrors);
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -163,27 +173,14 @@ public class BindStatus {
|
||||
/**
|
||||
* Extract the error codes from the ObjectError list.
|
||||
*/
|
||||
private void initErrorCodes() {
|
||||
this.errorCodes = new String[this.objectErrors.size()];
|
||||
for (int i = 0; i < this.objectErrors.size(); i++) {
|
||||
ObjectError error = this.objectErrors.get(i);
|
||||
private void initErrorCodes(List<? extends ObjectError> objectErrors) {
|
||||
this.errorCodes = new String[objectErrors.size()];
|
||||
for (int i = 0; i < objectErrors.size(); i++) {
|
||||
ObjectError error = objectErrors.get(i);
|
||||
this.errorCodes[i] = error.getCode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the error messages from the ObjectError list.
|
||||
*/
|
||||
private void initErrorMessages() throws NoSuchMessageException {
|
||||
if (this.errorMessages == null) {
|
||||
this.errorMessages = new String[this.objectErrors.size()];
|
||||
for (int i = 0; i < this.objectErrors.size(); i++) {
|
||||
ObjectError error = this.objectErrors.get(i);
|
||||
this.errorMessages[i] = this.requestContext.getMessage(error, this.htmlEscape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the bean and property path for which values and errors
|
||||
@@ -256,14 +253,13 @@ public class BindStatus {
|
||||
* Return if this status represents a field or object error.
|
||||
*/
|
||||
public boolean isError() {
|
||||
return (this.errorCodes != null && this.errorCodes.length > 0);
|
||||
return (this.errorCodes.length > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the error codes for the field or object, if any.
|
||||
* Returns an empty array instead of null if none.
|
||||
*/
|
||||
@Nullable
|
||||
public String[] getErrorCodes() {
|
||||
return this.errorCodes;
|
||||
}
|
||||
@@ -280,16 +276,15 @@ public class BindStatus {
|
||||
* if any. Returns an empty array instead of null if none.
|
||||
*/
|
||||
public String[] getErrorMessages() {
|
||||
initErrorMessages();
|
||||
return this.errorMessages;
|
||||
return initErrorMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first error message for the field or object, if any.
|
||||
*/
|
||||
public String getErrorMessage() {
|
||||
initErrorMessages();
|
||||
return (this.errorMessages.length > 0 ? this.errorMessages[0] : "");
|
||||
String[] errorMessages = initErrorMessages();
|
||||
return (errorMessages.length > 0 ? errorMessages[0] : "");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,8 +294,26 @@ public class BindStatus {
|
||||
* @return the error message string
|
||||
*/
|
||||
public String getErrorMessagesAsString(String delimiter) {
|
||||
initErrorMessages();
|
||||
return StringUtils.arrayToDelimitedString(this.errorMessages, delimiter);
|
||||
return StringUtils.arrayToDelimitedString(initErrorMessages(), delimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the error messages from the ObjectError list.
|
||||
*/
|
||||
private String[] initErrorMessages() throws NoSuchMessageException {
|
||||
if (this.errorMessages == null) {
|
||||
if (this.objectErrors != null) {
|
||||
this.errorMessages = new String[this.objectErrors.size()];
|
||||
for (int i = 0; i < this.objectErrors.size(); i++) {
|
||||
ObjectError error = this.objectErrors.get(i);
|
||||
this.errorMessages[i] = this.requestContext.getMessage(error, this.htmlEscape);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.errorMessages = new String[0];
|
||||
}
|
||||
}
|
||||
return this.errorMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -341,7 +354,7 @@ public class BindStatus {
|
||||
StringBuilder sb = new StringBuilder("BindStatus: ");
|
||||
sb.append("expression=[").append(this.expression).append("]; ");
|
||||
sb.append("value=[").append(this.value).append("]");
|
||||
if (isError()) {
|
||||
if (!ObjectUtils.isEmpty(this.errorCodes)) {
|
||||
sb.append("; errorCodes=").append(Arrays.asList(this.errorCodes));
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
@@ -92,31 +92,43 @@ public class RequestContext {
|
||||
public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = RequestContext.class.getName() + ".CONTEXT";
|
||||
|
||||
|
||||
protected static final boolean jstlPresent = ClassUtils.isPresent("javax.servlet.jsp.jstl.core.Config",
|
||||
RequestContext.class.getClassLoader());
|
||||
protected static final boolean jstlPresent = ClassUtils.isPresent(
|
||||
"javax.servlet.jsp.jstl.core.Config", RequestContext.class.getClassLoader());
|
||||
|
||||
@Nullable
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Nullable
|
||||
private HttpServletResponse response;
|
||||
|
||||
@Nullable
|
||||
private Map<String, Object> model;
|
||||
|
||||
@Nullable
|
||||
private WebApplicationContext webApplicationContext;
|
||||
|
||||
@Nullable
|
||||
private Locale locale;
|
||||
|
||||
@Nullable
|
||||
private TimeZone timeZone;
|
||||
|
||||
@Nullable
|
||||
private Theme theme;
|
||||
|
||||
@Nullable
|
||||
private Boolean defaultHtmlEscape;
|
||||
|
||||
@Nullable
|
||||
private Boolean responseEncodedHtmlEscape;
|
||||
|
||||
@Nullable
|
||||
private UrlPathHelper urlPathHelper;
|
||||
|
||||
@Nullable
|
||||
private RequestDataValueProcessor requestDataValueProcessor;
|
||||
|
||||
@Nullable
|
||||
private Map<String, Errors> errorsMap;
|
||||
|
||||
|
||||
@@ -214,15 +226,15 @@ public class RequestContext {
|
||||
* @param request current HTTP request
|
||||
* @param servletContext the servlet context of the web application (can be {@code null}; necessary for
|
||||
* fallback to root WebApplicationContext)
|
||||
* @param model the model attributes for the current view (can be {@code null}, using the request attributes
|
||||
* for Errors retrieval)
|
||||
* @param model the model attributes for the current view (can be {@code null}, using the request
|
||||
* attributes for Errors retrieval)
|
||||
* @see #getFallbackLocale
|
||||
* @see #getFallbackTheme
|
||||
* @see org.springframework.web.servlet.DispatcherServlet#LOCALE_RESOLVER_ATTRIBUTE
|
||||
* @see org.springframework.web.servlet.DispatcherServlet#THEME_RESOLVER_ATTRIBUTE
|
||||
*/
|
||||
protected void initContext(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable ServletContext servletContext,
|
||||
@Nullable Map<String, Object> model) {
|
||||
protected void initContext(HttpServletRequest request, @Nullable HttpServletResponse response,
|
||||
@Nullable ServletContext servletContext, @Nullable Map<String, Object> model) {
|
||||
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
@@ -267,7 +279,8 @@ public class RequestContext {
|
||||
|
||||
// Determine response-encoded HTML escape setting from the "responseEncodedHtmlEscape"
|
||||
// context-param in web.xml, if any.
|
||||
this.responseEncodedHtmlEscape = WebUtils.getResponseEncodedHtmlEscape(this.webApplicationContext.getServletContext());
|
||||
this.responseEncodedHtmlEscape =
|
||||
WebUtils.getResponseEncodedHtmlEscape(this.webApplicationContext.getServletContext());
|
||||
|
||||
this.urlPathHelper = new UrlPathHelper();
|
||||
|
||||
@@ -776,8 +789,8 @@ public class RequestContext {
|
||||
* @return the message
|
||||
*/
|
||||
public String getThemeMessage(String code, @Nullable List<?> args, String defaultMessage) {
|
||||
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null), defaultMessage,
|
||||
this.locale);
|
||||
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null),
|
||||
defaultMessage, this.locale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
*/
|
||||
public class ServletUriComponentsBuilder extends UriComponentsBuilder {
|
||||
|
||||
@Nullable
|
||||
private String originalPath;
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
@@ -81,16 +82,20 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
||||
|
||||
|
||||
/** Set of supported HTTP methods */
|
||||
@Nullable
|
||||
private Set<String> supportedMethods;
|
||||
|
||||
@Nullable
|
||||
private String allowHeader;
|
||||
|
||||
private boolean requireSession = false;
|
||||
|
||||
@Nullable
|
||||
private CacheControl cacheControl;
|
||||
|
||||
private int cacheSeconds = -1;
|
||||
|
||||
@Nullable
|
||||
private String[] varyByRequestHeaders;
|
||||
|
||||
|
||||
@@ -159,8 +164,9 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
||||
/**
|
||||
* Return the HTTP methods that this content generator supports.
|
||||
*/
|
||||
@Nullable
|
||||
public final String[] getSupportedMethods() {
|
||||
return StringUtils.toStringArray(this.supportedMethods);
|
||||
return (this.supportedMethods != null ? StringUtils.toStringArray(this.supportedMethods) : null);
|
||||
}
|
||||
|
||||
private void initAllowHeader() {
|
||||
@@ -193,6 +199,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
||||
* requests are handled before making a call to
|
||||
* {@link #checkRequest(HttpServletRequest)}.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getAllowHeader() {
|
||||
return this.allowHeader;
|
||||
}
|
||||
@@ -225,6 +232,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
||||
* that builds the Cache-Control HTTP response header.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nullable
|
||||
public final CacheControl getCacheControl() {
|
||||
return this.cacheControl;
|
||||
}
|
||||
@@ -269,6 +277,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
||||
* Return the configured request header names for the "Vary" response header.
|
||||
* @since 4.3
|
||||
*/
|
||||
@Nullable
|
||||
public final String[] getVaryByRequestHeaders() {
|
||||
return this.varyByRequestHeaders;
|
||||
}
|
||||
@@ -391,7 +400,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
||||
applyCacheSeconds(response, this.cacheSeconds);
|
||||
}
|
||||
if (this.varyByRequestHeaders != null) {
|
||||
for (String value : getVaryRequestHeadersToAdd(response)) {
|
||||
for (String value : getVaryRequestHeadersToAdd(response, this.varyByRequestHeaders)) {
|
||||
response.addHeader("Vary", value);
|
||||
}
|
||||
}
|
||||
@@ -587,18 +596,18 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
||||
}
|
||||
|
||||
|
||||
private Collection<String> getVaryRequestHeadersToAdd(HttpServletResponse response) {
|
||||
private Collection<String> getVaryRequestHeadersToAdd(HttpServletResponse response, String[] varyByRequestHeaders) {
|
||||
if (!response.containsHeader(HttpHeaders.VARY)) {
|
||||
return Arrays.asList(getVaryByRequestHeaders());
|
||||
return Arrays.asList(varyByRequestHeaders);
|
||||
}
|
||||
Collection<String> result = new ArrayList<>(getVaryByRequestHeaders().length);
|
||||
Collections.addAll(result, getVaryByRequestHeaders());
|
||||
Collection<String> result = new ArrayList<>(varyByRequestHeaders.length);
|
||||
Collections.addAll(result, varyByRequestHeaders);
|
||||
for (String header : response.getHeaders(HttpHeaders.VARY)) {
|
||||
for (String existing : StringUtils.tokenizeToStringArray(header, ",")) {
|
||||
if ("*".equals(existing)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
for (String value : getVaryByRequestHeaders()) {
|
||||
for (String value : varyByRequestHeaders) {
|
||||
if (value.equalsIgnoreCase(existing)) {
|
||||
result.remove(value);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.web.servlet.tags;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.BodyTagSupport;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* JSP tag for collecting arguments and passing them to an {@link ArgumentAware}
|
||||
* ancestor in the tag hierarchy.
|
||||
@@ -33,6 +35,7 @@ import javax.servlet.jsp.tagext.BodyTagSupport;
|
||||
@SuppressWarnings("serial")
|
||||
public class ArgumentTag extends BodyTagSupport {
|
||||
|
||||
@Nullable
|
||||
private Object value;
|
||||
|
||||
private boolean valueSet;
|
||||
|
||||
@@ -20,6 +20,7 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
/**
|
||||
@@ -38,8 +39,9 @@ public class BindErrorsTag extends HtmlEscapingAwareTag {
|
||||
public static final String ERRORS_VARIABLE_NAME = "errors";
|
||||
|
||||
|
||||
private String name;
|
||||
private String name = "";
|
||||
|
||||
@Nullable
|
||||
private Errors errors;
|
||||
|
||||
|
||||
@@ -80,6 +82,7 @@ public class BindErrorsTag extends HtmlEscapingAwareTag {
|
||||
* Retrieve the Errors instance that this tag is currently bound to.
|
||||
* <p>Intended for cooperating nesting tags.
|
||||
*/
|
||||
@Nullable
|
||||
public final Errors getErrors() {
|
||||
return this.errors;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -17,11 +17,11 @@
|
||||
package org.springframework.web.servlet.tags;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
|
||||
import javax.servlet.jsp.JspTagException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.servlet.support.BindStatus;
|
||||
|
||||
@@ -55,14 +55,17 @@ public class BindTag extends HtmlEscapingAwareTag implements EditorAwareTag {
|
||||
public static final String STATUS_VARIABLE_NAME = "status";
|
||||
|
||||
|
||||
private String path;
|
||||
private String path = "";
|
||||
|
||||
private boolean ignoreNestedPath = false;
|
||||
|
||||
@Nullable
|
||||
private BindStatus status;
|
||||
|
||||
@Nullable
|
||||
private Object previousPageStatus;
|
||||
|
||||
@Nullable
|
||||
private Object previousRequestStatus;
|
||||
|
||||
|
||||
@@ -150,6 +153,14 @@ public class BindTag extends HtmlEscapingAwareTag implements EditorAwareTag {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current BindStatus.
|
||||
*/
|
||||
private BindStatus getStatus() {
|
||||
Assert.state(this.status != null, "No current BindStatus");
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the property that this tag is currently bound to,
|
||||
* or {@code null} if bound to an object rather than a specific property.
|
||||
@@ -159,7 +170,7 @@ public class BindTag extends HtmlEscapingAwareTag implements EditorAwareTag {
|
||||
*/
|
||||
@Nullable
|
||||
public final String getProperty() {
|
||||
return this.status.getExpression();
|
||||
return getStatus().getExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,12 +180,12 @@ public class BindTag extends HtmlEscapingAwareTag implements EditorAwareTag {
|
||||
*/
|
||||
@Nullable
|
||||
public final Errors getErrors() {
|
||||
return this.status.getErrors();
|
||||
return getStatus().getErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PropertyEditor getEditor() {
|
||||
return this.status.getEditor();
|
||||
return getStatus().getEditor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -59,8 +59,10 @@ public class EvalTag extends HtmlEscapingAwareTag {
|
||||
|
||||
private final ExpressionParser expressionParser = new SpelExpressionParser();
|
||||
|
||||
@Nullable
|
||||
private Expression expression;
|
||||
|
||||
@Nullable
|
||||
private String var;
|
||||
|
||||
private int scope = PageContext.PAGE_SCOPE;
|
||||
@@ -114,12 +116,13 @@ public class EvalTag extends HtmlEscapingAwareTag {
|
||||
this.pageContext.setAttribute(EVALUATION_CONTEXT_PAGE_ATTRIBUTE, evaluationContext);
|
||||
}
|
||||
if (this.var != null) {
|
||||
Object result = this.expression.getValue(evaluationContext);
|
||||
Object result = (this.expression != null ? this.expression.getValue(evaluationContext) : null);
|
||||
this.pageContext.setAttribute(this.var, result, this.scope);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
String result = this.expression.getValue(evaluationContext, String.class);
|
||||
String result = (this.expression != null ?
|
||||
this.expression.getValue(evaluationContext, String.class) : null);
|
||||
result = ObjectUtils.getDisplayString(result);
|
||||
result = htmlEscape(result);
|
||||
result = (this.javaScriptEscape ? JavaScriptUtils.javaScriptEscape(result) : result);
|
||||
@@ -156,6 +159,7 @@ public class EvalTag extends HtmlEscapingAwareTag {
|
||||
|
||||
private final PageContext pageContext;
|
||||
|
||||
@Nullable
|
||||
private final javax.servlet.jsp.el.VariableResolver variableResolver;
|
||||
|
||||
public JspPropertyAccessor(PageContext pageContext) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,7 @@ import org.springframework.web.util.HtmlUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class HtmlEscapingAwareTag extends RequestContextAwareTag {
|
||||
|
||||
@Nullable
|
||||
private Boolean htmlEscape;
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.servlet.jsp.JspException;
|
||||
@@ -65,18 +66,23 @@ public class MessageTag extends HtmlEscapingAwareTag implements ArgumentAware {
|
||||
public static final String DEFAULT_ARGUMENT_SEPARATOR = ",";
|
||||
|
||||
|
||||
@Nullable
|
||||
private MessageSourceResolvable message;
|
||||
|
||||
@Nullable
|
||||
private String code;
|
||||
|
||||
@Nullable
|
||||
private Object arguments;
|
||||
|
||||
private String argumentSeparator = DEFAULT_ARGUMENT_SEPARATOR;
|
||||
|
||||
private List<Object> nestedArguments;
|
||||
private List<Object> nestedArguments = Collections.emptyList();
|
||||
|
||||
@Nullable
|
||||
private String text;
|
||||
|
||||
@Nullable
|
||||
private String var;
|
||||
|
||||
private String scope = TagUtils.SCOPE_PAGE;
|
||||
|
||||
@@ -49,9 +49,11 @@ public class NestedPathTag extends TagSupport implements TryCatchFinally {
|
||||
public static final String NESTED_PATH_VARIABLE_NAME = "nestedPath";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String path;
|
||||
|
||||
/** Caching a previous nested path, so that it may be reset */
|
||||
@Nullable
|
||||
private String previousNestedPath;
|
||||
|
||||
|
||||
@@ -74,6 +76,7 @@ public class NestedPathTag extends TagSupport implements TryCatchFinally {
|
||||
/**
|
||||
* Return the path that this tag applies to.
|
||||
*/
|
||||
@Nullable
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,10 @@ import org.springframework.lang.Nullable;
|
||||
*/
|
||||
public class Param {
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
|
||||
@@ -46,6 +48,7 @@ public class Param {
|
||||
/**
|
||||
* Return the raw parameter name.
|
||||
*/
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
@@ -53,7 +56,7 @@ public class Param {
|
||||
/**
|
||||
* Set the raw value of the parameter
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
public void setValue(@Nullable String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.web.servlet.tags;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.BodyTagSupport;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* JSP tag for collecting name-value parameters and passing them to a
|
||||
* {@link ParamAware} ancestor in the tag hierarchy.
|
||||
@@ -34,8 +36,9 @@ import javax.servlet.jsp.tagext.BodyTagSupport;
|
||||
@SuppressWarnings("serial")
|
||||
public class ParamTag extends BodyTagSupport {
|
||||
|
||||
private String name;
|
||||
private String name = "";
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
private boolean valueSet;
|
||||
@@ -83,7 +86,7 @@ public class ParamTag extends BodyTagSupport {
|
||||
@Override
|
||||
public void release() {
|
||||
super.release();
|
||||
this.name = null;
|
||||
this.name = "";
|
||||
this.value = null;
|
||||
this.valueSet = false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -24,6 +24,8 @@ import javax.servlet.jsp.tagext.TryCatchFinally;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.support.JspAwareRequestContext;
|
||||
import org.springframework.web.servlet.support.RequestContext;
|
||||
|
||||
@@ -60,6 +62,7 @@ public abstract class RequestContextAwareTag extends TagSupport implements TryCa
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
|
||||
@Nullable
|
||||
private RequestContext requestContext;
|
||||
|
||||
|
||||
@@ -79,11 +82,7 @@ public abstract class RequestContextAwareTag extends TagSupport implements TryCa
|
||||
}
|
||||
return doStartTagInternal();
|
||||
}
|
||||
catch (JspException ex) {
|
||||
logger.error(ex.getMessage(), ex);
|
||||
throw ex;
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
catch (JspException | RuntimeException ex) {
|
||||
logger.error(ex.getMessage(), ex);
|
||||
throw ex;
|
||||
}
|
||||
@@ -97,6 +96,7 @@ public abstract class RequestContextAwareTag extends TagSupport implements TryCa
|
||||
* Return the current RequestContext.
|
||||
*/
|
||||
protected final RequestContext getRequestContext() {
|
||||
Assert.state(this.requestContext != null, "No current RequestContext");
|
||||
return this.requestContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.TagSupport;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.util.TagUtils;
|
||||
|
||||
/**
|
||||
@@ -41,9 +42,11 @@ import org.springframework.web.util.TagUtils;
|
||||
public class TransformTag extends HtmlEscapingAwareTag {
|
||||
|
||||
/** the value to transform using the appropriate property editor */
|
||||
@Nullable
|
||||
private Object value;
|
||||
|
||||
/** the variable to put the result in */
|
||||
@Nullable
|
||||
private String var;
|
||||
|
||||
/** the scope of the variable the result will be put in */
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -28,6 +29,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
import org.springframework.web.util.JavaScriptUtils;
|
||||
@@ -82,16 +85,20 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
|
||||
private static final String URL_TYPE_ABSOLUTE = "://";
|
||||
|
||||
|
||||
private List<Param> params;
|
||||
private List<Param> params = Collections.emptyList();
|
||||
|
||||
private Set<String> templateParams;
|
||||
private Set<String> templateParams = Collections.emptySet();
|
||||
|
||||
@Nullable
|
||||
private UrlType type;
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
@Nullable
|
||||
private String context;
|
||||
|
||||
@Nullable
|
||||
private String var;
|
||||
|
||||
private int scope = PageContext.PAGE_SCOPE;
|
||||
@@ -198,9 +205,11 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
|
||||
* @return the URL value as a String
|
||||
* @throws JspException
|
||||
*/
|
||||
private String createUrl() throws JspException {
|
||||
String createUrl() throws JspException {
|
||||
Assert.state(this.value != null, "No value set");
|
||||
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
|
||||
HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
|
||||
|
||||
StringBuilder url = new StringBuilder();
|
||||
if (this.type == UrlType.CONTEXT_RELATIVE) {
|
||||
// add application context to url
|
||||
@@ -231,7 +240,7 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
|
||||
|
||||
// HTML and/or JavaScript escape, if demanded.
|
||||
urlStr = htmlEscape(urlStr);
|
||||
urlStr = this.javaScriptEscape ? JavaScriptUtils.javaScriptEscape(urlStr) : urlStr;
|
||||
urlStr = (this.javaScriptEscape ? JavaScriptUtils.javaScriptEscape(urlStr) : urlStr);
|
||||
|
||||
return urlStr;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.lang.Nullable;
|
||||
*/
|
||||
public abstract class AbstractUrlBasedView extends AbstractView implements InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private String url;
|
||||
|
||||
|
||||
|
||||
@@ -69,10 +69,10 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement
|
||||
private static final int OUTPUT_BYTE_ARRAY_INITIAL_SIZE = 4096;
|
||||
|
||||
|
||||
private String beanName;
|
||||
|
||||
@Nullable
|
||||
private String contentType = DEFAULT_CONTENT_TYPE;
|
||||
|
||||
@Nullable
|
||||
private String requestContextAttribute;
|
||||
|
||||
private final Map<String, Object> staticAttributes = new LinkedHashMap<>();
|
||||
@@ -81,26 +81,12 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement
|
||||
|
||||
private boolean exposeContextBeansAsAttributes = false;
|
||||
|
||||
private Set<String> exposedContextBeanNames;
|
||||
|
||||
|
||||
/**
|
||||
* Set the view's name. Helpful for traceability.
|
||||
* <p>Framework code must call this when constructing views.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the view's name. Should never be {@code null},
|
||||
* if the view was correctly configured.
|
||||
*/
|
||||
@Nullable
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
private Set<String> exposedContextBeanNames;
|
||||
@Nullable
|
||||
private String beanName;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the content type for this view.
|
||||
@@ -287,6 +273,24 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement
|
||||
this.exposedContextBeanNames = new HashSet<>(Arrays.asList(exposedContextBeanNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the view's name. Helpful for traceability.
|
||||
* <p>Framework code must call this when constructing views.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the view's name. Should never be {@code null},
|
||||
* if the view was correctly configured.
|
||||
*/
|
||||
@Nullable
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepares the view given the specified model, merging it with static
|
||||
|
||||
@@ -88,27 +88,21 @@ import org.springframework.web.servlet.ViewResolver;
|
||||
public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
implements ViewResolver, Ordered, InitializingBean {
|
||||
|
||||
private int order = Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
@Nullable
|
||||
private ContentNegotiationManager contentNegotiationManager;
|
||||
|
||||
private final ContentNegotiationManagerFactoryBean cnmFactoryBean = new ContentNegotiationManagerFactoryBean();
|
||||
|
||||
private boolean useNotAcceptableStatusCode = false;
|
||||
|
||||
@Nullable
|
||||
private List<View> defaultViews;
|
||||
|
||||
@Nullable
|
||||
private List<ViewResolver> viewResolvers;
|
||||
|
||||
private int order = Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ContentNegotiationManager} to use to determine requested media types.
|
||||
@@ -124,6 +118,7 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
* Return the {@link ContentNegotiationManager} to use to determine requested media types.
|
||||
* @since 4.1.9
|
||||
*/
|
||||
@Nullable
|
||||
public ContentNegotiationManager getContentNegotiationManager() {
|
||||
return this.contentNegotiationManager;
|
||||
}
|
||||
@@ -157,7 +152,8 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
}
|
||||
|
||||
public List<View> getDefaultViews() {
|
||||
return Collections.unmodifiableList(this.defaultViews);
|
||||
return (this.defaultViews != null ? Collections.unmodifiableList(this.defaultViews) :
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,7 +165,17 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
}
|
||||
|
||||
public List<ViewResolver> getViewResolvers() {
|
||||
return Collections.unmodifiableList(this.viewResolvers);
|
||||
return (this.viewResolvers != null ? Collections.unmodifiableList(this.viewResolvers) :
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
@@ -243,6 +249,7 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
*/
|
||||
@Nullable
|
||||
protected List<MediaType> getMediaTypes(HttpServletRequest request) {
|
||||
Assert.state(this.contentNegotiationManager != null, "No ContentNegotiationManager set");
|
||||
try {
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request);
|
||||
|
||||
@@ -297,18 +304,21 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
throws Exception {
|
||||
|
||||
List<View> candidateViews = new ArrayList<>();
|
||||
for (ViewResolver viewResolver : this.viewResolvers) {
|
||||
View view = viewResolver.resolveViewName(viewName, locale);
|
||||
if (view != null) {
|
||||
candidateViews.add(view);
|
||||
}
|
||||
for (MediaType requestedMediaType : requestedMediaTypes) {
|
||||
List<String> extensions = this.contentNegotiationManager.resolveFileExtensions(requestedMediaType);
|
||||
for (String extension : extensions) {
|
||||
String viewNameWithExtension = viewName + '.' + extension;
|
||||
view = viewResolver.resolveViewName(viewNameWithExtension, locale);
|
||||
if (view != null) {
|
||||
candidateViews.add(view);
|
||||
if (this.viewResolvers != null) {
|
||||
Assert.state(this.contentNegotiationManager != null, "No ContentNegotiationManager set");
|
||||
for (ViewResolver viewResolver : this.viewResolvers) {
|
||||
View view = viewResolver.resolveViewName(viewName, locale);
|
||||
if (view != null) {
|
||||
candidateViews.add(view);
|
||||
}
|
||||
for (MediaType requestedMediaType : requestedMediaTypes) {
|
||||
List<String> extensions = this.contentNegotiationManager.resolveFileExtensions(requestedMediaType);
|
||||
for (String extension : extensions) {
|
||||
String viewNameWithExtension = viewName + '.' + extension;
|
||||
view = viewResolver.resolveViewName(viewNameWithExtension, locale);
|
||||
if (view != null) {
|
||||
candidateViews.add(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.servlet.view;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,7 @@ public class InternalResourceViewResolver extends UrlBasedViewResolver {
|
||||
private static final boolean jstlPresent = ClassUtils.isPresent(
|
||||
"javax.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader());
|
||||
|
||||
@Nullable
|
||||
private Boolean alwaysInclude;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,6 +20,7 @@ import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.support.JstlUtils;
|
||||
import org.springframework.web.servlet.support.RequestContext;
|
||||
|
||||
@@ -76,6 +77,7 @@ import org.springframework.web.servlet.support.RequestContext;
|
||||
*/
|
||||
public class JstlView extends InternalResourceView {
|
||||
|
||||
@Nullable
|
||||
private MessageSource messageSource;
|
||||
|
||||
|
||||
|
||||
@@ -94,14 +94,17 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
|
||||
|
||||
private boolean exposeModelAttributes = true;
|
||||
|
||||
@Nullable
|
||||
private String encodingScheme;
|
||||
|
||||
@Nullable
|
||||
private HttpStatus statusCode;
|
||||
|
||||
private boolean expandUriTemplateVariables = true;
|
||||
|
||||
private boolean propagateQueryParams = false;
|
||||
|
||||
@Nullable
|
||||
private String[] hosts;
|
||||
|
||||
|
||||
@@ -270,6 +273,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
|
||||
* Return the configured application hosts.
|
||||
* @since 4.3
|
||||
*/
|
||||
@Nullable
|
||||
public String[] getHosts() {
|
||||
return this.hosts;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.servlet.View;
|
||||
|
||||
@@ -72,17 +73,17 @@ public class ResourceBundleViewResolver extends AbstractCachingViewResolver
|
||||
|
||||
private ClassLoader bundleClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
@Nullable
|
||||
private String defaultParentView;
|
||||
|
||||
@Nullable
|
||||
private Locale[] localesToInitialize;
|
||||
|
||||
/* Locale -> BeanFactory */
|
||||
private final Map<Locale, BeanFactory> localeCache =
|
||||
new HashMap<>();
|
||||
private final Map<Locale, BeanFactory> localeCache = new HashMap<>();
|
||||
|
||||
/* List of ResourceBundle -> BeanFactory */
|
||||
private final Map<List<ResourceBundle>, ConfigurableApplicationContext> bundleCache =
|
||||
new HashMap<>();
|
||||
private final Map<List<ResourceBundle>, ConfigurableApplicationContext> bundleCache = new HashMap<>();
|
||||
|
||||
|
||||
public void setOrder(int order) {
|
||||
|
||||
@@ -102,31 +102,39 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
|
||||
public static final String FORWARD_URL_PREFIX = "forward:";
|
||||
|
||||
|
||||
@Nullable
|
||||
private Class<?> viewClass;
|
||||
|
||||
private String prefix = "";
|
||||
|
||||
private String suffix = "";
|
||||
|
||||
@Nullable
|
||||
private String contentType;
|
||||
|
||||
private boolean redirectContextRelative = true;
|
||||
|
||||
private boolean redirectHttp10Compatible = true;
|
||||
|
||||
@Nullable
|
||||
private String[] redirectHosts;
|
||||
|
||||
@Nullable
|
||||
private String requestContextAttribute;
|
||||
|
||||
/** Map of static attributes, keyed by attribute name (String) */
|
||||
private final Map<String, Object> staticAttributes = new HashMap<>();
|
||||
|
||||
@Nullable
|
||||
private Boolean exposePathVariables;
|
||||
|
||||
@Nullable
|
||||
private Boolean exposeContextBeansAsAttributes;
|
||||
|
||||
@Nullable
|
||||
private String[] exposedContextBeanNames;
|
||||
|
||||
@Nullable
|
||||
private String[] viewNames;
|
||||
|
||||
private int order = Integer.MAX_VALUE;
|
||||
@@ -276,6 +284,7 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
|
||||
* Return the configured application hosts for redirect purposes.
|
||||
* @since 4.3
|
||||
*/
|
||||
@Nullable
|
||||
public String[] getRedirectHosts() {
|
||||
return this.redirectHosts;
|
||||
}
|
||||
@@ -467,7 +476,10 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
|
||||
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
|
||||
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
|
||||
RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
|
||||
view.setHosts(getRedirectHosts());
|
||||
String[] hosts = getRedirectHosts();
|
||||
if (hosts != null) {
|
||||
view.setHosts(hosts);
|
||||
}
|
||||
return applyLifecycleMethods(viewName, view);
|
||||
}
|
||||
// Check for special "forward:" prefix.
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.servlet.View;
|
||||
|
||||
@@ -63,8 +64,10 @@ public class XmlViewResolver extends AbstractCachingViewResolver
|
||||
|
||||
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
|
||||
|
||||
@Nullable
|
||||
private Resource location;
|
||||
|
||||
@Nullable
|
||||
private ConfigurableApplicationContext cachedFactory;
|
||||
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public interface FreeMarkerConfig {
|
||||
Configuration getConfiguration();
|
||||
|
||||
/**
|
||||
* Returns the {@link TaglibFactory} used to enable JSP tags to be
|
||||
* Return the {@link TaglibFactory} used to enable JSP tags to be
|
||||
* accessed from FreeMarker templates.
|
||||
*/
|
||||
TaglibFactory getTaglibFactory();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -28,7 +28,9 @@ import freemarker.template.TemplateException;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.ui.freemarker.FreeMarkerConfigurationFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
/**
|
||||
@@ -78,8 +80,10 @@ import org.springframework.web.context.ServletContextAware;
|
||||
public class FreeMarkerConfigurer extends FreeMarkerConfigurationFactory
|
||||
implements FreeMarkerConfig, InitializingBean, ResourceLoaderAware, ServletContextAware {
|
||||
|
||||
@Nullable
|
||||
private Configuration configuration;
|
||||
|
||||
@Nullable
|
||||
private TaglibFactory taglibFactory;
|
||||
|
||||
|
||||
@@ -133,6 +137,7 @@ public class FreeMarkerConfigurer extends FreeMarkerConfigurationFactory
|
||||
*/
|
||||
@Override
|
||||
public Configuration getConfiguration() {
|
||||
Assert.state(this.configuration != null, "No Configuration available");
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
@@ -141,6 +146,7 @@ public class FreeMarkerConfigurer extends FreeMarkerConfigurationFactory
|
||||
*/
|
||||
@Override
|
||||
public TaglibFactory getTaglibFactory() {
|
||||
Assert.state(this.taglibFactory != null, "No TaglibFactory available");
|
||||
return this.taglibFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,12 +87,16 @@ import org.springframework.web.servlet.view.AbstractTemplateView;
|
||||
*/
|
||||
public class FreeMarkerView extends AbstractTemplateView {
|
||||
|
||||
@Nullable
|
||||
private String encoding;
|
||||
|
||||
@Nullable
|
||||
private Configuration configuration;
|
||||
|
||||
@Nullable
|
||||
private TaglibFactory taglibFactory;
|
||||
|
||||
@Nullable
|
||||
private ServletContextHashModel servletContextHashModel;
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -87,8 +88,10 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration
|
||||
|
||||
private String resourceLoaderPath = "classpath:";
|
||||
|
||||
@Nullable
|
||||
private MarkupTemplateEngine templateEngine;
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
@@ -119,7 +122,8 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration
|
||||
}
|
||||
|
||||
public MarkupTemplateEngine getTemplateEngine() {
|
||||
return templateEngine;
|
||||
Assert.state(this.templateEngine != null, "No MarkupTemplateEngine set");
|
||||
return this.templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,6 +132,7 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration
|
||||
}
|
||||
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
Assert.state(this.applicationContext != null, "No ApplicationContext set");
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
@@ -209,6 +214,7 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration
|
||||
*/
|
||||
private class LocaleTemplateResolver implements TemplateResolver {
|
||||
|
||||
@Nullable
|
||||
private ClassLoader classLoader;
|
||||
|
||||
@Override
|
||||
@@ -218,6 +224,7 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration
|
||||
|
||||
@Override
|
||||
public URL resolveTemplate(String templatePath) throws IOException {
|
||||
Assert.state(this.classLoader != null, "No template ClassLoader available");
|
||||
return GroovyMarkupConfigurer.this.resolveTemplate(this.classLoader, templatePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.view.AbstractTemplateView;
|
||||
import org.springframework.web.util.NestedServletException;
|
||||
@@ -50,6 +51,7 @@ import org.springframework.web.util.NestedServletException;
|
||||
*/
|
||||
public class GroovyMarkupView extends AbstractTemplateView {
|
||||
|
||||
@Nullable
|
||||
private MarkupTemplateEngine engine;
|
||||
|
||||
|
||||
@@ -99,6 +101,7 @@ public class GroovyMarkupView extends AbstractTemplateView {
|
||||
|
||||
@Override
|
||||
public boolean checkResource(Locale locale) throws Exception {
|
||||
Assert.state(this.engine != null, "No MarkupTemplateEngine set");
|
||||
try {
|
||||
this.engine.resolveTemplate(getUrl());
|
||||
}
|
||||
@@ -124,6 +127,7 @@ public class GroovyMarkupView extends AbstractTemplateView {
|
||||
* for the given view URL.
|
||||
*/
|
||||
protected Template getTemplate(String viewUrl) throws Exception {
|
||||
Assert.state(this.engine != null, "No MarkupTemplateEngine set");
|
||||
try {
|
||||
return this.engine.createTemplateByPath(viewUrl);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.ser.FilterProvider;
|
||||
|
||||
import org.springframework.http.converter.json.MappingJacksonValue;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
|
||||
@@ -53,6 +54,7 @@ public abstract class AbstractJackson2View extends AbstractView {
|
||||
|
||||
private JsonEncoding encoding = JsonEncoding.UTF8;
|
||||
|
||||
@Nullable
|
||||
private Boolean prettyPrint;
|
||||
|
||||
private boolean disableCaching = true;
|
||||
@@ -61,7 +63,8 @@ public abstract class AbstractJackson2View extends AbstractView {
|
||||
|
||||
|
||||
protected AbstractJackson2View(ObjectMapper objectMapper, String contentType) {
|
||||
setObjectMapper(objectMapper);
|
||||
this.objectMapper = objectMapper;
|
||||
configurePrettyPrint();
|
||||
setContentType(contentType);
|
||||
setExposePathVariables(false);
|
||||
}
|
||||
@@ -74,7 +77,6 @@ public abstract class AbstractJackson2View extends AbstractView {
|
||||
* on the types to be serialized, in which case a custom-configured ObjectMapper is unnecessary.
|
||||
*/
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "'objectMapper' must not be null");
|
||||
this.objectMapper = objectMapper;
|
||||
configurePrettyPrint();
|
||||
}
|
||||
@@ -184,8 +186,12 @@ public abstract class AbstractJackson2View extends AbstractView {
|
||||
FilterProvider filters = (FilterProvider) model.get(FilterProvider.class.getName());
|
||||
if (serializationView != null || filters != null) {
|
||||
MappingJacksonValue container = new MappingJacksonValue(value);
|
||||
container.setSerializationView(serializationView);
|
||||
container.setFilters(filters);
|
||||
if (serializationView != null) {
|
||||
container.setSerializationView(serializationView);
|
||||
}
|
||||
if (filters != null) {
|
||||
container.setFilters(filters);
|
||||
}
|
||||
value = container;
|
||||
}
|
||||
return value;
|
||||
|
||||
@@ -78,12 +78,15 @@ public class MappingJackson2JsonView extends AbstractJackson2View {
|
||||
private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
|
||||
|
||||
|
||||
@Nullable
|
||||
private String jsonPrefix;
|
||||
|
||||
@Nullable
|
||||
private Set<String> modelKeys;
|
||||
|
||||
private boolean extractValueFromSingleKeyModel = false;
|
||||
|
||||
@Nullable
|
||||
private Set<String> jsonpParameterNames = new LinkedHashSet<>(Arrays.asList("jsonp", "callback"));
|
||||
|
||||
|
||||
@@ -146,6 +149,7 @@ public class MappingJackson2JsonView extends AbstractJackson2View {
|
||||
/**
|
||||
* Return the attributes in the model that should be rendered by this view.
|
||||
*/
|
||||
@Nullable
|
||||
public final Set<String> getModelKeys() {
|
||||
return this.modelKeys;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scripting.support.StandardScriptEvalException;
|
||||
import org.springframework.scripting.support.StandardScriptUtils;
|
||||
@@ -83,24 +82,31 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
new NamedThreadLocal<>("ScriptTemplateView engines");
|
||||
|
||||
|
||||
@Nullable
|
||||
private ScriptEngine engine;
|
||||
|
||||
@Nullable
|
||||
private String engineName;
|
||||
|
||||
@Nullable
|
||||
private Boolean sharedEngine;
|
||||
|
||||
@Nullable
|
||||
private String[] scripts;
|
||||
|
||||
@Nullable
|
||||
private String renderObject;
|
||||
|
||||
@Nullable
|
||||
private String renderFunction;
|
||||
|
||||
@Nullable
|
||||
private Charset charset;
|
||||
|
||||
@Nullable
|
||||
private String[] resourceLoaderPaths;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@Nullable
|
||||
private volatile ScriptEngineManager scriptEngineManager;
|
||||
|
||||
|
||||
@@ -164,15 +170,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
this.renderFunction = functionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ScriptTemplateConfigurer#setContentType(String)}} documentation.
|
||||
* @since 4.2.1
|
||||
*/
|
||||
@Override
|
||||
public void setContentType(@Nullable String contentType) {
|
||||
super.setContentType(contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ScriptTemplateConfigurer#setCharset(Charset)} documentation.
|
||||
*/
|
||||
@@ -227,9 +224,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
String resourceLoaderPath = viewConfig.getResourceLoaderPath();
|
||||
setResourceLoaderPath(resourceLoaderPath == null ? DEFAULT_RESOURCE_LOADER_PATH : resourceLoaderPath);
|
||||
}
|
||||
if (this.resourceLoader == null) {
|
||||
this.resourceLoader = getApplicationContext();
|
||||
}
|
||||
if (this.sharedEngine == null && viewConfig.isSharedEngine() != null) {
|
||||
this.sharedEngine = viewConfig.isSharedEngine();
|
||||
}
|
||||
@@ -248,11 +242,12 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
loadScripts(this.engine);
|
||||
}
|
||||
else {
|
||||
setEngine(createEngineFromName());
|
||||
setEngine(createEngineFromName(this.engineName));
|
||||
}
|
||||
|
||||
if (this.renderFunction != null && this.engine != null) {
|
||||
Assert.isInstanceOf(Invocable.class, this.engine, "ScriptEngine must implement Invocable when 'renderFunction' is specified.");
|
||||
Assert.isInstanceOf(Invocable.class, this.engine,
|
||||
"ScriptEngine must implement Invocable when 'renderFunction' is specified");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,27 +258,31 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
engines = new HashMap<>(4);
|
||||
enginesHolder.set(engines);
|
||||
}
|
||||
Assert.state(this.engineName != null, "No engine name specified");
|
||||
Object engineKey = (!ObjectUtils.isEmpty(this.scripts) ?
|
||||
new EngineKey(this.engineName, this.scripts) : this.engineName);
|
||||
ScriptEngine engine = engines.get(engineKey);
|
||||
if (engine == null) {
|
||||
engine = createEngineFromName();
|
||||
engine = createEngineFromName(engineName);
|
||||
engines.put(engineKey, engine);
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
else {
|
||||
// Simply return the configured ScriptEngine...
|
||||
Assert.state(this.engine != null, "No shared engine available");
|
||||
return this.engine;
|
||||
}
|
||||
}
|
||||
|
||||
protected ScriptEngine createEngineFromName() {
|
||||
if (this.scriptEngineManager == null) {
|
||||
this.scriptEngineManager = new ScriptEngineManager(obtainApplicationContext().getClassLoader());
|
||||
protected ScriptEngine createEngineFromName(String engineName) {
|
||||
ScriptEngineManager scriptEngineManager = this.scriptEngineManager;
|
||||
if (scriptEngineManager == null) {
|
||||
scriptEngineManager = new ScriptEngineManager(obtainApplicationContext().getClassLoader());
|
||||
this.scriptEngineManager = scriptEngineManager;
|
||||
}
|
||||
|
||||
ScriptEngine engine = StandardScriptUtils.retrieveEngineByName(this.scriptEngineManager, this.engineName);
|
||||
ScriptEngine engine = StandardScriptUtils.retrieveEngineByName(scriptEngineManager, engineName);
|
||||
loadScripts(engine);
|
||||
return engine;
|
||||
}
|
||||
@@ -307,10 +306,12 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
|
||||
@Nullable
|
||||
protected Resource getResource(String location) {
|
||||
for (String path : this.resourceLoaderPaths) {
|
||||
Resource resource = this.resourceLoader.getResource(path + location);
|
||||
if (resource.exists()) {
|
||||
return resource;
|
||||
if (this.resourceLoaderPaths != null) {
|
||||
for (String path : this.resourceLoaderPaths) {
|
||||
Resource resource = obtainApplicationContext().getResource(path + location);
|
||||
if (resource.exists()) {
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -341,7 +342,9 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
super.prepareResponse(request, response);
|
||||
|
||||
setResponseContentType(request, response);
|
||||
response.setCharacterEncoding(this.charset.name());
|
||||
if (this.charset != null) {
|
||||
response.setCharacterEncoding(this.charset.name());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -375,10 +378,10 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
}
|
||||
else if (this.renderObject != null) {
|
||||
Object thiz = engine.eval(this.renderObject);
|
||||
html = ((Invocable)engine).invokeMethod(thiz, this.renderFunction, template, model, context);
|
||||
html = ((Invocable) engine).invokeMethod(thiz, this.renderFunction, template, model, context);
|
||||
}
|
||||
else {
|
||||
html = ((Invocable)engine).invokeFunction(this.renderFunction, template, model, context);
|
||||
html = ((Invocable) engine).invokeFunction(this.renderFunction, template, model, context);
|
||||
}
|
||||
|
||||
response.getWriter().write(String.valueOf(html));
|
||||
@@ -393,7 +396,9 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
if (resource == null) {
|
||||
throw new IllegalStateException("Template resource [" + path + "] not found");
|
||||
}
|
||||
InputStreamReader reader = new InputStreamReader(resource.getInputStream(), this.charset);
|
||||
InputStreamReader reader = (this.charset != null ?
|
||||
new InputStreamReader(resource.getInputStream(), this.charset) :
|
||||
new InputStreamReader(resource.getInputStream()));
|
||||
return FileCopyUtils.copyToString(reader);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -63,6 +63,8 @@ import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
@@ -130,20 +132,25 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Nullable
|
||||
private TilesInitializer tilesInitializer;
|
||||
|
||||
@Nullable
|
||||
private String[] definitions;
|
||||
|
||||
private boolean checkRefresh = false;
|
||||
|
||||
private boolean validateDefinitions = true;
|
||||
|
||||
@Nullable
|
||||
private Class<? extends DefinitionsFactory> definitionsFactoryClass;
|
||||
|
||||
@Nullable
|
||||
private Class<? extends PreparerFactory> preparerFactoryClass;
|
||||
|
||||
private boolean useMutableTilesContainer = false;
|
||||
|
||||
@Nullable
|
||||
private ServletContext servletContext;
|
||||
|
||||
|
||||
@@ -264,6 +271,7 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws TilesException {
|
||||
Assert.state(this.servletContext != null, "No ServletContext available");
|
||||
ApplicationContext preliminaryContext = new SpringWildcardServletTilesApplicationContext(this.servletContext);
|
||||
if (this.tilesInitializer == null) {
|
||||
this.tilesInitializer = new SpringTilesInitializer();
|
||||
@@ -277,7 +285,9 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws TilesException {
|
||||
this.tilesInitializer.destroy();
|
||||
if (this.tilesInitializer != null) {
|
||||
this.tilesInitializer.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.apache.tiles.request.render.Renderer;
|
||||
import org.apache.tiles.request.servlet.ServletRequest;
|
||||
import org.apache.tiles.request.servlet.ServletUtil;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
@@ -54,12 +55,14 @@ import org.springframework.web.servlet.view.AbstractUrlBasedView;
|
||||
*/
|
||||
public class TilesView extends AbstractUrlBasedView {
|
||||
|
||||
@Nullable
|
||||
private Renderer renderer;
|
||||
|
||||
private boolean exposeJstlAttributes = true;
|
||||
|
||||
private boolean alwaysInclude = false;
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
@@ -107,17 +110,21 @@ public class TilesView extends AbstractUrlBasedView {
|
||||
|
||||
@Override
|
||||
public boolean checkResource(final Locale locale) throws Exception {
|
||||
Assert.state(this.renderer != null, "No Renderer set");
|
||||
|
||||
HttpServletRequest servletRequest = null;
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
if (requestAttributes instanceof ServletRequestAttributes) {
|
||||
servletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||
}
|
||||
|
||||
Request request = new ServletRequest(this.applicationContext, servletRequest, null) {
|
||||
@Override
|
||||
public Locale getRequestLocale() {
|
||||
return locale;
|
||||
}
|
||||
};
|
||||
|
||||
return this.renderer.isRenderable(getUrl(), request);
|
||||
}
|
||||
|
||||
@@ -125,6 +132,8 @@ public class TilesView extends AbstractUrlBasedView {
|
||||
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
|
||||
HttpServletResponse response) throws Exception {
|
||||
|
||||
Assert.state(this.renderer != null, "No Renderer set");
|
||||
|
||||
exposeModelAsRequestAttributes(model, request);
|
||||
if (this.exposeJstlAttributes) {
|
||||
JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext()));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.view.tiles3;
|
||||
|
||||
import org.apache.tiles.request.render.Renderer;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
|
||||
/**
|
||||
@@ -32,8 +33,10 @@ import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
*/
|
||||
public class TilesViewResolver extends UrlBasedViewResolver {
|
||||
|
||||
@Nullable
|
||||
private Renderer renderer;
|
||||
|
||||
@Nullable
|
||||
private Boolean alwaysInclude;
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonView;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.servlet.View;
|
||||
@@ -47,6 +48,7 @@ public class MappingJackson2XmlView extends AbstractJackson2View {
|
||||
public static final String DEFAULT_CONTENT_TYPE = "application/xml";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String modelKey;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.web.servlet.view.xml;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
@@ -52,8 +51,10 @@ public class MarshallingView extends AbstractView {
|
||||
public static final String DEFAULT_CONTENT_TYPE = "application/xml";
|
||||
|
||||
|
||||
@Nullable
|
||||
private Marshaller marshaller;
|
||||
|
||||
@Nullable
|
||||
private String modelKey;
|
||||
|
||||
|
||||
@@ -106,6 +107,8 @@ public class MarshallingView extends AbstractView {
|
||||
if (toBeMarshalled == null) {
|
||||
throw new IllegalStateException("Unable to locate object to be marshalled in model: " + model);
|
||||
}
|
||||
|
||||
Assert.state(this.marshaller != null, "No Marshaller set");
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||
this.marshaller.marshal(toBeMarshalled, new StreamResult(baos));
|
||||
|
||||
@@ -159,6 +162,7 @@ public class MarshallingView extends AbstractView {
|
||||
* @see Marshaller#supports(Class)
|
||||
*/
|
||||
protected boolean isEligibleForMarshalling(String modelKey, Object value) {
|
||||
Assert.state(this.marshaller != null, "No Marshaller set");
|
||||
Class<?> classToCheck = value.getClass();
|
||||
if (value instanceof JAXBElement) {
|
||||
classToCheck = ((JAXBElement) value).getDeclaredType();
|
||||
|
||||
@@ -75,22 +75,28 @@ import org.springframework.web.util.WebUtils;
|
||||
*/
|
||||
public class XsltView extends AbstractUrlBasedView {
|
||||
|
||||
@Nullable
|
||||
private Class<? extends TransformerFactory> transformerFactoryClass;
|
||||
|
||||
@Nullable
|
||||
private String sourceKey;
|
||||
|
||||
@Nullable
|
||||
private URIResolver uriResolver;
|
||||
|
||||
private ErrorListener errorListener = new SimpleTransformErrorListener(logger);
|
||||
|
||||
private boolean indent = true;
|
||||
|
||||
@Nullable
|
||||
private Properties outputProperties;
|
||||
|
||||
private boolean cacheTemplates = true;
|
||||
|
||||
@Nullable
|
||||
private TransformerFactory transformerFactory;
|
||||
|
||||
@Nullable
|
||||
private Templates cachedTemplates;
|
||||
|
||||
|
||||
@@ -215,6 +221,7 @@ public class XsltView extends AbstractUrlBasedView {
|
||||
* @return the TransformerFactory (never {@code null})
|
||||
*/
|
||||
protected final TransformerFactory getTransformerFactory() {
|
||||
Assert.state(this.transformerFactory != null, "No TransformerFactory available");
|
||||
return this.transformerFactory;
|
||||
}
|
||||
|
||||
@@ -416,7 +423,7 @@ public class XsltView extends AbstractUrlBasedView {
|
||||
private Templates loadTemplates() throws ApplicationContextException {
|
||||
Source stylesheetSource = getStylesheetSource();
|
||||
try {
|
||||
Templates templates = this.transformerFactory.newTemplates(stylesheetSource);
|
||||
Templates templates = getTransformerFactory().newTemplates(stylesheetSource);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loading templates '" + templates + "'");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,6 +20,7 @@ import java.util.Properties;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.URIResolver;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.view.AbstractUrlBasedView;
|
||||
import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
|
||||
@@ -34,14 +35,18 @@ import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
*/
|
||||
public class XsltViewResolver extends UrlBasedViewResolver {
|
||||
|
||||
@Nullable
|
||||
private String sourceKey;
|
||||
|
||||
@Nullable
|
||||
private URIResolver uriResolver;
|
||||
|
||||
@Nullable
|
||||
private ErrorListener errorListener;
|
||||
|
||||
private boolean indent = true;
|
||||
|
||||
@Nullable
|
||||
private Properties outputProperties;
|
||||
|
||||
private boolean cacheTemplates = true;
|
||||
@@ -124,7 +129,9 @@ public class XsltViewResolver extends UrlBasedViewResolver {
|
||||
@Override
|
||||
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
|
||||
XsltView view = (XsltView) super.buildView(viewName);
|
||||
view.setSourceKey(this.sourceKey);
|
||||
if (this.sourceKey != null) {
|
||||
view.setSourceKey(this.sourceKey);
|
||||
}
|
||||
if (this.uriResolver != null) {
|
||||
view.setUriResolver(this.uriResolver);
|
||||
}
|
||||
@@ -132,7 +139,9 @@ public class XsltViewResolver extends UrlBasedViewResolver {
|
||||
view.setErrorListener(this.errorListener);
|
||||
}
|
||||
view.setIndent(this.indent);
|
||||
view.setOutputProperties(this.outputProperties);
|
||||
if (this.outputProperties != null) {
|
||||
view.setOutputProperties(this.outputProperties);
|
||||
}
|
||||
view.setCacheTemplates(this.cacheTemplates);
|
||||
return view;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user