这是我的配置类:
在没有ServletContext参数的templateResolver()方法中,出现编译错误,因此将其添加为参数并将其提供给ServletContextTemplateResolver(servletContext);
@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {"com.packtpub.springsecurity"})
public class ThymeleafConfig {
@Bean
public ServletContextTemplateResolver templateResolver(ServletContext servletContext) {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(servletContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCacheable(false);
resolver.setOrder(1);
return resolver;
}
@Bean
public SpringTemplateEngine templateEngine(final ServletContextTemplateResolver templateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver);
return engine;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver(final SpringTemplateEngine templateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine);
return resolver;
}
}
当我运行我的应用程序时,出现以下错误:::
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method templateResolver in com.packtpub.springsecurity.web.configuration.ThymeleafConfig required a bean of type 'javax.servlet.ServletContext' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'javax.servlet.ServletContext' in your configuration.
我在做什么错? 谢谢
其他配置文件是
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>chapter2</groupId>
<artifactId>chapter2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>chapter2</name>
<description>chapter 2 test</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring dependencies START-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!-- Servlet and JSP related dependencies -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- For datasource configuration -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<!-- We will be using MySQL as our database server -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- Spring dependencies END -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20170516</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@Configuration
//@Import({SecurityConfig.class, DataSourceConfig.class})
@ComponentScan(basePackages =
{
"com.packtpub.springsecurity.dataaccess",
"com.packtpub.springsecurity.domain",
"com.packtpub.springsecurity.service"
}
)
@PropertySource(value = {"classpath:application.properties"})
public class JavaConfig {
/**
* Note: If you want to use @PropertySource, you must create a static
* PropertySourcesPlaceholderConfigurer with the @Bean as seen here.
* @return PropertySourcesPlaceholderConfigurer
* @throws java.io.IOException
*/
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
propertySourcesPlaceholderConfigurer.setProperties(yamlPropertiesFactoryBean().getObject());
return propertySourcesPlaceholderConfigurer;
}
@Bean
public static YamlPropertiesFactoryBean yamlPropertiesFactoryBean() {
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("application.yml"));
return yaml;
}
} // The end...
@Order(1)
public class SecurityWebAppInitializer
extends AbstractSecurityWebApplicationInitializer {
/**
* Don't initialize the filter directly, the Spring WebApplicationInitializer
* parent will take care of the initialization.
*/
public SecurityWebAppInitializer() {
super();
}
} // The end...
public class WebAppInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { JavaConfig.class, SecurityConfig.class, DataSourceConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/*" };
}
@Override
public void onStartup(final ServletContext servletContext)
throws ServletException {
// Register DispatcherServlet
super.onStartup(servletContext);
// Register H2 Admin console:
ServletRegistration.Dynamic h2WebServlet = servletContext.addServlet("h2WebServlet",
"org.h2.server.web.WebServlet");
h2WebServlet.addMapping("/admin/h2/*");
h2WebServlet.setInitParameter("webAllowOthers", "true");
}
} // The End...
@Configuration
@EnableWebMvc
@Import({ThymeleafConfig.class})
@ComponentScan(basePackages = {
"com.packtpub.springsecurity.web.controllers",
"com.packtpub.springsecurity.web.model"
})
public class WebMvcConfig extends WebMvcConfigurerAdapter
{
@Autowired
private ThymeleafViewResolver thymeleafViewResolver;
/**
* We mention this in the book, but this helps to ensure that the intercept-url patterns prevent access to our
* controllers. For example, once security has been applied for administrators try commenting out the modifications
* to the super class and requesting <a
* href="http://localhost:800/calendar/events/.html">http://localhost:800/calendar/events/.html</a>. You will
* observe that security is bypassed since it did not match the pattern we provided. In later chapters, we discuss
* how to secure the service tier which helps mitigate bypassing of the URL based security too.
*/
// FIXME: FInd out what this is and why it is here.
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping result = new RequestMappingHandlerMapping();
result.setUseSuffixPatternMatch(false);
result.setUseTrailingSlashMatch(false);
return result;
}
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
.setCachePeriod(31_556_926)
;
}
@Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
configurer
.ignoreAcceptHeader(false)
.favorPathExtension(true) // .html / .json / .ms
.defaultContentType(MediaType.TEXT_HTML) // text/html
.mediaTypes(
new HashMap<String, MediaType>(){
{
put("html", MediaType.TEXT_HTML);
put("xml", MediaType.APPLICATION_XML);
put("json", MediaType.APPLICATION_JSON);
}
})
;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
}
/*@Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver() {
ContentNegotiatingViewResolver result = new ContentNegotiatingViewResolver();
Map<String, String> mediaTypes = new HashMap<>();
mediaTypes.put("json", MediaType.APPLICATION_JSON_VALUE);
// result.setMediaTypes(mediaTypes);
result.setDefaultViews(Collections.singletonList(jacksonView()));
return result;
}*/
@Bean
public MappingJackson2JsonView jacksonView() {
MappingJackson2JsonView jacksonView = new MappingJackson2JsonView();
jacksonView.setExtractValueFromSingleKeyModel(true);
Set<String> modelKeys = new HashSet<String>();
modelKeys.add("events");
modelKeys.add("event");
jacksonView.setModelKeys(modelKeys);
return jacksonView;
}
@Override
public void configureViewResolvers(final ViewResolverRegistry registry) {
registry.viewResolver(thymeleafViewResolver);
}
// i18N support
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
resource.setBasenames("/WEB-INF/locales/messages");
resource.setDefaultEncoding("UTF-8");
resource.setFallbackToSystemLocale(Boolean.TRUE);
return resource;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
}
已更新
根据@Adina在下面的评论中,我已经从POM中删除了以下依赖项,但仍然收到错误
<!-- dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency-->
我还能再做什么
答案 0 :(得分:1)
在对代码进行一些调试之后,真正的问题是您在负责配置Servlet上下文的配置中自动装配ThymeleafViewResolver。
public class WebMvcConfig implements WebMvcConfigurer{
@Autowired
private ThymeleafViewResolver thymeleafViewResolver;
主要问题是,在初始化ServletContext之前,应用程序将尝试初始化ServletContextTemplateResolver(自动装配将强制进行Bean顺序初始化),并且您已经注意到它取决于ServletContext。
解决方案:
不用担心,Thymeleaf将默认设置为viewResolver。
spring-boot-starter-thymeleaf已经“照料”了您提供的大多数配置。 如果只想更改默认的视图目录解析器,则只需添加application.properties
spring.mvc.view.prefix=/WEB-INF/templates/
spring.mvc.view.suffix=.html
P.S:在从Spring Starter覆盖默认定义时要格外小心,因为您会发现这些类型的错误不容易找到。