Hello!, I upgraded the springboot version from 2.1.3.RELEASE to 2.6.5, and I found that my static resources could not be accessed.
Here are some of my configs
package cn.sunline.web.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import javax.annotation.Resource;
import org.apache.catalina.Context;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.Order;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import cn.sunline.common.conf.KiteInitAutoConfiguration;
import cn.sunline.web.common.listener.CommonSessionAndRequestListener;
import cn.sunline.web.common.mvc.handler.KiteWebExceptionResolver;
import cn.sunline.web.common.security.AccessDecisionManager;
import cn.sunline.web.common.security.AuthenticationFailure;
import cn.sunline.web.common.security.AuthenticationSuccess;
import cn.sunline.web.common.security.KiteSecurityPasswordEncoder;
import cn.sunline.web.common.security.LogoutSuccessHandler;
import cn.sunline.web.common.security.SecurityFacility;
import cn.sunline.web.common.security.SecurityServiceImpl;
import cn.sunline.web.common.security.UnauthorizedEntryPoint;
import cn.sunline.web.common.security.UrlAccessDecisionVoter;
import cn.sunline.web.common.security.filter.OrganizationContextFilter;
import cn.sunline.web.common.security.filter.XssFilter;
/**
* @author fengliming
*
*/
@Configuration
@AutoConfigureAfter(KiteInitAutoConfiguration.class)
@EnableWebMvc
@ComponentScan(basePackages = { "cn.sunline" }, includeFilters = {
@Filter(type = FilterType.ANNOTATION, value = Controller.class) })
@SuppressWarnings("all")
public class KiteWebAutoConfiguration {
/**
* 静态资源图片不经过DispacherServlet
*/
@Configuration
@EnableWebMvc
public class KiteWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/home.in");
registry.addStatusController("/WEB-INF/pages/error/500.jsp", HttpStatus.INTERNAL_SERVER_ERROR);
registry.addStatusController("/WEB-INF/pages/error/404.jsp", HttpStatus.NOT_FOUND);
registry.addStatusController("/WEB-INF/pages/error/403.jsp", HttpStatus.FORBIDDEN);
WebMvcConfigurer.super.addViewControllers(registry);
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.useRegisteredExtensionsOnly(false).favorPathExtension(false).favorParameter(true).parameterName("mediaType")
.ignoreAcceptHeader(true).defaultContentType(MediaType.APPLICATION_JSON);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**","/**/*.js","/**/*.png","/**/*.jpg","/**/*.ico","/**/*.gif","/**/).css","/**/*.htm",
"/**/*.html","/static/**","/login.in","/setLanguage.in","/sessionServer/timeout.do", "/user/getLogoImgName.in");
registry.hasMappingForPattern("*.in");
}
// public void addViewControllers(ViewControllerRegistry registry) {
// registry.addRedirectViewController("/", "/static/kindeditor/license.txt");
// }
/**
* <p>
* spring mvc统一异常处理类
* </p>
* @return
*/
@Bean
@Order(0)
public HandlerExceptionResolver handlerExceptionResolver() {
return new KiteWebExceptionResolver();
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver resolver = new CookieLocaleResolver();
resolver.setCookieMaxAge(604800);
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return resolver;
}
/**
* 文件上传,默认最大允许10M
*
* @param maxUploadSize
* @return
*/
@Bean
CommonsMultipartResolver commonsMultipartResolver(
@Value("#{env['maxUploadSize']?:10485760}") long maxUploadSize) {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(maxUploadSize);
return resolver;
}
}
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addContextCustomizers((context)->context.addWelcomeFile("home.in"));
return factory;
}
@Bean
public ServletListenerRegistrationBean commonSessionAndRequestListener(){
ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean();
servletListenerRegistrationBean.setListener(new CommonSessionAndRequestListener());
return servletListenerRegistrationBean;
}
// @Bean
// public RequestMappingHandlerMapping buildRequestMappingHandlerMapping() {
// return new RequestMappingHandlerMapping();
// }
@Bean
public AbstractHandlerMethodAdapter buildRequestMappingHandlerAdapter() {
RequestMappingHandlerAdapter handler = new RequestMappingHandlerAdapter();
handler.setOrder(10000);
handler.setWebBindingInitializer(buildConfigurableWebBindingInitializer());
handler.setMessageConverters(Arrays.asList(buildMappingJackson2HttpMessageConverter()));
return handler;
}
@Resource(name="conversionService")
private GenericConversionService conversionService;
@Bean
public ConfigurableWebBindingInitializer buildConfigurableWebBindingInitializer() {
ConfigurableWebBindingInitializer config = new ConfigurableWebBindingInitializer();
config.setConversionService(conversionService);
return config;
}
@Bean
public MappingJackson2HttpMessageConverter buildMappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.APPLICATION_JSON_UTF8);
// list.add("text/json;charset=utf-8");
// list.add("application/json;charset=utf-8");
converter.setSupportedMediaTypes(list);
return converter;
}
@Bean
public InternalResourceViewResolver buildInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
return resolver;
}
@Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean reg = new ServletRegistrationBean(dispatcherServlet);
reg.getUrlMappings().clear();
reg.addUrlMappings("*.in");
reg.addUrlMappings("/hello");
reg.setLoadOnStartup(1);
return reg;
}
@Bean
public AuthenticationSuccess authenticationSuccess() {
AuthenticationSuccess authenticationSuccess = new AuthenticationSuccess();
authenticationSuccess.setTargetUrl("/home.in");
return authenticationSuccess;
}
@Bean
public AuthenticationFailure authenticationFailure() {
AuthenticationFailure authenticationFailure = new AuthenticationFailure();
authenticationFailure.setDefaultFailureUrl("/login.in?error=true");
return authenticationFailure;
}
@Bean
public LogoutSuccessHandler logoutSuccessHandler() {
LogoutSuccessHandler logoutSuccessHandler = new LogoutSuccessHandler("/");
return logoutSuccessHandler;
}
@Bean
public OrganizationContextFilter organizationContextFilter() {
return new OrganizationContextFilter();
}
@Bean
public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<XssFilter>(new XssFilter());
registration.setName("xssFilter");
registration.addUrlPatterns("*.in");
// 执行顺序,越小越优先
registration.setOrder(0);
return registration;
}
@Bean
public SecurityServiceImpl securityServiceImpl() {
SecurityServiceImpl securityServiceImpl = new SecurityServiceImpl();
return securityServiceImpl;
}
@Bean
public SecurityFacility securityFacility() {
SecurityFacility securityFacility = new SecurityFacility();
securityFacility.setSecurityService(securityServiceImpl());
return securityFacility;
}
@Bean
public KiteSecurityPasswordEncoder kiteSecurityPasswordEncoder() {
KiteSecurityPasswordEncoder kiteSecurityPasswordEncoder = new KiteSecurityPasswordEncoder();
return kiteSecurityPasswordEncoder;
}
@Bean
public AccessDecisionManager accessDecisionManager() {
@SuppressWarnings("unchecked")
AccessDecisionManager accessDecisionManager = new AccessDecisionManager(
Arrays.asList(new RoleVoter(), new AuthenticatedVoter(), new UrlAccessDecisionVoter()));
return accessDecisionManager;
}
@Bean
public UnauthorizedEntryPoint unauthorizedEntryPoint() {
UnauthorizedEntryPoint unauthorizedEntryPoint = new UnauthorizedEntryPoint();
unauthorizedEntryPoint.setLoginUrl("/login.in");
return unauthorizedEntryPoint;
}
@Bean
public ProviderManager authenticationManager() {
ProviderManager authenticationManager = new ProviderManager(Arrays.asList(daoAuthenticationProvider()));
return authenticationManager;
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(securityFacility());
daoAuthenticationProvider.setPasswordEncoder(kiteSecurityPasswordEncoder());
return daoAuthenticationProvider;
}
}
2.1.3.RELEASE
2.6.5
I don't know why, since the request doesn't go into springmvc I can't debug Thanks!
Comment From: wilkinsona
You are using @EnableWebMvc which completely disables Boot’s auto-configuration. You are also defining a registration for the dispatcher servlet and static resource mappings yourself. Given that you’re configuring so much yourself, it’s hard to see where Spring Boot could be causing the problem.
If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.
Comment From: pruidong
You can refer to https://docs.spring.io/spring-boot/docs/2.6.5/reference/htmlsingle/#application-properties.web.spring.web.resources.static-locations to configure static resources. Use @ControllerAdvice to handle global exceptions.
Comment From: hoowhoami
Modifying the configuration "spring.mvc.pathmatch.matching-strategy=ant_path_matcher" can solve this problem.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: Toldwin
Hi, not sure it's 100% linked with your case but it's close enough to give you the information.
I had an issue upgrading 2.5.12 to 2.6.6 with static exposition of files because the key changed. I fixed it by changing the properties key :
- from : spring.resources.static-locations: value
- to : spring.web.resources.static-locations: value
Looks like spring.resources.static-locations has been deprecated. It's indeed specified with this key in the document pruidong has linked : https://docs.spring.io/spring-boot/docs/2.6.5/reference/htmlsingle/#application-properties.web.spring.web.resources.static-locations
Best regards,
Comment From: wilkinsona
@hoowhoami @Toldwin Thank you for trying to help, but the use of @EnableWebMvc means that none of Spring Boot's MVC auto-configuration properties will take effect.
It has been just over two weeks since the original request for feedback so I am going to close this now. @zzq1314zll if you have a chance to prepare and share the requested sample we can take another look.