Skip to content

Commit

Permalink
Merge pull request #13866 from codeconsole/7.0.x-controller-webmvc
Browse files Browse the repository at this point in the history
Continue ControllersAutoConfiguration Migration
  • Loading branch information
codeconsole authored Nov 22, 2024
2 parents 7c71d9f + 4634e09 commit acd6772
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
package org.grails.plugins.web.controllers;

import grails.config.Settings;
import grails.core.GrailsApplication;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.Filter;
import jakarta.servlet.MultipartConfigElement;
import org.grails.web.config.http.GrailsFilters;
import org.grails.web.filters.HiddenHttpMethodFilter;
import org.grails.web.servlet.mvc.GrailsDispatcherServlet;
import org.grails.web.servlet.mvc.GrailsWebRequestFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.util.ClassUtils;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.EnumSet;

Expand All @@ -30,6 +38,30 @@ public class ControllersAutoConfiguration {
@Value("${" + Settings.FILTER_FORCE_ENCODING + ":false}")
private boolean filtersForceEncoding;

@Value("${" + Settings.RESOURCES_CACHE_PERIOD + ":0}")
private int resourcesCachePeriod;

@Value("${" + Settings.RESOURCES_ENABLED + ":true}")
private boolean resourcesEnabled;

@Value("${" + Settings.RESOURCES_PATTERN + ":" + Settings.DEFAULT_RESOURCE_PATTERN + "}")
private String resourcesPattern;

@Value("${" + Settings.CONTROLLERS_UPLOAD_LOCATION + ":#{null}}")
private String uploadTmpDir;

@Value("${" + Settings.CONTROLLERS_UPLOAD_MAX_FILE_SIZE + ":128000}")
private long maxFileSize;

@Value("${" + Settings.CONTROLLERS_UPLOAD_MAX_REQUEST_SIZE + ":128000}")
private long maxRequestSize;

@Value("${" + Settings.CONTROLLERS_UPLOAD_FILE_SIZE_THRESHOLD + ":0}")
private int fileSizeThreshold;

@Value("${" + Settings.WEB_SERVLET_PATH + ":#{null}}")
String grailsServletPath;

@Bean
@ConditionalOnMissingBean(CharacterEncodingFilter.class)
public CharacterEncodingFilter characterEncodingFilter() {
Expand Down Expand Up @@ -67,4 +99,84 @@ public FilterRegistrationBean<Filter> grailsWebRequestFilter(ApplicationContext
registrationBean.setOrder(GrailsFilters.GRAILS_WEB_REQUEST_FILTER.getOrder());
return registrationBean;
}

@Bean
public MultipartConfigElement multipartConfigElement() {
if (uploadTmpDir == null) {
uploadTmpDir = System.getProperty("java.io.tmpdir");
}
return new MultipartConfigElement(uploadTmpDir, maxFileSize, maxRequestSize, fileSizeThreshold);
}

@Bean
public DispatcherServlet dispatcherServlet() {
return new GrailsDispatcherServlet();
}

@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistration(GrailsApplication application, DispatcherServlet dispatcherServlet, MultipartConfigElement multipartConfigElement) {
if (grailsServletPath == null) {
boolean isTomcat = ClassUtils.isPresent("org.apache.catalina.startup.Tomcat", application.getClassLoader());
grailsServletPath = isTomcat ? Settings.DEFAULT_TOMCAT_SERVLET_PATH : Settings.DEFAULT_WEB_SERVLET_PATH;
}
DispatcherServletRegistrationBean dispatcherServletRegistration = new DispatcherServletRegistrationBean(dispatcherServlet, grailsServletPath);
dispatcherServletRegistration.setLoadOnStartup(2);
dispatcherServletRegistration.setAsyncSupported(true);
dispatcherServletRegistration.setMultipartConfig(multipartConfigElement);
return dispatcherServletRegistration;
}

@Bean
public GrailsWebMvcConfigurer webMvcConfig() {
return new GrailsWebMvcConfigurer(resourcesCachePeriod, resourcesEnabled, resourcesPattern);
}

static class GrailsWebMvcConfigurer implements WebMvcConfigurer {

private static final String[] SERVLET_RESOURCE_LOCATIONS = new String[] { "/" };

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[] {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"
};

private static final String[] RESOURCE_LOCATIONS;

static {
RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length
+ SERVLET_RESOURCE_LOCATIONS.length];
System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0,
SERVLET_RESOURCE_LOCATIONS.length);
System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS,
SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);
}

boolean addMappings;
Integer cachePeriod;
String resourcesPattern;

GrailsWebMvcConfigurer(Integer cachePeriod, Boolean addMappings, String resourcesPattern) {
this.addMappings = addMappings;
this.cachePeriod = cachePeriod;
this.resourcesPattern = resourcesPattern;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!addMappings) {
return;
}

