SpringMVC概述
替代了原来的Servlet

入门案例
SpringMVC环境搭建及测试
1.导入依赖
XML
<!-- 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>${spring.version}</version>
</dependency>
2.写Controller
java
@Controller
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save...");
return "{'info':'SpringMVC'}";
}
}
3.配置SpringMVC的config,让他加载SpringMVC需要的bean
java
@Configuration
@ComponentScan("com.example.controller")
public class SpringMVCConfig {
}
4.配置Servlet容器
java
public class ServletConfig extends AbstractDispatcherServletInitializer {
@Override
//加载SpringMVC的容器
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(SpringMVCConfig.class);
return context;
}
@Override
//设置哪些请求归属于SpringMVC处理
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
//加载Spring容器配置 SpringMVC底层会用到Spring
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
启动Tomcat服务器,访问/save路径

流程分析

bean加载控制

我的目录结构

Spring需要加载除controller外的所有包,SpringMVC需要加载controller包
SpringMVCConfig

SpringConfig
方式1

方式2
这里会出现的一个问题是,由于SpringMVCConfig也用@Configuration注解,尽管SpringConfig已经把Controller排除了,但是SpringConfig 在扫描com.example包时 会调用SpringMVCConfig(里面加载了Controller) 把Controller重新加载回来,这样调用Spring的上下文对象仍然能得到Controller的实例化对象。测试代码和结果如下:

解决方法:
1.把这两个config都移到com.example包的外面,这样他们两个就不会被重复加载了。
2.SpringConfig加载的时候过滤@Component注解

方式3
这种方式下不区分Spring和SpringMVC的环境(这句话的意思是我们不需要显式地用@Component去定义SpringMVC和Spring的bean了(或者都扫同一个包?),也就是Spring和SpringMVC整合起来了,SpringMVC会用到Spring的bean)
ServletConfig
java
public class ServletConfig extends AbstractDispatcherServletInitializer {
@Override
//加载SpringMVC的容器
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();//初始化web容器
context.register(SpringMVCConfig.class);
return context;
}
@Override
//设置哪些请求归属于SpringMVC处理
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
//加载Spring容器配置 这里加载Spring,不区分Spring和SpringMVC环境
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();//初始化springIoC容器
context.register(SpringConfig.class);
return context;
}
}
ServletConfig优化(继承这个长长的东西)
代码量更少了
java
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
//加载Spring容器配置
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
//加载SpringMVC的容器
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVCConfig.class};
}
@Override
//设置所有请求都归属于SpringMVC处理
protected String[] getServletMappings() {
return new String[]{"/"};
}
}