为什么 Spring 在使用 WebApplicationInitializer 时会抛出"IllegalStateException: No ServletContext set"



我只是在学习Java,现在尝试使用MVC + thymeleaf为我的应用程序创建UI。当我尝试运行应用程序时,出现错误,堆栈跟踪如下:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceHandlerMapping' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:656)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:882)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:89)
at com.foxminded.university.Main.main(Main.java:26)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
... 14 more
Caused by: java.lang.IllegalStateException: No ServletContext set
at org.springframework.util.Assert.state(Assert.java:73)
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.resourceHandlerMapping(WebMvcConfigurationSupport.java:534)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 15 more

我的配置文件:

@Configuration
@ComponentScan("com.foxminded.university")
@PropertySource("classpath:config.properties")
@EnableWebMvc
public class ContextConfig implements WebMvcConfigurer {
private final ApplicationContext applicationContext;
@Value("${url}")
public String url;
@Value("${user}")
public String user;
@Value("${password}")
public String password;
@Value("${driverClass}")
public Class<Driver> driverClass;
@Autowired
public ContextConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public DataSource dataSource() {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(driverClass);
dataSource.setUsername(user);
dataSource.setUrl(url);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
}

dispatcherServlet:

public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {    
return new Class[] {ContextConfig.class};
}
@Override
protected String[] getServletMappings() {   
return new String[] {"/"};
}
}

和绒球.xml:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.foxminded.tasks</groupId>
<artifactId>University1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>University1</name>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<junit.jupiter.version>5.6.0</junit.jupiter.version>
<org.springframework.version>5.2.5.RELEASE</org.springframework.version>
<org.springframework.boot.version>2.2.6.RELEASE</org.springframework.boot.version>
<h2.version>1.4.200</h2.version>
<org.postgres.version>42.2.11</org.postgres.version>
<org.sonarsource.scanner.maven.version>3.2</org.sonarsource.scanner.maven.version>
<mockito.version>3.3.3</mockito.version>
<logback.version>1.3.0-alpha5</logback.version>
<slf4j.version>2.0.0-alpha1</slf4j.version>
<servlet.version>4.0.1</servlet.version>
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
</properties>
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.host.url>
http://localhost:9000
</sonar.host.url>
</properties>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>${org.springframework.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>${thymeleaf.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>${org.sonarsource.scanner.maven.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${org.postgres.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
</project>

请,你能解释一下,问题在哪里,我能做什么。我试图删除.m2存储库并重建项目,但没有任何反应。

我从创建 DAO 和服务层更改的主要方法,它在控制台中制作小菜单,用于获取学生和教师的时间表:

public class Main {
private final static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
logger.info("Start Main");
@SuppressWarnings("resource")
final ApplicationContext context = new AnnotationConfigApplicationContext(ContextConfig.class);     
DatabaseInitializer initializer = context.getBean("databaseInitializer", DatabaseInitializer.class);
try {
initializer.createTableInsertData();
} catch (IOException e1) {
logger.error("DB was not created");
System.exit(0);
}
TimeTable timeTable = context.getBean("timeTable", TimeTable.class);
TeacherService teacherService = context.getBean("teacherService", TeacherService.class);
StudentService studentService = context.getBean("studentService", StudentService.class);    
final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));     
final String commandListMessage = "Please select which TimeTable you want take:n"
+ ""1" - TimeTable for student for selected interval;n"
+ ""2" - TimeTable for teacher for selected interval;n"
+ ""help" - for get this list of commands again;n" + "or "exit" to exit.";
System.out.println(commandListMessage);
String command = "";
try {
command = reader.readLine();        
logger.debug("command is {}", command);         
logger.debug("start menu loop");
while (!(command.equalsIgnoreCase("exit"))) {
logger.info("switch command");              
switch (command) {
case "1":
logger.debug("case 1");         
System.out.println("Enter student id:");
int studentId = Integer.parseInt(reader.readLine());
Student student = studentService.findOne(studentId);
if (student != null) {
System.out.println("Enter date interval as "MM.DD-MM.DD":");
String[] dateInterval = reader.readLine().split("\D");     
logger.debug("getting TT for student {} and period {}.{}-{}.{}", student, dateInterval[0], dateInterval[1], dateInterval[2], dateInterval[3]);                      
String timeTableString = timeTable.getTTForGroup(student,
LocalDateTime.of(Year.now().getValue(), Month.of(Integer.parseInt(dateInterval[0])),
Integer.parseInt(dateInterval[1]), 0, 0, 0),
LocalDateTime.of(Year.now().getValue(), Month.of(Integer.parseInt(dateInterval[2])),
Integer.parseInt(dateInterval[3]), 23, 59, 59));
timeTable.printTimeTable(timeTableString);
} else {
System.out.println("student whith this id "" + studentId + "" is not exist.");                        
logger.warn("student with this id {} is not exist", studentId);
}
break;
case "2":
logger.debug("case 2");                 
System.out.println("Enter teacher id:");
int teacherId = Integer.parseInt(reader.readLine());
Teacher teacher = teacherService.findOne(teacherId);
if (teacher != null) {
System.out.println("Enter date interval as "MM.DD-MM.DD":");
String[] dateInterval = reader.readLine().split("\D");             
logger.debug("getting TT for teacher {} and period {}.{}-{}.{}", teacher, dateInterval[0], dateInterval[1], dateInterval[2], dateInterval[3]);                  
String timeTableString = timeTable.getTTForTeacher(teacher,
LocalDateTime.of(Year.now().getValue(), Month.of(Integer.parseInt(dateInterval[0])),
Integer.parseInt(dateInterval[1]), 0, 0, 0),
LocalDateTime.of(Year.now().getValue(), Month.of(Integer.parseInt(dateInterval[2])),
Integer.parseInt(dateInterval[3]), 23, 59, 59));
timeTable.printTimeTable(timeTableString);
} else {
System.out.println("teacher whith this id "" + teacherId + "" is not exist.");                        
logger.warn("teacher with this id {} is not exist", teacherId);
}
break;
case "help":
logger.debug("case help");
System.out.println(commandListMessage);
break;
default:
logger.debug("case default");
System.out.println("Please enter the correct command.");
break;
}
command = reader.readLine();
}
reader.close();
} catch (IOException e) {
logger.error("Reading failure", e);
}   
logger.info("Exit Main");
}
}

如前所述,问题出在雄猫身上。 我添加了Tomcat7插件和Maven-war-plugin,并以Tomcat7:run的形式运行它,所以它现在可以工作了。 并制作 servlet 4.0.0 的版本,而不是 4.0.1,因为由于某种原因它不适用于它。

我想你可能没有覆盖这个类的方法 AbstractAnnotationConfigDispatcherServletInitializer 正确。看看周围的东西。启用调试日志。你为什么不试试Spring Boot。它会自动为您管理所有依赖项的创建。

最新更新