SpringMVC 概述
# SpringMVC 概述
![[Pasted image 20220614164333.png]]
先前学习的MyBatis取代了原有的原生数据层,如今学习的SpringMVC取代了Servlet称为新的表示层
# Servlet和SpringMVC对比
![[Pasted image 20220614164632.png]] ![[Pasted image 20220614164648.png]] 同一种功能,很明显SpringMVC的代码量更加少,这点能加快程序员开发进度
# 安装
# 依赖安装
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.20</version>
</dependency>
2
3
4
5
6
7
8
9
10
11
切记千万不要使用tomcat10,由于更新导致包名变更,因此目前仍未适配到。
# 主类配置
在Spring章节中,当我们打算获取bean时,我们往往需要先获得AnnotationConfigApplicationContext
的实例对象,然后才能通过getBean()
获取。
在实现该对象时,其实还有个与他类似的同胞类,就是专门用于web的AnnotationConfigWebApplicationContext
,而我们SpringMVC就是要实例化这个类~
//config->SContainersInitConfig.java
public class SContainersInitConfig extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
从上面代码可知,我们需要让主类配置继承自AbstractDispatcherServletInitializer
,该类有三个方法需要实现。
createServletApplicationContext 该方法用于创建Servlet容器时,加载SpringMVC对应的bean并放入
WebApplicationContext
对象范围中,而WebApplicationContext
的作用范围为ServletContext
范围,即整个web容器范围 ![[Pasted image 20220615020916.png]]getServletMappings 该方法用于设定SpringMVC对应的请求映射路径,设置为
/
标识拦截所有请求,人已请求都将转交给SpringMVC处理 ![[Pasted image 20220615021016.png]]createRootApplicationContext 如果创建Servlet容器时需要加载非SpringMVC的bean,则使用当前方法执行,使用方式同
createServletApplicationContext
# 表示层逻辑
//controller->UserController.java
@Controller
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("Loading save()...");
return "{'module':'springmvc'}";
}
}
2
3
4
5
6
7
8
9
10
11
首先,class上面添加了一个新的注释@Controller
,该注释用于说明此类是表示层的控制器,这样做方便SpringMVC扫描,下面的save
函数上有两注释
@RequestMapping("/save")
- 用于匹配用户请求路径@ResponseBody
- 将返回值作为响应体返回
# SpringMVCConfig
//config->SpringMVCConfig.java
@Configuration
@ComponentScan("com.project.controller")
public class SpringMVCConfig {
}
2
3
4
5
# 启动流程
![[Pasted image 20220615021553.png]]
# Bean加载
假设我们项目的目录如下 ![[Pasted image 20220615021821.png]]
- SpringMVC仅加载controller包下的bean
- Spring需要加载除了controller包以外的bean
# 思想一
手动一个个导入
# 思想二
排除法导入
@Configuration
@ComponentScan(value = "com.project",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
))
@Import({SpringMVCConfig.class})
public class SpringConfig {
}
2
3
4
5
6
7
8
9
笔者心态:除非几百个,否则我还是选择思想一吧
如你所见,很麻烦。。。
- excludeFilters : 排除规则
- type : 排除的类型
- classes : 排除的类
上面的例子意思是按照注解类型排除掉注解为Controller的类。
注意:导入的包是org.springframework.stereotype.Controller;
# 小问题
这是当前目录结构: ![[Pasted image 20220615024710.png]]
这是SpringConfig配置:
@Configuration
@ComponentScan(value = "com.project",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
))
@Import({SpringMVCConfig.class})
public class SpringConfig {
}
2
3
4
5
6
7
8
9
这是SpringMVCConfig配置:
@Configuration
@ComponentScan("com.project.controller")
public class SpringMVCConfig {
}
2
3
4
那么问题来了,SpringConfig把Controller去掉了,但SpringMVCController又把它加上了,忙了一大轮岂不等于没写吗???
你只需要将这两个类移到com.project
外即可,这样彼此就不会互相加载了。
# 加载非SpringMVC的bean
上一段我们配置完了传统的Spring配置了,那么现在就能在主类配置中进行设置。
主类设置中还有一个没有使用到的方法createRootApplicationContext
就是用来做这件事的。
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
2
3
4
5
6
可以看到,配置和createServletApplicationContext
完全一样。
现在类的实现就是这样了: ![[Pasted image 20220615025628.png]]
你能注意到一个严重的问题,createServletApplicationContext
和createRootApplicationContext
的区别仅在于配置类的类名而已,其余完全一致,那么我们能不能省略到只填写类名呢??
事实上,我们主类配置继承的AbstractDispatcherServletInitializer
是继承自AbstractAnnotationConfigDispatcherServletInitializer
类,该类可用于更便捷地初始化。现在代码可以简化如下:
public class SContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVCConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16