这里写目录标题
回顾Servet开发流程
- 创建web工程
- 设置TomCat服务器,加载Web工程
- 导入Servlet坐标
- 定义处理请求的功能类(Servlet)
- 在web.xml中设置请求映射(配置映射关系)
使用SpringMVC基本也是同样的操作流程
使用SpringMVC开发web程序流程
- 创建web工程(Maven流程)
- 设置TomCat服务器,加载web工程
- 导入坐标(SpringMVC+Servlet)
- 定义处理请求的功能类(Controller)
- 设置请求映射(配置映射关系)
- 将SpringMVC设定加载到Tomcat容器中
入门案例实现
一:导入依赖
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- tomcat 插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
二:编写SpringConfig配置类
和SpringConfig配置类相似: 用于设置容器的相关内容
@ComponentScan注解用来定义扫描的包
@Configuration
@ComponentScan("icu.not996.controller")
public class SpringMvcConfig {
}
三:定义Controller类
该类必须是受Spring管理的bean,延伸注解中有一个专门做视图层的注解:@Controller
类中必须有处理器对应的方法方法处理请求,同时需要给它加上@RequestMapping注解来指定它处理的请求路径
package icu.not996.controller;
......
@Controller
public class UserController {
@RequestMapping(value = "/save")
@ResponseBody //表示返回的内容就是响应体
public String save(@RequestParam("name") String name){
System.out.println("User save ..."+name);
return "{'info':'springmvc'}"; //返回一段"数据"
}
}
四:使用配置类来代替Web.xml
SpringMVC提供了快速开发配置类的方式,用于服务器启动时会自动加载SpringMVC
实现方式:写一个配置类ServletContainersInitConfig继承抽象类AbstractDispatcherServletInitializer并重写其中的三个抽象方法:
- protected WebApplicationContext createServletApplicationContext():要求在其中加载SpringMVC容器对象
- protected String[] getServletMappings():设置哪些请求归SpringMVC处理
- protected WebApplicationContext createRootApplicationContext():加载Spring对应的容器对象
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext aca=new AnnotationConfigWebApplicationContext();
aca.register(SpringMvcConfig.class);//注册容器
return aca;
}
protected String[] getServletMappings() {
return new String[]{"/"}; //设置`所有的请求都归SpringMVC处理
}
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
简化书写:AbstractDispatcherServletInitializer类提供了一个子类AbstractAnnotationConfigDispatcherServletInitializer,能够帮助简化书写,仅需配置类名即可
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class}; //设置Spring容器配置类
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class}; //设置SpringMVC容器配置类
}
protected String[] getServletMappings() {
return new String[]{"/"}; //设置哪些请求归SpringMVC处理
}
}
五:使用TomCat插件运行web项目并测试
使用PostMan发送测试请求:
后台显示正常:
入门案例工作流程分析:
- 服务器启动,执行ServletContainersInitConfig类,初始化web容器
- 执行createServletApplicationContext()方法,创建WebApplicationContext对象
实际上是将容器加载进了ServletContext中
- 加载SpringMvcConfig
- 执行@CompentScan加载对应的bean
- 加载UserController,每个@RequestMapping的名称都对应一个具体的方法
其他细节配置
(1)Controller加载控制与业务bean加载控制
SpringMVC只用加载表现层的相关bean,其他的bean由于Spring加载,如何避免Spring加载到SpringMVC控制的bean?
处理方案:加载Spring控制的bean的时候排除掉SpringMVC控制的bean:
方式一:Spring加载bean的时候设定扫描范围为精确范围,例如service包,dao包等
方式二:排除掉controller包内的dao:使用SpringConfig配置类@ComponentScan注解的属性:excldeFilters
方式三:不区分Spring与SpringMVC的环境,将它们加载到同一环境中
@Configuration
//@ComponentScan({"icu.not996.service","icu.not996.dao"})
//设置spring配置类加载bean时的过滤规则,当前要求排除掉表现层对应的bean
//excludeFilters属性:设置扫描加载bean时,排除的过滤规则
//type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
//classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean
@ComponentScan(value="icu.not996",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
(2)请求和响应细节
请求路径设置
为了防止不同的模块相似业务导致请求路径冲突,所以,应该在对应的请求路径前加上模块名:
//请求路径映射
@RequestMapping("/book/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
因为同一个类中模块名相同,为了防止书写错误和减少冗余,通常在类上添加注解@RequestMapping用于提取请求路径的公共部分,代表整个模块的访问前缀:
@Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起,形成完整的请求映射路径
@RequestMapping("/user")
public class UserController {
//请求路径映射
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'user save'}";
}
}
请求的参数传递
- 传递普通参数:请求的参数名和Controller中对应方法的形参名相同即可,如果不相同使用:@RequestParam("")注解绑定请求参数和形参
- 传递对象属性参数:传递参数名和接收方法的属性名相同,自动将参数塞进对象的属性中
- 传递对象的引用属性参数:在请求中以 属性名.属性名的形式书写 例如 key:address.city value:beijing
- 传递一个数组:把参数使用同一个变量名传给服务器即可 服务器对应方法行参位置使用该类型对应的数组进行接收
- 使用集合接收多个参数:在方法形参前加上注解@RequestParam
总结:默认参数都能对应上,如果不能对应上,使用@RequestParam注解进行对应
传递json数据
(一):添加json数据转换相关坐标
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
(二):开启自动转化json数据的支持
在SpringMvcConfig类上添加依赖@EnableWebMvc
@Configuration
@ComponentScan("icu.not996.controller")
@EnableWebMvc //开启json数据类型自动转换
public class SpringMvcConfig {
}
(三):接收数据时在形参前加上@RequestBody
@RequestBody指定请求体中的数据进入形参中
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
System.out.println("list common(json)参数传递 list ==> "+likes);
return "{'module':'list common for json param'}";
}
解决请求乱码问题
重写AbstractAnnotationConfigDispatcherServletInitializer的getServletFilters()方法:
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter=new CharacterEncodingFilter("UTF-8");//spring提供的字符集过滤器
//import org.springframework.web.filter.CharacterEncodingFilter; springWeb包中
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
响应
响应页面
直接return页面的名称,以字符串的形式返回即可
//响应页面/跳转页面
//返回值为String类型,设置返回值为页面名称,即可实现页面跳转
@RequestMapping("/toJumpPage")
public String toJumpPage(){
System.out.println("跳转页面");
return "page.jsp";
}
响应数据
响应文本数据
使用@RequestBody注解
//响应文本数据
//返回值为String类型,设置返回值为任意字符串信息,即可实现返回指定字符串信息,需要依赖@ResponseBody注解
@RequestMapping("/toText")
@ResponseBody
public String toText(){
System.out.println("返回纯文本数据");
return "response text";
}
响应json数据
//响应POJO对象
//返回值为实体类对象,设置返回值为实体类类型,即可实现返回对应对象的json数据,需要依赖@ResponseBody注解和@EnableWebMvc注解
@RequestMapping("/toJsonPOJO")
@ResponseBody
public User toJsonPOJO(){
System.out.println("返回json对象数据");
User user = new User();
user.setName("itcast");
user.setAge(15);
return user;
}