范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

牛啊!终于有人把主流服务层框架SpringMVC讲明白了

  SpringMVC简介
  首先我们先来简单了解一下SpringMVC: SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 SpringMVC致力于服务层,同Servlet一样应用于服务层,用于服务层开发 SpringMVC隶属于Spring,同样具有简化代码,使用简单,开发便捷,灵活性强的优点 SpringMVC入门案例
  在未学习SpringMVC之前,我们的服务端开发通常采用Servlet: package com.itheima.web.servlet.old;  import com.alibaba.fastjson.JSON; import com.itheima.pojo.Brand; import com.itheima.service.BrandService; import com.itheima.service.impl.BrandServiceImpl;  import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.util.List;  //@WebServlet("/addServlet") public class AddServlet extends HttpServlet {      private BrandService brandService = new BrandServiceImpl();      @Override     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {          //1. 接收品牌数据         BufferedReader br = request.getReader();         String params = br.readLine();//json字符串          //转为Brand对象         Brand brand = JSON.parseObject(params, Brand.class);          //2. 调用service添加         brandService.add(brand);          //3. 响应成功的标识         response.getWriter().write("success");     }      @Override     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {         this.doGet(request, response);     } }
  我们可以注意到其过程非常繁琐,因为我们需要获取参数并进行类型转换,包括添加至Service等过程
  但是SpringMVC秉承着简化代码的原则,将大部分内容转化为Java代码进行封装,大大减少了繁琐的过程
  接下来我们来介绍SpringMVC版: 导入jar包 <?xml version="1.0" encoding="UTF-8"?>     4.0.0    com.itheima   springmvc_01_quickstart   1.0-SNAPSHOT   war                 javax.servlet       javax.servlet-api       3.1.0       provided                  org.springframework       spring-webmvc       5.2.10.RELEASE                                 org.apache.tomcat.maven         tomcat7-maven-plugin         2.1                    80           /                            创建SpringMVC控制类(等同于Servlet类) package com.itheima.controller;  import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;  //定义表现层控制器bean @Controller public class UserController {      //设置映射路径为/save,即外部访问路径     @RequestMapping("/save")     //设置当前操作返回结果为指定json数据(本质上是一个字符串信息)     @ResponseBody     public String save(){         System.out.println("user save ...");         return "{"info":"springmvc"}";     }      //设置映射路径为/delete,即外部访问路径     @RequestMapping("/delete")     @ResponseBody     public String delete(){         System.out.println("user save ...");         return "{"info":"springmvc"}";     } } 初始化SpringMVC环境(同Spring一样创建Config配置Java类) package com.itheima.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;  //springmvc配置类,本质上还是一个spring配置类 @Configuration @ComponentScan("com.itheima.controller") public class SpringMvcConfig { } 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求 /* 我们服务层的实际操作都是放置于Servlet容器中 我们配置的SpringMVC和Spring环境都是用于服务层,所以我们需要把相关Config加载仅Servlet容器中 */  package com.itheima.config;  import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;  // web容器配置类 // AbstractDispatcherServletInitializer是SpringMVC为我们设置好的类,继承并实现相关方法即可 public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {     //加载springmvc配置类,产生springmvc容器(本质还是spring容器)     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;     } }
  我们对上述新的内容进行解析: @Controller 名称:@Controller 类型:类注解 位置:SpringMVC控制类定义上方 作用:设定SpringMVC的核心控制器Bean @RequestMapping 名称:@RequestMapping 类型:方法注解 位置:SpringMVC控制器方法定义上方 作用:设置当前控制器方法请求访问路径 相关属性:value(请求访问路径) @ResponseBody 名称:@ResponseBody 类型:方法注释 位置:SpringMVC控制器方法定义上方 作用:设置当前控制器方法响应内容为当前返回值,无需解析 AbstractDispatcherServletInitializer类 AbstractDispatcherServletInitializer是SpringMVC提供的快速初始化Web3.0容器的抽象类 AbstractDispatcherServletInitializer提供三个接口方法供用户实现 createServletApplicationContext方法用于创建Servlet容器时,加载SpringMVC对应的Bean并放入 AnnotationConfigWebApplicationContext的作用范围对应整个Web容器范围,必须使用WebApplicationcontext类型
  最后我们总结一下上述操作的出现频率: 一次性工作创建工程,设置服务器,加载工程导入坐标创建Web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器Bean) 常态工作定义处理请求的控制类定义处理请求的操作方法,并设置映射路径(@RequestMapper)与返回Json数据(@ResponseBody) SpringMVC工作流程
  在分析SpringMVC工作流程前,我们需要知道服务层是由下面的框架组成的:
  启动服务器初始化过程: 服务器启动,执行ServletContainersInitConfig类,初始化Web容器 执行createServletApplicationContext方法,创建了WebApplicationContext对象 加载SpringMvcConfig 执行@ComponentScan加载对应的bean 加载UserController,每个@RequestMapping的名称对应一个具体的方法 执行getServletMappings方法,定义所有的请求都通过SpringMVC
  单次请求过程: 发送请求localhost/save Web容器发现所有请求都经过SpirngMVC,将请求交给SpringMVC处理 解析请求路径/save 由/save匹配执行对应的方法save() 执行save() 检测到有@ResponseBody直接将save()方法的返回值作为响应求体返回给请求方 SpringMVC加载控制
  在学习SpringMVC之后,我们的Bean的范围逐渐变大: SpringMVC相关bean(表现层bean) Spring相关bean(业务层Service,功能DataSource等)
  但是我们在使用时,需要区分相关bean的导入路径: SpringMVC加载的bean对应的包均在com.itheima.controller包内 Spring加载的bean却包含有多个文件夹
  因而我们给出两种方法来解决Spring的扫描问题: Spring加载的bean设定范围为com.itheima,并排除掉controller包内的bean package com.itheima.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller;  @Configuration /* @ComponentScan注解设置扫描范围 @ComponentScan中包含有value,excludeFilters属性 value:用于控制扫描范围 excludeFilters:用于控制排除范围,需要采用@ComponentScan.Filter过滤器 type:设置排除规则,当前使用按照bean定义时的注解类型进行排除 classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean */ @ComponentScan(value="com.itheima",     excludeFilters = @ComponentScan.Filter(         type = FilterType.ANNOTATION,         classes = Controller.class     ) ) public class SpringConfig { }  /* 这里做一个小补充内容: @ComponentScan中除了excludeFilters,还包括有includeFilters includeFilters:加载指定的bean,需要指定类型(type)和具体项(classes) */ Spring加载的bean设定范围为精准范围,例如service包,dao包等 package com.itheima.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller;  @Configuration @ComponentScan({"com.itheima.service","com.itheima.dao"}) public class SpringConfig { } Servlet容器简化写法
  我们的Servlet容器中可以定义Spring和SpringMVC的配置文件 package com.itheima.config;  import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;  public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {          // 配置SpringMVC配置文件     protected WebApplicationContext createServletApplicationContext() {         AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();         ctx.register(SpringMvcConfig.class);         return ctx;     }          // 配置Spring配置文件     protected WebApplicationContext createRootApplicationContext() {         AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();         ctx.register(SpringConfig.class);         return ctx;     }          // 配置拦截路径     protected String[] getServletMappings() {         return new String[]{"/"};     }  } 我们可以注意到:
  Spring和SpringMVC导入方法中均采用AnnotationConfigWebApplicationContext来创建对象
  两者之间的区别仅仅是class包的不同
  Spring给了我们一种新的继承类用于简化开发: package com.itheima.config;  import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer; //web配置类简化开发,仅设置配置类类名即可 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[]{"/"};     } } 注意:
  AbstractAnnotationConfigDispatcherServletInitializer是createServletApplicationContext的继承类
  我们同样继承它的三个方法,但这次我们只需要在里面标明相关类和路径即可 常用工具推荐Postman
  在我们的SpringMVC中岔开一个话题: 关于我们的网页调试的复杂性
  我们在一个网页开发中,会不断的调试网页,通过各种路径反复查询或者采用不同的访问方式(GET/POST)
  如果我们采用正常的网页进行测试,无疑会出现非常麻烦的步骤
  所以我们推荐采用Postman软件,下面我们将会简单做一下介绍 Postman链接
  首先为大家附上链接: 下载链接:Download Postman (getpostman.com) 文档链接:PostMan中文文档 整合链接:Apipost-API 文档、设计、调试、自动化测试一体化协作平台 Postman操作讲解
  在了解操作前,我们需要明白Postman的作用: 用于分类存储网页请求 用于发送请求进行测试
  关于安装注册的过程我们不再赘述 Postman页面展示
  我们先来查看Postman的主页:
  首先我们可以看到左上角的Workspaces,这个是最大的分类空间
  我们可以看到左上角SpringMVC,这是我所创建的WorkSpaces,关于我在SpringMVC所做的网页测试部分将都在这里进行
  除此之外,我们可以看到右侧的DEMO1,以及内部的测试用例文件夹,以及项目save
  以上就是我们的Postman的基本页面 Postman具体使用
  我们的Postman的具体使用流程如下: 创建新的Workspaces
  选定主界面,创建对应文件夹
  创建项目(点击中间区域的加号)
  书写项目内容(GET可以更换其他类型,后面书写URL,下方key,value书写传递数据)
  下方的数据传递可以更换类型,例如更换为body体的raw来书写JSON格式
  书写后保存到相应列表并标注名称
  到这里,我们Postman的基本使用基本就结束了,到后面我们会对具体内容做具体补充~ SpringMVC设置请求与响应
  SpringMVC和Servlet同属于服务层的工具,那么必不可少的就是请求与响应的反馈问题
  接下来我们将一一介绍请求与响应的相关知识 请求映射路径设置
  首先我们先来想一想我们之前的路径设置是否有那么一点点缺陷? // Book的服务层  package com.itheima.controller;  import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;  @Controller public class BookController {     //请求路径映射     @RequestMapping("/save")     @ResponseBody     public String save(){         System.out.println("book save ...");         return "{"module":"book save"}";     } } // User的服务层  package com.itheima.controller;  import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  @Controller public class UserController {     //请求路径映射     @RequestMapping("/save")     @ResponseBody     public String save(){         System.out.println("user save ...");         return "{"module":"user save"}";     }     //请求路径映射     @RequestMapping("/delete")     @ResponseBody     public String delete(){         System.out.println("user delete ...");         return "{"module":"user delete"}";     }  }
  我们可以注意到我们的单个项目中不可能只包括有一个服务层
  但我们的请求映射路径却只是简单设计为相同的名称,就会导致我们访问该页面时,系统无法匹配
  所以我们需要给他们采用不同的映射路径,我们常有的操作是直接在前面加上一层该类的路径名: package com.itheima.controller;  import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;  @Controller public class BookController {     //请求路径映射     @RequestMapping("/book/save")     @ResponseBody     public String save(){         System.out.println("book save ...");         return "{"module":"book save"}";     } }
  但当项目逐渐增多,我们多次书写路径名就有可能导致错误,所以我们采用类注解@RequestMapping来解决: package com.itheima.controller;  import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  @Controller //类上方配置的请求映射与方法上面配置的请求映射连接在一起,形成完整的请求映射路径 @RequestMapping("/user") public class UserController {     //请求路径映射     @RequestMapping("/save")     @ResponseBody     public String save(){         System.out.println("user save ...");         return "{"module":"user save"}";     }     //请求路径映射     @RequestMapping("/delete")     @ResponseBody     public String delete(){         System.out.println("user delete ...");         return "{"module":"user delete"}";     }  }
  注意:@RequestMapping不仅仅可以用于方法表示映射,也可以用于整个Bean类中表示映射前缀 参数传递问题
  关于参数传递我们从三个方面来讲解: 传递方式 传递参数类型 特殊参数类型 按传递方式
  我们的传递方式通常采用GET或者POST方式
  但在前面的学习中我们可以知道我们的传递方式是有不同的,我们在Postman的书写形式也是不同的
  例如我们先给出一个简单的参数传递函数 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //普通参数:请求参数与形参名称对应即可完成参数传递     @RequestMapping("/commonParam")     @ResponseBody     public String commonParam(String name ,int age){         System.out.println("普通参数传递 name ==> "+name);         System.out.println("普通参数传递 age ==> "+age);         return "{"module":"common param"}";     }  }
  我们的GET方式直接在网页后用?和&来书写传递参数:
  我们的POST方式只能在下方的body中书写参数:
  然后我们需要注意到的是这里的中文同样会出现乱码行为
  这次我们选择在ServletContainersInitConfig中处理数据: // 下述代码基本属于我们创建项目的固定代码  package com.itheima.config;  import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;  import javax.servlet.Filter;  public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {     protected Class<?>[] getRootConfigClasses() {         return new Class[0]{SpringConfig.class};     }      protected Class<?>[] getServletConfigClasses() {         return new Class[]{SpringMvcConfig.class};     }      protected String[] getServletMappings() {         return new String[]{"/"};     }      //乱码处理     @Override     protected Filter[] getServletFilters() {         // CharacterEncodingFilter 属于处理中文编码的过滤器,我们直接创建即可(一次性操作)         CharacterEncodingFilter filter = new CharacterEncodingFilter();         filter.setEncoding("UTF-8");         return new Filter[]{filter};     } } 按参数方式
  我们按参数来分类主要分为五种: 普通参数 POJO类 嵌套式POJO类 数组参数 集合参数
  我们下面来一一介绍 普通参数
  普通参数:请求参数和形参变量名相同时,自动匹配 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //普通参数:请求参数与形参名称对应即可完成参数传递     @RequestMapping("/commonParam")     @ResponseBody     public String commonParam(String name ,int age){         System.out.println("普通参数传递 name ==> "+name);         System.out.println("普通参数传递 age ==> "+age);         return "{"module":"common param"}";     }  }
  Postman操作:
  这里需要注意:当请求参数名与形参名不同时,使用@RequestParam注解关联请求参数名称与形参名称之间的关系 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //普通参数:请求参数名与形参名不同时,使用@RequestParam注解关联请求参数名称与形参名称之间的关系     @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"}";     }  }
  Postman操作:
  @RequestParam:绑定请求参数与处理器方法形参间的关系
  包含有两个参数
  required:是否为必传参数
  defaultValue:参数默认值 POJO参数
  POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //POJO参数:请求参数与形参对象中的属性对应即可完成参数传递     @RequestMapping("/pojoParam")     @ResponseBody     public String pojoParam(User user){         System.out.println("pojo参数传递 user ==> "+user);         return "{"module":"pojo param"}";     }  }
  Postman操作:
  嵌套POJO参数
  嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递     @RequestMapping("/pojoContainPojoParam")     @ResponseBody     public String pojoContainPojoParam(User user){         System.out.println("pojo嵌套pojo参数传递 user ==> "+user);         return "{"module":"pojo contain pojo param"}";     }  }
  Postman操作:
  数组参数
  数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中     @RequestMapping("/arrayParam")     @ResponseBody     public String arrayParam(String[] likes){         System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes));         return "{"module":"array param"}";     }  }
  Postman操作:
  集合保存普通参数
  集合保存普通参数:请求参数与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据     @RequestMapping("/listParam")     @ResponseBody     public String listParam(@RequestParam List likes){         System.out.println("集合参数传递 likes ==> "+ likes);         return "{"module":"list param"}";     }  }
  Postman参数:
  按特殊参数方式
  我们的特殊参数主要介绍两种: JSON类型 日期类型
  我们下面一一介绍 JSON类型
  JSON类型是我们Web开发中最常用的类型,所以这一部分算是一个小重点
  我们将一一讲解JSON类型传递的步骤: 导入JSON坐标 <?xml version="1.0" encoding="UTF-8"?>     4.0.0    com.itheima   springmvc_04_request_param   1.0-SNAPSHOT   war                javax.servlet       javax.servlet-api       3.1.0       provided                 org.springframework       spring-webmvc       5.2.10.RELEASE                        com.fasterxml.jackson.core       jackson-databind       2.9.0                                 org.apache.tomcat.maven         tomcat7-maven-plugin         2.1                    80           /                           在SpringMVC配置类中添加JSON类型转换注解 package com.itheima.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.config.annotation.EnableWebMvc;  import javax.servlet.Filter; import javax.servlet.annotation.WebFilter;  @Configuration @ComponentScan("com.itheima.controller") //开启json数据类型自动转换 @EnableWebMvc public class SpringMvcConfig { } 在Controller中书写相关Web代码(注意:需要使用@RequestBody表示将请求体数据传递给请求参数) package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //集合参数:json格式     //1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc     //2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据     @RequestMapping("/listParamForJson")     @ResponseBody     public String listParamForJson(@RequestBody List likes){         System.out.println("list common(json)参数传递 list ==> "+likes);         return "{"module":"list common for json param"}";     }      //POJO参数:json格式     //1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc     //2.使用@RequestBody注解将外部传递的json数据映射到形参的实体类对象中,要求属性名称一一对应     @RequestMapping("/pojoParamForJson")     @ResponseBody     public String pojoParamForJson(@RequestBody User user){         System.out.println("pojo(json)参数传递 user ==> "+user);         return "{"module":"pojo for json param"}";     }      //集合参数:json格式     //1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc     //2.使用@RequestBody注解将外部传递的json数组数据映射到形参的保存实体类对象的集合对象中,要求属性名称一一对应     @RequestMapping("/listPojoParamForJson")     @ResponseBody     public String listPojoParamForJson(@RequestBody List list){         System.out.println("list pojo(json)参数传递 list ==> "+list);         return "{"module":"list pojo for json param"}";     }      }
  Postman操作:
  在上面我们有两个注解需要特别注意一下: @EnableWebMvc 名称:@EnableWebMvc 类型:配置类注解 位置:SpringMVC配置类定义上方 作用:开启SpringMVC多项辅助功能 @RequestBody 名称:@RequestBody 类型:形参注解 位置:SpringMVC控制器方法形参定义前面 作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次 @RequestBody和@RequestParam区别
  区别@RequestParam用于接收url地址传参,表单传参[application/x-www-form-urlencoded]@RequestBody用于接收JSON数据[application/json]应用后期开发中,发送json数据为主,@RequestBody应用较广如果发送非json格式数据,选用@RequestParam接收请求参数日期型参数类型
  我们的日期类型数据基于系统不同格式也不相同,大致有以下几种: 2022-10-05 2022/10/05 10/05/2022
  接收形参时,我们根据不同的日期格式设置不同的接收方式 package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.Arrays; import java.util.Date; import java.util.List; //请求参数 @Controller public class UserController {      //日期参数     //使用@DateTimeFormat注解设置日期类型数据格式,默认格式yyyy/MM/dd     @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"}";     }  }  /* 名称:@DateTimeFormat 类型:形参注解 位置:SpringMVC控制器方法前 作用:设定日期时间型数据格式 属性:pattern:日期时间格式字符串 */
  Postman操作:
  这里我们简单介绍一下@DateTimeFormat的转换原理Converter接口: public interface Converter{ 	@Nullable     T convert(S var1) }
  Converter接口属于顶层接口,由它为起源创建了许多相关的接口与类用于各种转化: 请求参数年龄数据(String->Integer) 日期格式转发(String->Date)
  @EnableWebMvc功能之一:根据类型匹配对应的类型转换器 设置响应
  在了解请求的相关知识之后,我们回到Controller代码中学习一下响应 跳转响应
  在正常情况下,我们的响应给出的是当前项目的文档,相当于页面的跳转效应: package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.ArrayList; import java.util.Date; import java.util.List;  @Controller public class UserController {      //响应页面/跳转页面     //返回值为String类型,设置返回值为页面名称,即可实现页面跳转     @RequestMapping("/toJumpPage")     public String toJumpPage(){         System.out.println("跳转页面");         return "page.jsp";     }  } 信息响应
  如果我们希望得到一些信息响应,就需要采用注解解释: package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;  import java.util.ArrayList; import java.util.Date; import java.util.List;  @Controller public class UserController {          //响应文本数据     //返回值为String类型,设置返回值为任意字符串信息,即可实现返回指定字符串信息,需要依赖@ResponseBody注解     @RequestMapping("/toText")     @ResponseBody     public String toText(){         System.out.println("返回纯文本数据");         return "response text";     }      //响应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;     }      //响应POJO集合对象     //返回值为集合对象,设置返回值为集合类型,即可实现返回对应集合的json数组数据,需要依赖@ResponseBody注解和@EnableWebMvc注解     @RequestMapping("/toJsonList")     @ResponseBody     public List toJsonList(){         System.out.println("返回json集合数据");         User user1 = new User();         user1.setName("传智播客");         user1.setAge(15);          User user2 = new User();         user2.setName("黑马程序员");         user2.setAge(12);          List userList = new ArrayList();         userList.add(user1);         userList.add(user2);          return userList;     } }  /* 名称:@ResponseBody 类型:方法注解 位置:SpringMVC控制器方法定义上方 作用:设置当前控制器返回值作为响应体 */
  当我们使用Postman访问该链接时就会给出对应反馈,这里就不做演示了 REST风格
  首先我们来简单介绍一下REST: REST(Representational State Transfer),表现形式状态转换
  我们给出正常风格和REST风格两种书写形式,我们可以明显看到REST的内容做出大规模的省略: 正常风格:http://localhost/user/getById?id=1 REST风格:http://localhost/users/1
  REST风格优点: 书写简化 隐藏资源的访问行为,无法通过地址得知对资源的操作 REST风格简介
  我们来对REST风格做出简单解释: REST风格是采用访问资源的行为动作来区别对资源进行了何种操作
  我们给出五种常见行为动作: http://localhost/users:查看全部用户信息 GET(查询) http://localhost/users/1: 查看指定用户信息 GET(查询) http://localhost/users:添加用户信息 POST(新增/保存) http://localhost/users:修改用户信息 PUT(修改/更新) http://localhost/users/1: 删除用户信息 DELETE(删除)
  我们通常将根据REST风格进行的访问称为RESTful 上述行为是约定方式,约定不是规范,是可以打破的,所以称为REST风格,而不是REST规范
  描述模块的名称通常使用负数,也就是加s的格式描述,表示此类,而非单个资源 RESTful入门案例
  从本质上而言,REST只是一种规范形式,我们对于REST的风格修改仅针对于Controller
  我们下面将逐步进行RESTful的修改: 设置http请求动作 package com.itheima.controller;  import com.itheima.domain.Book; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;  @Controller public class BookController {      // RequestMapping中包含value和method两种属性     // value:访问路径     // method:访问方法     @RequestMapping(value = "/users",method = Request.POST)     @RequestBody 	public String save(@RequestBody User user){ 		System.out.println("user save" + user);         return "{"module":"user save"}"     } }  /* 名称:@RequestMapping 类型:方法注解 位置:SpringMVC控制器方法定义上方 作用:设置当前控制器方法请求访问路径 属性:value访问路径,method请求动作 */ 设置请求参数(路径变量) package com.itheima.controller;  import com.itheima.domain.Book; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;  @Controller public class BookController {      // 首先针对我们所需参数给出@PathVariable注解,并在访问路径中采用{}占位表示所传数据     // 简单来说就是,系统根据请求路径,得到所需数据,再带入到方法中     @RequestMapping(value = "/users/{id}" ,method = RequestMethod.DELETE)     @RequestBody     public String delete(@PathVariable Integer id){         System.out.println("book delete..." + id);         return "{"module":"book delete"}";     } }  /* 名称:@PathVariable 类型:形参注解 位置:SpringMVC控制器方法形参定义前面 作用:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应 */
  下面我们给出所有情况案例: package com.itheima.controller;  import com.itheima.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;  @Controller public class UserController {      //设置当前请求方法为POST,表示REST风格中的添加操作     @RequestMapping(value = "/users",method = RequestMethod.POST)     @ResponseBody     public String save(){         System.out.println("user save...");         return "{"module":"user save"}";     }      //设置当前请求方法为DELETE,表示REST风格中的删除操作     //@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同     @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)     @ResponseBody     public String delete(@PathVariable Integer id){         System.out.println("user delete..." + id);         return "{"module":"user delete"}";     }      //设置当前请求方法为PUT,表示REST风格中的修改操作     @RequestMapping(value = "/users",method = RequestMethod.PUT)     @ResponseBody     public String update(@RequestBody User user){         System.out.println("user update..."+user);         return "{"module":"user update"}";     }      //设置当前请求方法为GET,表示REST风格中的查询操作     //@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同     @RequestMapping(value = "/users/{id}" ,method = RequestMethod.GET)     @ResponseBody     public String getById(@PathVariable Integer id){         System.out.println("user getById..."+id);         return "{"module":"user getById"}";     }      //设置当前请求方法为GET,表示REST风格中的查询操作     @RequestMapping(value = "/users",method = RequestMethod.GET)     @ResponseBody     public String getAll(){         System.out.println("user getAll...");         return "{"module":"user getAll"}";     }  }   /* 	下述为原有代码:      @RequestMapping     @ResponseBody     public String delete(){         System.out.println("user delete...");         return "{"module":"user delete"}";     }      @RequestMapping     @ResponseBody     public String update(){         System.out.println("user update...");         return "{"module":"user update"}";     }      @RequestMapping     @ResponseBody     public String getById(){         System.out.println("user getById...");         return "{"module":"user getById"}";     }      @RequestMapping     @ResponseBody     public String getAll(){         System.out.println("user getAll...");         return "{"module":"user getAll"}";     } */ 我们在这里给出@RequestBody,@RequestParam,@PathVariable区别
  区别:
  @RequestParam用于接收url地址传参或表单传参@RequestBody用于接收json数据@PathVariable用于接收路径参数,使用{参数名称}描述路径参数
  应用:
  后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广如果发送非json格式数据,选用@RequestParam接受请求参数采用RESTful进行开发,当参数数量较少时,如1个,可以采用@PathVariable接收请求路径变量,常用来传递id值REST快速开发
  我们在上一小节中会发现有许多重复性的代码: // 每次都填写value,method导致代码繁冗 // 包括每次填写ResponseBody使代码繁冗  @RequestMapping(value = "/users",method = RequestMethod.GET) @ResponseBody
  所以我们可以采用一些小技巧来简化代码: 将前缀地址和相关注解放于类中: package com.itheima.controller;  import com.itheima.domain.Book; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;  //@Controller //@ResponseBody @RestController @RequestMapping("/books") public class BookController {  } /* 正常情况下,我们的类本身具有@Controller,并且为了省略类中的@ResponseBody而直接标注在类头 但Spring提供了一种新的注解@RestController,相当于@Controller和@ResponseBody的结合,我们只需要书写这一个注解即可   名称:@RestController 类型:类注解 位置:基于SpringMVC的RESTful开发控制器类定义上方 作用:设置当前控制器为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能 */ 采用新的地址注解代替老注解: package com.itheima.controller;  import com.itheima.domain.Book; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;  @RestController @RequestMapping("/books") public class BookController {  	//@RequestMapping( method = RequestMethod.POST)     //使用@PostMapping简化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简化DELETE请求方法对应的映射配置     @DeleteMapping("/{id}")          public String delete(@PathVariable Integer id){         System.out.println("book delete..." + id);         return "{"module":"book delete"}";     }  	//@RequestMapping(method = RequestMethod.PUT)     //使用@PutMapping简化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简化GET请求方法对应的映射配置     @GetMapping("/{id}")         public String getById(@PathVariable Integer id){         System.out.println("book getById..."+id);         return "{"module":"book getById"}";     }  	//@RequestMapping(method = RequestMethod.GET)     //使用@GetMapping简化GET请求方法对应的映射配置     @GetMapping                  public String getAll(){         System.out.println("book getAll...");         return "{"module":"book getAll"}";     } }  /* 名称:@GetMapping @PostMapping @PutMapping @DeleteMapping 类型:方法注解 位置:基于SpringMVC的RESTful开发控制器方法定义上方 作用:设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping对应GET请求 参数:value请求访问路径 */ 结束语
  好的,关于SpringMVC的内容就介绍到这里,希望能为你带来帮助!

警惕自称可以淡化肥胖纹的妊娠产品!不仅价格高甚至连有效为0警惕那些自称可以淡化肥胖纹的妊娠产品!不仅价格高,甚至连有效为0!对肥胖纹毫无作用!不想给它们交智商税的这5款妊娠油测评必看!某些妊娠产品不仅对肥胖纹没有用,还浪费钱!淡化肥胖纹,刚刚,国际油价大跌!这里,紧缩预期升温强美元冲击全球经济。北京时间9月7日晚,黄金跌原油跌国内商品期市夜盘开盘多数下跌大宗商品波动加剧9月7日21时左右,国际油价下挫,美油10月布油11月合约均跌逾3布油跌破90美元桶服贸之机视频加载中在服务业已成为拉动全球经济增长重要动力的今天,7000多家境内外企业以线上线下参会的方式,共同亮相2022年服贸会。中国机遇,全球共享。通过不断扩大开放深化合作引领创新,伦敦股市7日下跌新华社伦敦9月7日电(记者杨海若)英国伦敦股市金融时报100种股票平均价格指数7日报收于7237。83点,比前一交易日下跌62。61点,跌幅为0。86。欧洲三大股指当天涨跌不一。个美元兑人民币汇率破7,我们要如何应对为提升金融机构外汇资金运用能力,中国人民银行决定,自2022年9月15日起,下调金融机构外汇存款准备金率2个百分点,即外汇存款准备金率由现行8下调至6。外汇储备金率下调,能否避免美iQOO10Pro高配新机登场,iQOO9沦为百元机唱响价格悲歌如今的智能手机来讲,屏幕指纹已经不是什么新鲜事物,但想要给予用户更加极速更加安全的体验确实不容易。而iQOO10Pro支持超声波3D广域指纹,指纹识别区域面积578mm2,只需0。状况频出的湘雅医院,是时候走下神坛了湘雅医院回应专家将莲子壳当成肿瘤湘雅二院15名医护被罚医疗腐败软肋在哪湘雅二院刘翔峰9月6日,湘雅医院爆出丑闻,一位家长在网上发帖称,因发现其11个月的孩子嘴里有黑色硬块,带孩子到幼小衔接课程化,居家也能学!深高龙岗打造精彩课程套餐从幼儿园到小学是儿童成长过程的重要转折点,做好幼小衔接是迎接一年级萌娃入学的首要工作。结合深圳市教育局关于2022年秋季学期全市中小学开展在线教学的通知文件精神,深圳市高级中学龙岗扫地机器人哪个牌子好,扫地机器人科普扫地机器人哪个牌子好,毋庸置疑是冰尊扫地机器人最好,虽然说金无赤足人无完人,但在购买扫地机器人的时候,大多数用户还是会期待自己能入手到完美的机器,那扫地机器人哪个牌子好?下文开始介初一看习惯初二看思维初三看自主卡位三个关键点,初中学生才能让静待花开。卡位1初一培养良好的习惯初一最关键就是改变小学时的不良习惯,比如拖沓书写好动等等。同时,要养成新的良好习惯。良好的学习习惯,主要做好以下五个中央财政再下达福建实际种粮农民一次性农资补贴来源东南网据福建省财政厅消息,针对农资市场价格走势和农业生产形势,近期,中央财政在此前已下达我省两批实际种粮农民一次性农资补贴资金基础上,再下达补贴资金6952万元,以缓解农资价格
谈欢时景深欢欢,我好像,爱上茉儿了。时景深说这话的时候,眼神里带着一种深深的,谈欢从没有见过的缱绻。时景深,她爱了二十年的竹马,跟她说,他爱上了自己的闺蜜。谈欢勾起自己烈焰一般的红唇,恭喜啊气疯向太,让向佐疯狂迷恋,两度嫁入豪门的黄婉佩,手段太高明文李培树编辑孙大圣1999年,是范文芳的幸运之年,也是不幸之年。幸运的是她凭借尔冬升导演的真心话中的阿真一角被提名香港电影金像奖,成为第一位入围香港电影金像奖的新加坡艺人。不幸的是伊朗启动新型离心机,美推动削减核武器,绝不能树立另一个强敌据央视新闻8月2日报道,伊朗原子能组织对外透露,伊朗政府目前已经下令启动了数百台新型的离心机,并已向国际原子能机构进行了相关通报。据悉,此举意在加大伊朗对于铀浓缩的制造活动,以满足言情小说(年轻漂亮的小美妇)第六十五章不能给你,哎呀!你就别喝了。我们都喝醉了,谁来照顾小慧啊?小雨把手里的半杯酒给倒在了地上。妈妈!你别喝了,看你脸都那么红了。小慧拉着沈丽的手。沈丽微笑着捏了捏小慧的脸,闺女啊!你妈2019年,温州富婆征婚送宾利,网友直言不敢娶,后来结婚了吗?如果有人娶我,我就送他一辆宾利作为彩礼!这是2019年网络某婚恋短视频里的话。视频一出,瞬间传遍网络。现在很多人上网的时候,经常拿有钱买不到爱情这句话开玩笑。这句话看似好玩,实则道2020年,浙江小伙捡到1只奇怪甲虫,两天后网友出价31万都不肯卖浙江小伙上班途中捡到一只奇怪甲虫,拍下照片放到网上,结果两天后有网友出价31万,他都不肯卖。有人笑他傻,有钱都不赚,他却反过来笑别人不懂装懂这东西比金子值钱。究竟什么虫子价值31万终于明白,林志颖车祸后为啥娱乐圈集体失声了林志颖做了什么欺骗行为?让我们回顾一下拿手机装X几年前,林志颖在新iPhone发布之前拍下了照片并发布了一份文档。假装认真,引来了一段时间不知道真相的网友的嫉妒。但后来大家都知道他62岁的山口百惠微胖也气质,穿衣简约不扮嫩,自然老去的样子真美年龄会影响女性的身材与颜值,但夺不走气质,反而经历岁月沉淀之后,女性的魅力会越来越迷人。比如如今已62岁的山口百惠,纵使脸上布满皱纹,身材逐渐发福变胖,依旧从容地面对岁月,做一个优六公主今晚叒双又整活了,网友你可以永远相信CCTV6国与国之间的对抗较量,从古至今都不仅仅是军事的比拼,舆论,在其中也能发挥关键作用。然而就近日佩洛西将要访问台湾一事,六公主又找了几部别有深意的片子,可以说六公主紧跟时事的能力真不是爱情公寓诺澜大变样,毫无辨识度像网红,网友直呼认不出了近日,关于久未露面的刘萌萌现身沉香如屑引来不少网友的热议,对于当年曾在爱情公寓中饰演诺澜一角成功走入大众视野,她与娄艺潇饰演的胡一菲都和曾小贤的感情线也一度成为不少网友心目中的意难李小璐带女儿云南旅游,母女俩人高颜值,潇洒玩乐被质疑经济来源8月1日,女明星李小璐晒出自己和女儿贾云馨在云南西双版纳游玩的视频,说自己和闺蜜去了趟西双版纳,结束了快乐炎热的七月,准备开始了新鲜的八月。视频里,是李小璐集锦了自己和女儿在云南游