参考视频:SpringMVC教程,SpringMVC从零到精通,老杜SpringMVC,动力节点SpringMVC

1. web.xml文件的替代

1.1 Servlet3.0新特性

Servlet3.0新特性:web.xml文件可以不写了。

在Servlet3.0的时候,规范中提供了一个接口ServletContainerInitializer

ServletContainerInitializer接口

服务器在启动的时候会自动从容器中找 ServletContainerInitializer接口的实现类,自动调用它的onStartup方法来完成Servlet上下文的初始化。

在Spring3.1版本的时候,提供了这样一个类SpringServletContainerInitializer,实现以上的接口:

SpringServletContainerInitializer类

它的核心方法如下:

SpringServletContainerInitializer类的核心方法

可以看到在服务器启动的时候,它会去加载所有实现WebApplicationInitializer接口的类:

WebApplicationInitializer接口

这个接口下有一个子类是我们需要的:AbstractAnnotationConfigDispatcherServletInitializer

AbstractAnnotationConfigDispatcherServletInitializer类

当我们编写类继承AbstractAnnotationConfigDispatcherServletInitializer之后,web服务器在启动的时候会根据它来初始化Servlet上下文。

web服务器根据AbstractAnnotationConfigDispatcherServletInitializer初始化Servlet上下文

1.2 编写WebAppInitializer

以下这个类就是用来代替web.xml文件的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.muyoukule.config;

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* Spring的配置
*
* @return
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}

/**
* SpringMVC的配置
*
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVCConfig.class};
}

/**
* 用于配置 DispatcherServlet 的映射路径
*
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}

/**
* 配置过滤器
*
* @return
*/
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceRequestEncoding(true);
characterEncodingFilter.setForceResponseEncoding(true);
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
}
}

SpringMVC配置如下:

1
2
3
4
5
package com.muyoukule.config;

@Configuration
public class SpringMVCConfig {
}

2. Spring MVC的配置

2.1 组件扫描

1
2
3
4
5
6
// 指定该类是一个配置类,可以当配置文件使用
@Configuration
// 开启组件扫描
@ComponentScan("com.muyoukule.controller")
public class SpringMVCConfig {
}

2.2 开启注解驱动

1
2
3
4
5
6
7
8
// 指定该类是一个配置类,可以当配置文件使用
@Configuration
// 开启组件扫描
@ComponentScan("com.muyoukule.controller")
// 开启注解驱动
@EnableWebMvc
public class SpringMVCConfig {
}

2.3 视图解析器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 指定该类是一个配置类,可以当配置文件使用
@Configuration
// 开启组件扫描
@ComponentScan("com.muyoukule.controller")
// 开启注解驱动
@EnableWebMvc
public class SpringMVCConfig {
@Bean
public ThymeleafViewResolver getViewResolver(SpringTemplateEngine springTemplateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(springTemplateEngine);
resolver.setCharacterEncoding("UTF-8");
resolver.setOrder(1);
return resolver;
}

@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver iTemplateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(iTemplateResolver);
return templateEngine;
}

@Bean
public ITemplateResolver templateResolver(ApplicationContext applicationContext) {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/thymeleaf/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCharacterEncoding("UTF-8");
resolver.setCacheable(false);//开发时关闭缓存,改动即可生效
return resolver;
}
}

2.4 开启默认Servlet处理

让SpringMVCConfig类实现这个接口:WebMvcConfigurer

并且重写以下的方法:

1
2
3
4
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}

2.5 view-controller

重写以下方法:

1
2
3
4
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/test").setViewName("test");
}

2.6 异常处理器

重写以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 配置异常处理器
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
// 可以配置多个异常处理器,这是其中一个。
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();

// 设置其中的 exceptionMappings 属性
Properties prop = new Properties();
prop.setProperty("java.lang.Exception", "tip");
resolver.setExceptionMappings(prop);

// 设置其中的 exceptionAttribute 属性
resolver.setExceptionAttribute("e");

// 将异常处理器添加到List集合中。
resolvers.add(resolver);
}

2.7 拦截器

自定义一个拦截器实现HandlerInterceptor接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.muyoukule.interceptors;

@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor's preHandle");
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor's postHandle");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor's afterCompletion");
}
}

在SpringMVCConfig类重写以下方法:

1
2
3
4
5
@Override
public void addInterceptors(InterceptorRegistry registry) {
MyInterceptor myInterceptor = new MyInterceptor();
registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/test");
}