Вот мои классы конфигурации:
В методе templateResolver () без параметра ServletContext я получаю ошибку компиляции, поэтому добавьте ее в качестве параметра и передайте в 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();
}
}
ОБНОВЛЕНО
Я удалил следующие зависимости из POM в соответствии с @Adina в комментарии ниже, но все еще получаю ошибки
<!-- 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-->
Что еще я могу сделать снова
@Adina Я добавил дополнительные файлы конфигурации
Почему у вас есть эти зависимости, связанные с <! - сервлетами и JSP ->), и планируете ли вы развернуть свое приложение как WAR или JAR?
Развертывание @SimonMartinelli на данный момент не актуально. Я просто хочу, чтобы код работал.
@EddyFreeman, хотите ли вы использовать и jsp, и тимелеаф? Ваша инициализация не удалась, потому что он не знает, какой из них инициализировать. Это старые дебаты о stackoverflow, если вы можете использовать их оба. Если вы удалите все зависимости, связанные с jsp, и оставите только тимелеаф, ваша ошибка больше не возникнет.
@Adina Я обновил свой пост. Я удалил некоторые зависимости из POM, но по-прежнему получаю сообщение об ошибке
Spring Boot автоматически настроит Thymeleaf и Spring MVC за вас. Вам почти наверняка не нужен @EnableWebMvc, и, вероятно, вам не понадобится ни один из трех бобов, связанных с Thymeleaf. В чем причина того, что нужно настраивать вещи вручную, а не позволять Spring Boot обо всем позаботиться? Кроме того, здесь имеет значение упаковка, которую вы будете использовать. WEB-INF не существует, если вы не создаете файл войны.
Вы смотрели краткое руководство. Вам не нужен ThymeleafConfig




После некоторой отладки вашего кода настоящая проблема заключается в том, что вы автоматически подключаете ThymeleafViewResolver в конфигурации, отвечающей за настройку контекста сервлета.
public class WebMvcConfig implements WebMvcConfigurer{
@Autowired
private ThymeleafViewResolver thymeleafViewResolver;
Основная проблема заключается в том, что перед инициализацией вашего ServletContext приложение попытается инициализировать ServletContextTemplateResolver (autowired установит инициализацию порядка компонентов), и, как вы заметили, это зависит от ServletContext.
Решение:
Не волнуйтесь, Thymeleaf по умолчанию будет установлен как viewResolver.
Большая часть предоставленной вами конфигурации уже «позаботилась» с помощью spring -boot-starter-thymeleaf. Если вы хотите просто изменить преобразователь каталога просмотра по умолчанию, вы можете просто добавить application.properties
spring.mvc.view.prefix=/WEB-INF/templates/
spring.mvc.view.suffix=.html
P.S: Будьте особенно осторожны, когда вы отменяете определение по умолчанию из Spring Starters, поскольку вы можете видеть, что эти типы ошибок нелегко найти.
Ваш код выглядит нормально, не могли бы вы добавить зависимости приложения Spring?