SpringMVC开发步骤
添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.springmvc_demo</groupId><artifactId>springmvc_01_quickstart</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><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.10.RELEASE</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>80</port><path>/</path></configuration></plugin></plugins></build>
</project>
说明:servlet的坐标为什么需要添加<scope>provided</scope>
?
-
scope是maven中jar包依赖作用范围的描述,
-
如果不设置默认是
compile
在在编译、运行、测试时均有效 -
如果运行有效的话就会和tomcat中的servlet-api包发生冲突,导致启动报错
-
provided代表的是该包只在编译和测试的时候用,运行的时候无效直接使用tomcat中的,就避免冲突
创建配置类
@Configuration
@ComponentScan("com.springmvc_demo.controller")
public class SpringMvcConfig {
}
创建controller
@Controller
public class UserController {@RequestMapping("/save")@ResponseBodypublic String save(){System.out.println("user save ...");return "{'info':'springmvc'}";}
}
- @ResponseBody:表示把返回值直接作为body输出
- 如果没有使用@ResponseBody,返回值被当作页面文件名,找不到对应的文件,就会报404错误
- @ResponseBody可以注解方法,也可以直接注解整个类,相当于类型所有方法都使用了@ResponseBody
- @RequestMapping指定访问路径,也可以注解整个类,这样,会把类上注解的路径 + 方法上的路径,构成完整的访问路径
创建容器配置类代替web.xml,因此可以删除web.xml
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {//加载springmvc配置类protected WebApplicationContext createServletApplicationContext() {//初始化WebApplicationContext对象AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();//加载指定配置类ctx.register(SpringMvcConfig.class);return ctx;}//设置由springmvc控制器处理的请求映射路径protected String[] getServletMappings() {return new String[]{"/"};}//加载spring配置类protected WebApplicationContext createRootApplicationContext() {return null;}
}
- tomcat启动后会自动加载此配置类
启动
- 注意:启动命令选择tomcat7:run
注意事项
- SpringMVC是基于Spring的,在pom.xml只导入了
spring-webmvc
jar包的原因是它会自动依赖spring相关坐标 - AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
- AbstractDispatcherServletInitializer提供了三个接口方法供用户实现
- createServletApplicationContext方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围
- createServletApplicationContext用来加载SpringMVC环境
- getServletMappings方法,设定SpringMVC对应的请求映射路径,即SpringMVC拦截哪些请求
- createRootApplicationContext方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式和createServletApplicationContext相同。
- createRootApplicationContext用来加载Spring环境
SpringMVC服务启动流程
-
服务器启动,执行ServletContainersInitConfig类,初始化web容器
- 功能类似于以前的web.xml
-
执行createServletApplicationContext方法,创建了WebApplicationContext对象
- 该方法加载SpringMVC的配置类SpringMvcConfig来初始化SpringMVC的容器
-
加载SpringMvcConfig配置类
-
执行@ComponentScan加载对应的bean
- 扫描指定包及其子包下所有类上的注解,如Controller类上的@Controller注解
-
加载UserController,每个@RequestMapping的名称对应一个具体的方法
- 此时就建立了
/save
和 save方法的对应关系
- 此时就建立了
-
执行getServletMappings方法,设定SpringMVC拦截请求的路径规则
/
代表所拦截请求的路径规则,只有被拦截后才能交给SpringMVC来处理请求
用户请求处理流程
- 发送请求
http://localhost/save
- web容器发现该请求满足SpringMVC拦截规则,将请求交给SpringMVC处理
- 解析请求路径/save
- 由/save匹配执行对应的方法save()
- 上面的第五步已经将请求路径和方法建立了对应关系,通过/save就能找到对应的save方法
- 执行save()
Spring 与 SpringMVC
- SpringMVC只扫描加载其表现层相关bean,也就是controller包下的类
- Spring控制的bean就包括了:业务bean(Service),功能bean(DataSource,SqlSessionFactoryBean,MapperScannerConfigurer等)
- 所有在Spring的配置类中,注意控制@ComponentScan的扫描范围,避免扫描到表现层的bean
- @ComponentScan作用:设置spring配置类扫描路径,用于加载使用注解格式定义的bean,可以设置以下属性:
- excludeFilters: 排除扫描路径中加载的bean,需要指定类别(type)和具体项(classes)
- includeFilters: 加载指定的bean,需要指定类别(type)和具体项(classes)
- @ComponentScan作用:设置spring配置类扫描路径,用于加载使用注解格式定义的bean,可以设置以下属性:
- 在SpringMVC项目中如何引入Spring的配置:在容器配置类中
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {protected WebApplicationContext createServletApplicationContext() {AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();ctx.register(SpringMvcConfig.class);return ctx;}protected String[] getServletMappings() {return new String[]{"/"};}protected WebApplicationContext createRootApplicationContext() {AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();ctx.register(SpringConfig.class); // 这里加载Spring的配置类return ctx;}
}
- 上面类的简写方式,继承AbstractAnnotationConfigDispatcherServletInitializer,这样就可以不用再去创建AnnotationConfigWebApplicationContext对象,不用手动register对应的配置类
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {protected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}protected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}protected String[] getServletMappings() {return new String[]{"/"};}
}
参数传递
-
普通参数
-
POJO类型参数
-
嵌套POJO类型参数
-
数组类型参数
-
集合类型参数
-
@RequestParam:获取路径?后面的参数,或者form表单参数(application/x-www-form-urlencoded)
-
@RequestBody:获取请求体参数
-
@PathVariable:获取路径变量
-
注意:SpringMVC接收JSON数据的实现步骤为:
(1)导入jackson包
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version>
</dependency>
(2)使用PostMan发送JSON数据
(3)开启SpringMVC注解驱动,在配置类上添加@EnableWebMvc注解
(4)Controller方法的参数前添加@RequestBody注解
日期类型的参数
- 可以使用@DateTimeFormat(pattern="yyyy-MM-dd")指定参数传入的格式
- 以上各种参数,SpringMVC内部都有对应的转换类,它们都实现了:org.springframework.core.convert.converter.Converter接口
响应
-
不使用注解@ReponseBody, 方法的返回值当作页面名称
-
使用@ReponseBody
- 该注解可以写在类上或者方法上
- 写在类上就是该类下的所有方法都有@ReponseBody功能
- 当方法上有@ReponseBody注解后
- 方法的返回值为字符串,会将其作为文本内容直接响应给前端
- 方法的返回值为对象,会将对象转换成JSON响应给前端
此处又使用到了类型转换,内部还是通过Converter接口的实现类完成的,所以Converter除了前面所说的功能外,它还可以实现:
- 对象转Json数据(POJO -> json)
- 集合转Json数据(Collection -> json)
Rest风格
- 按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
http://localhost/users
查询全部用户信息 GET(查询)http://localhost/users/1
查询指定用户信息 GET(查询)http://localhost/users
添加用户信息 POST(新增/保存)http://localhost/users
修改用户信息 PUT(修改/更新)http://localhost/users/1
删除用户信息 DELETE(删除)
请求的方式比较多,但是比较常用的就4种,分别是GET
,POST
,PUT
,DELETE
。
按照不同的请求方式代表不同的操作类型。
- 发送GET请求是用来做查询
- 发送POST请求是用来做新增
- 发送PUT请求是用来做修改
- 发送DELETE请求是用来做删除
但是注意:
- 上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
- REST提供了对应的架构方式,按照这种架构设计项目可以降低开发的复杂性,提高系统的可伸缩性
- REST中规定GET/POST/PUT/DELETE针对的是查询/新增/修改/删除,但是我们如果非要用GET请求做删除,这点在程序上运行是可以实现的
- 但是如果绝大多数人都遵循这种风格,你写的代码让别人读起来就有点莫名其妙了。
- 描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts......
步骤
- 使用@RestController注解类,替换@Controller与@ResponseBody注解,简化书写
- 将@RequestMapping提到类上面,用来定义所有方法共同的访问路径
- 使用@GetMapping @PostMapping @PutMapping @DeleteMapping,分别对应
GET
,POST
,PUT
,DELETE
各种http操作