SpringMVC是隶属于Spring框架的一部分,主要是用来进行Web开发,是对Servlet进行了封装。
实现:
<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.0modelVersion>
<groupId>com.zsgroupId>
<artifactId>springmvc_01_quickstartartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.10.RELEASEversion>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>8080port>
<path>/path>
configuration>
plugin>
plugins>
build>
project>
//设置springmvc的核心控制器bean,使用@Controller定义bean
@Controller
public class UserController {
//设置当前控制器方法请求访问路径
@RequestMapping("/save")
//@ResponseBody设置当前控制器方法响应内容为当前返回值,无需解析
@ResponseBody
public String save(){
System.out.println("user save ...");
//如果不加@ResponseBody,系统会根据返回值字符串寻找路径,例如return "index.jsp";会跳转到jsp页面
//返回真正json只需要返回对象,在pom引入jackson,springmvcconfig配置类注解@@EnableWebMvc,下面注释的语句就是返回JSON数据
//return new User("zhangsan",23);
return "{'info':'springmvc'}";
}
}
//3.创建SpringMVC的配置文件,加载controller对应的bean
@Configuration
@ComponentScan("com.zs.controller")
public class SpringMvcConfig {
}
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//创建Servlet容器时,加载springmvc的配置。将springmvc对应的bean并放入WebApplicationContext对象范围中。
//最终返回web容器WebApplicationContext ,web容器就是springmvc最终体现的容器。ApplicationContext应用上下文,容器
protected WebApplicationContext createServletApplicationContext() {
//创建注解配置的web容器。使用AnnotationConfigWebApplicationContext,比前面Spring创建注解容器的类AnnotationConfigApplicationContext中间多了Web
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
//加载springmvc的配置类字节码到web容器中,从而可以让web容器管理加载配置类管理的bean
//因为AnnotationConfigWebApplicationContext类没有带参构造方法,所以要手动为容器加载指定配置类字节码文件
ctx.register(SpringMvcConfig.class);
return ctx;
}
//设置由springmvc拦截并处理的请求路径,即springmvc拦截哪些请求。
//返回值String数组只有一个"/",代表所有路径都由springmvc处理
protected String[] getServletMappings() {
return new String[]{"/"};
}
//加载spring配置类,方法和加载springmvc方法相同,只是加载的配置类改成spring的配置文件
//如果创建Servlet容器时需要加载非表现层的bean,使用当前方法进行,使用方式和createServletApplicationContext相同。
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
}
方式一:
@Configuration
@ComponentScan({"com.itheima.service","comitheima.dao"})
public class SpringConfig {
}
方式二:
@Configuration
@ComponentScan(value="com.itheima",
excludeFilters=@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
excludeFilters属性:设置扫描加载bean时,排除的过滤规则
type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
ANNOTATION:按照注解排除
ASSIGNABLE_TYPE:按照指定的类型过滤
ASPECTJ:按照Aspectj表达式排除,基本上不会用
REGEX:按照正则表达式排除
CUSTOM:按照自定义规则排除
大家只需要知道第一种ANNOTATION即可
classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean
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);
return ctx;
}
}
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[]{"/"};
}
}
如果要求发送的是post请求,我们就得准备页面在页面上准备form表单,测试起来比较麻烦。所以我们就需要借助一些第三方工具,如PostMan
基本使用:
思考:团队多人开发,每个人设置不同的请求路径,冲突问题如何解决?
解决:设置模块名作为请求路径前缀
@RequestMapping
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>80port>
<path>/path>
<uriEncoding>UTF-8uriEncoding>
configuration>
plugin>
plugins>
build>
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//重写getServletFilters过滤器方法,返回数组传入CharacterEncodingFilter过滤器对象,乱码处理
@Override
protected Filter[] getServletFilters() {
//创建字符编码过滤器CharacterEncodingFilter对象
CharacterEncodingFilter filter = new CharacterEncodingFilter();
//设置编码
filter.setEncoding("UTF-8");
//返回过滤器数组,元素为CharacterEncodingFilter对象
return new Filter[]{filter};
}
}
说明:CharacterEncodingFilter是在spring-webmvc包中,会自动导入对应的依赖jar包
示例:
发送请求与参数:
http://localhost/commonParamDifferentName?name=张三&age=18
接收参数::
@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(@RequestParam("name") String userName , int age){
System.out.println("普通参数传递 userName ==> "+userName);
System.out.println("普通参数传递 age ==> "+age);
return "{'module':'common param different name'}";
}
示例:
POJO类,User
public class User {
private String name;
private int age;
//setter...getter...略
}
发送请求和参数:
http://localhost/commonParamDifferentName?name=张三&age=18
接收参数:
//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println("pojo参数传递 user ==> "+user);
return "{'module':'pojo param'}";
}
说明:请求参数key的名称要和POJO中属性的名称一致,否则无法封装
//POJO参数嵌套:请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println("pojo参数传递 user ==> "+user);
return "{'module':'pojo param'}";
}
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.0version>
dependency>
@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
说明:@EnableWebMvc,这个注解功能很强大,这里用到的是将JSON数据自动类型转换成对象的功能
4.设置接收json数据@RequestBody
@RequestMapping("/listParamForJson")
@ResponseBody
//使用@RequestBody注解将前端请求体传递的json数组数据,传递并转换到形参的集合对象中作为数据
public String listParamForJson(@RequestBody List<String> likes){
System.out.println("list common(json)参数传递 list ==> "+likes);
return "{'module':'list common for json param'}";
}
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user){
System.out.println("pojo(json)参数传递 user ==> "+user);
return "{'module':'pojo for json param'}";
}
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("list pojo(json)参数传递 list ==> "+list);
return "{'module':'list pojo for json param'}";
}
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern="yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date date2)
System.out.println("参数传递 date ==> "+date);
System.out.println("参数传递 date1(yyyy-MM-dd) ==> "+date1);
System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
return "{'module':'data param'}";
}
使用PostMan发送请求,携带两个不同的日期格式:
http://localhost/dataParam?date=2088/08/08&date1=2088-08-08&date2=2088/08/08 8:08:08
@EnableWebMvc功能之一:根据类型匹配对应的类型转化器
@Controller
public class UserController {
@RequestMapping("/toJumpPage")
//注意
//1.此处不能添加@ResponseBody,如果加了该注入,会直接将page.jsp当字符串返回前端
//2.方法需要返回String
public String toJumpPage(){
System.out.println("跳转页面");
return "page.jsp";
}
}
@Controller
public class UserController {
@RequestMapping("/toText")
//注意此处该注解就不能省略,如果省略了,会把response text当前页面名称去查找,如果没有回报404错误
@ResponseBody
public String toText(){
System.out.println("返回纯文本数据");
return "response text";
}
}
@Controller
public class UserController {
@RequestMapping("/toJsonPOJO")
@ResponseBody
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") //导入jackson-databind后可以格式化日期格式
public User toJsonPOJO(){
System.out.println("返回json对象数据");
User user = new User();
user.setName("itcast");
user.setAge(15);
return user;
}
}
返回值为实体类对象,设置返回值为实体类类型,即可实现返回对应对象的json数据,需要依赖@ResponseBody注解和@EnableWebMvc注解
@Controller
public class UserController {
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
System.out.println("返回json集合数据");
User user1 = new User();
user1.setName("传智播客");
user1.setAge(15);
User user2 = new User();
user2.setName("黑马程序员");
user2.setAge(12);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
return userList;
}
}
当方法上有@ReponseBody注解后
方法的返回值为字符串,会将其作为文本内容直接响应给前端
方法的返回值为对象,会将对象转换成JSON响应给前端
此处又使用到了类型转换,内部通过HttpMessageConverter接口的实现类完成的
问题:一个相同的url地址即可以是新增也可以是修改或者查询,我们该如何区分?
答:通过调用它的行为进行区分
环境准备:
1.导入坐标:
<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.0modelVersion>
<groupId>com.itheimagroupId>
<artifactId>springmvc_06_restartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.10.RELEASEversion>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.0version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>8080port>
<path>/path>
configuration>
plugin>
plugins>
build>
project>
public class User {
private String name;
private int age;
//getter...setter...toString省略
}
public class Book {
private String name;
private double price;
//getter...setter...toString省略
}
@Controller
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(@RequestBody User user) {
System.out.println("user save..."+user);
return "{'module':'user save'}";
}
@RequestMapping("/delete")
@ResponseBody
public String delete(Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
@RequestMapping("/update")
@ResponseBody
public String update(@RequestBody User user) {
System.out.println("user update..." + user);
return "{'module':'user update'}";
}
@RequestMapping("/getById")
@ResponseBody
public String getById(Integer id) {
System.out.println("user getById..." + id);
return "{'module':'user getById'}";
}
@RequestMapping("/findAll")
@ResponseBody
public String getAll() {
System.out.println("user getAll...");
return "{'module':'user getAll'}";
}
}
@Controller
public class BookController {
@RequestMapping(value = "/books",method = RequestMethod.POST)
@ResponseBody
public String save(@RequestBody Book book){
System.out.println("book save..." + book);
return "{'module':'book save'}";
}
@RequestMapping(value = "/books/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println("book delete..." + id);
return "{'module':'book delete'}";
}
@RequestMapping(value = "/books",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody Book book){
System.out.println("book update..." + book);
return "{'module':'book update'}";
}
@RequestMapping(value = "/books/{id}",method = RequestMethod.GET)
@ResponseBody
public String getById(@PathVariable Integer id){
System.out.println("book getById..." + id);
return "{'module':'book getById'}";
}
@RequestMapping(value = "/books",method = RequestMethod.GET)
@ResponseBody
public String getAll(){
System.out.println("book getAll...");
return "{'module':'book getAll'}";
}
}
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//乱码处理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
REST风格实现@RequestMapping的method属性,@PathVariable
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save() {
System.out.println("user save...");
return "{'module':'user save'}";
}
@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody User user) {
System.out.println("user update..." + user);
return "{'module':'user update'}";
}
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
/*@Controller
@ResponseBody*/
@RestController
@RequestMapping("/books")
public class BookController {
//@RequestMapping(method = RequestMethod.POST)
@PostMapping
public String save(@RequestBody Book book){
System.out.println("book save..." + book);
return "{'module':'book save'}";
}
//@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("book delete..." + id);
return "{'module':'book delete'}";
}
//@RequestMapping(method = RequestMethod.PUT)
@PutMapping
public String update(@RequestBody Book book){
System.out.println("book update..." + book);
return "{'module':'book update'}";
}
//@RequestMapping(value = "/{id}",method = RequestMethod.GET)
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("book getById..." + id);
return "{'module':'book getById'}";
}
//@RequestMapping(method = RequestMethod.GET)
@GetMapping
public String getAll(){
System.out.println("book getAll...");
return "{'module':'book getAll'}";
}
}
实现:
1.搭建项目导入jar包
2.编写Controller类,提供两个方法,一个用来做列表查询,一个用来做新增
3.在方法上使用RESTful进行路径设置
4.完成请求、参数的接收和结果的响应
5.使用PostMan进行测试
6.将前端页面拷贝到项目中
7.页面发送ajax请求
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.0modelVersion>
<groupId>com.zsgroupId>
<artifactId>spring_rest_caseartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.10.RELEASEversion>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.0version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>8080port>
<path>/path>
configuration>
plugin>
plugins>
build>
project>
public class Book {
private Integer id;
private String type;
private String name;
private String description;
//setter...getter...toString略
}
@RestController
@RequestMapping("/books")
public class BookController {
@PostMapping
public String save(@RequestBody Book book) {
System.out.println("book save =>"+book);
return "{'module':'book save success'}";
}
@GetMapping
public List<Book> getAll() {
System.out.println("book getAll is running ...");
List<Book> bookList = new ArrayList<Book>();
Book book1 = new Book();
book1.setType("计算机");
book1.setName("SpringMVC入门教程");
book1.setDescription("小试牛刀");
bookList.add(book1);
Book book2 = new Book();
book2.setType("计算机");
book2.setName("SpringMVC实战教程");
book2.setDescription("一代宗师");
bookList.add(book2);
Book book3 = new Book();
book3.setType("计算机丛书");
book3.setName("SpringMVC实战教程进阶");
book3.setDescription("一代宗师呕心创作");
bookList.add(book3);
return bookList;
}
}
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//乱码处理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
@Configuration
@ComponentScan("com.zs.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//当访问/pages/**时,走/pages目录下的内容
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}
SpringMvcConfig扫描SpringMvcSupport配置类
@Configuration
//@ComponentScan({"com.itheima.controller","com.itheima.config"})
@ComponentScan("com.zs")
@EnableWebMvc
public class SpringMvcConfig {
}
方式二:
SpringMvcConfig 实现WebMvcConfigurer 接口,既可以添加资源处理器,也可以添加拦截器,既然不用config的SpringMvcSupport,springmvc配置类也就不用扫描config目录
@Configuration
@ComponentScan({"package1.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterception projectInterception;
//添加拦截器,配置本地资源映射路径,在访问A(虚拟的)的时候,需要到B(实际的)的位置去访问。
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(projectInterception).addPathPatterns("/books","/books/*");
//如果只拦截/books,发送http://localhost/books/100后会发现拦截器没有被执行
//registry.addInterceptor(projectInterceptor).addPathPatterns("/books");
// }
//添加资源处理器
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}
saveBook () {
axios.post("/books",this.formData).then((res)=>{
});
},
//主页列表查询
getAll() {
axios.get("/books").then((res)=>{
this.dataList = res.data;
});
},
参考文章