if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod);
}
if (!registry.hasMappingForPattern(resourcesPattern)) {
registry.addResourceHandler(resourcesPattern)
.addResourceLocations(RESOURCE_LOCATIONS)
.setCachePeriod(cachePeriod);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,16 @@ import grails.config.Settings
import grails.core.GrailsControllerClass
import grails.plugins.Plugin
import grails.util.GrailsUtil
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.grails.core.artefact.ControllerArtefactHandler
import org.grails.plugins.web.servlet.context.BootStrapClassRunner
import org.grails.web.errors.GrailsExceptionResolver
import org.grails.web.servlet.mvc.GrailsDispatcherServlet
import org.grails.web.servlet.mvc.TokenResponseActionResultTransformer
import org.grails.web.servlet.view.CompositeViewResolver
import org.springframework.beans.factory.support.AbstractBeanDefinition
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean
import org.springframework.context.ApplicationContext
import org.springframework.util.ClassUtils
import org.springframework.web.multipart.support.StandardServletMultipartResolver
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
import jakarta.servlet.MultipartConfigElement

/**
* Handles the configuration of controllers for Grails.
Expand All @@ -61,15 +53,6 @@ class ControllersGrailsPlugin extends Plugin {
def config = application.config

boolean useJsessionId = config.getProperty(Settings.GRAILS_VIEWS_ENABLE_JSESSIONID, Boolean, false)
String uploadTmpDir = config.getProperty(Settings.CONTROLLERS_UPLOAD_LOCATION, System.getProperty("java.io.tmpdir"))
long maxFileSize = config.getProperty(Settings.CONTROLLERS_UPLOAD_MAX_FILE_SIZE, Long, 128000L)
long maxRequestSize = config.getProperty(Settings.CONTROLLERS_UPLOAD_MAX_REQUEST_SIZE, Long, 128000L)
int fileSizeThreashold = config.getProperty(Settings.CONTROLLERS_UPLOAD_FILE_SIZE_THRESHOLD, Integer, 0)
boolean isTomcat = ClassUtils.isPresent("org.apache.catalina.startup.Tomcat", application.classLoader)
String grailsServletPath = config.getProperty(Settings.WEB_SERVLET_PATH, isTomcat ? Settings.DEFAULT_TOMCAT_SERVLET_PATH : Settings.DEFAULT_WEB_SERVLET_PATH)
int resourcesCachePeriod = config.getProperty(Settings.RESOURCES_CACHE_PERIOD, Integer, 0)
boolean resourcesEnabled = config.getProperty(Settings.RESOURCES_ENABLED, Boolean, true)
String resourcesPattern = config.getProperty(Settings.RESOURCES_PATTERN, String, Settings.DEFAULT_RESOURCE_PATTERN)

if (!Boolean.parseBoolean(System.getProperty(Settings.SETTING_SKIP_BOOTSTRAP))) {
bootStrapClassRunner(BootStrapClassRunner)
Expand All @@ -83,8 +66,6 @@ class ControllersGrailsPlugin extends Plugin {

"${CompositeViewResolver.BEAN_NAME}"(CompositeViewResolver)

multipartConfigElement(MultipartConfigElement, uploadTmpDir, maxFileSize, maxRequestSize, fileSizeThreashold)

def handlerInterceptors = springConfig.containsBean("localeChangeInterceptor") ? [ref("localeChangeInterceptor")] : []
def interceptorsClosure = {
interceptors = handlerInterceptors
Expand All @@ -93,17 +74,6 @@ class ControllersGrailsPlugin extends Plugin {
annotationHandlerMapping(RequestMappingHandlerMapping, interceptorsClosure)
annotationHandlerAdapter(RequestMappingHandlerAdapter)

// add Grails webmvc config
webMvcConfig(GrailsWebMvcConfigurer, resourcesCachePeriod, resourcesEnabled, resourcesPattern)

// add the dispatcher servlet
dispatcherServlet(GrailsDispatcherServlet)
dispatcherServletRegistration(DispatcherServletRegistrationBean, ref("dispatcherServlet"), grailsServletPath) {
loadOnStartup = 2
asyncSupported = true
multipartConfig = multipartConfigElement
}

for (controller in application.getArtefacts(ControllerArtefactHandler.TYPE)) {
log.debug "Configuring controller $controller.fullName"
if (controller.available) {
Expand All @@ -128,55 +98,6 @@ class ControllersGrailsPlugin extends Plugin {
}
} }


@CompileStatic
static class GrailsWebMvcConfigurer implements WebMvcConfigurer {

private static final String[] SERVLET_RESOURCE_LOCATIONS = [ "/" ]

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = [
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" ]

private static final String[] RESOURCE_LOCATIONS
static {
RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length
+ SERVLET_RESOURCE_LOCATIONS.length]
System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0,
SERVLET_RESOURCE_LOCATIONS.length)
System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS,
SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);
}

boolean addMappings = true
Integer cachePeriod
String resourcesPattern

GrailsWebMvcConfigurer(Integer cachePeriod, boolean addMappings = true, String resourcesPattern = '/static/**') {
this.addMappings = addMappings
this.cachePeriod = cachePeriod
this.resourcesPattern = resourcesPattern
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!addMappings) {
return
}

if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod)
}
if (!registry.hasMappingForPattern(resourcesPattern)) {
registry.addResourceHandler(resourcesPattern)
.addResourceLocations(RESOURCE_LOCATIONS)
.setCachePeriod(cachePeriod)
}
}
}

@Override
void onChange( Map<String, Object> event) {
if (!(event.source instanceof Class)) {
Expand Down Expand Up @@ -205,5 +126,4 @@ class ControllersGrailsPlugin extends Plugin {
}
}
}

}

0 comments on commit acd6772

Please sign in to comment.