给酒吧做网站舆情优化公司

当前位置: 首页 > news >正文

给酒吧做网站,舆情优化公司,网上商城建网站,上海工商登记查询系统目录#xff1a; SpringMVC简介 背景SpringMVC概述技术体系定位快速入门 目的需求步骤代码实操测试工具 PostMan简介PostMan安装PostMan使用知识点总结请求与参数处理 请求路径 环境准备问题分析解决方式请求方式 环境准备技术分析参数 基本数据类型POJO嵌套POJO数组集合 SpringMVC简介 背景SpringMVC概述技术体系定位快速入门 目的需求步骤代码实操测试工具 PostMan简介PostMan安装PostMan使用知识点总结请求与参数处理 请求路径 环境准备问题分析解决方式请求方式 环境准备技术分析参数 基本数据类型POJO嵌套POJO数组集合List、Map ListMapDate日期类型File文件类型JSON类型中文乱码处理响应结果处理 前期准备响应页面 后端接口设置前端请求响应字符串响应JSON结果 后端接口设置前端请求类型转换器 问题思考ConverterHttpMessageConverter注意事项RESTful风格 RESTful风格简介快速体验 环境准备思路分析修改RESTful风格 新增删除修改根据ID查询查询所有知识点总结简化注解实战案例 需求分析环境准备后台接口开发页面访问处理扩展 运行原理技术架构组件介绍源码解析Debug源码 1.SpringMVC简介 背景 Servlet属于web层开发技术技术特点 每个请求都需要创建一个Servlet进行处理 创建Servlet存在重复操作 代码灵活性低开发效率低
是否有技术方案可以解决以上问题 SpringMVC概述 SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 详细介绍见官网Redirecting… 优点 使用简单、开发便捷(相比于Servlet) 灵活性强
技术体系定位 web程序通过浏览器访问前端页面发送异步请求到后端服务器 后台服务器采用三层架构进行功能开发 表现层负责接收请求和数据然后将数据转交给业务层 业务层负责调用数据层完成数据库表的增删改查并将结果返给表现层 表现层将数据转换成json格式返回给前端 前端页面将数据进行解析最终展示给用户。
变现层采用SpringMVC框架SpringMVC主要负责的内容有: controller如何接收请求和数据 如何将请求和数据转发给业务层 如何将响应数据转换成json发回到前端
2.快速入门 目的 能基于SpringMvc快速开发一个web应用 需求 搭建SpringMvc工程定义UserController.save()方法处理/save请求返回{module:springmvc}。 步骤 创建Maven项目并导入对应的jar包 创建控制器类 创建配置类 创建Tomcat的Servlet容器配置类
代码实操 创建Maven项目并导入对应的jar包 打开IDEA,创建一个新的maven项目 添加SpringMVC需要的依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.itheima/groupIdartifactIdspringmvc_01_quickstart/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingpropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.target/properties!–1. 导入SpringMVC与servlet的坐标– dependenciesdependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.2.10.RELEASE/version/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.1/versionconfigurationport8080/portpath//path/configuration/plugin/plugins/build /project 说明:servlet的坐标为什么需要添加scopeprovided/scope? scope是maven中jar包依赖作用范围的描述 如果不设置默认是compile在在编译、运行、测试时均有效 如果运行有效的话就会和tomcat中的servlet-api包发生冲突导致启动报错 provided代表的是该包只在编译和测试的时候用运行的时候无效直接使用tomcat中的就避免冲突
创建控制器类 //2.制作控制器类等同于Servlet //2.1必须是一个spring管理的bean //2.2定义具体处理请求的方法 //2.3设置当前方法的访问路径 //2.4设置响应结果为String类型数据 Controller public class UserController {RequestMapping(/save)ResponseBodypublic String save(){System.out.println(user save …);return springmvc;} }创建配置类 //3.定义配置类加载Controller对应的bean Configuration ComponentScan(com.itheima.controller) public class SpringMvcConfig { } 创建Tomcat的Servlet容器配置类 //4.定义servlet容器的配置类 public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {//加载springMVC配置protected WebApplicationContext createServletApplicationContext() {//初始化WebApplicationContext对象AnnotationConfigWebApplicationContext ctx new AnnotationConfigWebApplicationContext();//加载指定配置类ctx.register(SpringMvcConfig.class);return ctx;}//设置Tomcat接收的请求哪些归SpringMVC处理protected String[] getServletMappings() {return new String[]{/};}//设置spring相关配置protected WebApplicationContext createRootApplicationContext() {return null;} } 配置Tomcat环境 启动运行项目 浏览器访问 浏览器输入http://localhost/save进行访问可以看得如下内容 至此SpringMVC的入门案例就已经完成。   测试工具 PostMan简介 代码编写完后我们要想测试只需要打开浏览器直接输入地址发送请求即可。但是我们如果我们发送的是GET请求可以直接使用浏览器但是如果要发送的是POST请求呢? 如果要求发送的是post请求我们就得准备页面在页面上准备form表单测试起来比较麻烦。所以我们就需要借助一些第三方工具如PostMan. PostMan是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件作用常用于进行接口测试特征简单实用美观大方 PostMan安装 双击资料\Postman-win64-8.3.1-Setup.exe即可自动安装 安装完成后如果需要注册可以按照提示进行注册如果底部有跳过测试的链接也可以点击跳过注册 看到如下界面就说明已经安装成功。 PostMan使用 创建WorkSpace工作空间 发送请求 保存当前请求 注意:第一次请求需要创建一个新的目录后面就不需要创建新目录直接保存到已经创建好的目录即可。 知识点总结 Controller 名称Controller类型类注解位置SpringMVC控制器类定义上方作用设定SpringMVC的核心控制器bean RequestMapping 名称RequestMapping类型类注解或方法注解位置SpringMVC控制器类或方法定义上方作用设置当前控制器方法请求访问路径相关属性value(默认)请求访问路径 ResponseBody 名称ResponseBody类型类注解或方法注解位置SpringMVC控制器类或方法定义上方作用设置当前控制器方法响应内容为当前返回值无需解析 3.请求与参数处理 请求路径 环境准备 入门案例基础上编写BookController和UserController
Controller public class UserController {RequestMapping(/save)ResponseBodypublic String save(){System.out.println(user save …);return {module:user save};}RequestMapping(/delete)ResponseBodypublic String save(){System.out.println(user delete …);return {module:user delete};} }Controller public class BookController {RequestMapping(/save)ResponseBodypublic String save(){System.out.println(book save …);return {module:book save};} } 最终创建好的项目结构如下: 把环境准备好后启动Tomcat服务器后台会报错: 从错误信息可以看出: UserController有一个save方法访问路径为http://localhost/save BookController也有一个save方法访问路径为http://localhost/save 当访问http://localhost/saved的时候到底是访问UserController还是BookController?
问题分析 团队多人开发每人设置不同的请求路径冲突问题该如何解决? 解决思路:为不同模块设置模块名作为请求路径前置 对于Book模块的save,将其访问路径设置http://localhost/book/save 对于User模块的save,将其访问路径设置http://localhost/user/save 这样在同一个模块中出现命名冲突的情况就比较少了。 解决方式 解决方案
Controller public class UserController {RequestMapping(/user/save)ResponseBodypublic String save(){System.out.println(user save …);return {module:user save};}RequestMapping(/user/delete)ResponseBodypublic String save(){System.out.println(user delete …);return {module:user delete};} }Controller public class BookController {RequestMapping(/book/save)ResponseBodypublic String save(){System.out.println(book save …);return {module:book save};} } 问题是解决了但是每个方法前面都需要进行修改写起来比较麻烦而且还有很多重复代码如果/user后期发生变化所有的方法都需要改耦合度太高。 优化方式
Controller RequestMapping(/user) public class UserController {RequestMapping(/save)ResponseBodypublic String save(){System.out.println(user save …);return {module:user save};}RequestMapping(/delete)ResponseBodypublic String delete(){System.out.println(user delete …);return {module:user delete};} }Controller RequestMapping(/book) public class BookController {RequestMapping(/save)ResponseBodypublic String save(){System.out.println(book save …);return {module:book save};} } 注意: 当类上和方法上都添加了RequestMapping注解前端发送请求的时候要和两个注解的value值相加匹配才能访问到。 RequestMapping注解value属性前面加不加/都可以
请求方式 关于请求参数的传递与接收是和请求方式有关系的目前比较常见的两种请求方式为 GET POST
针对于不同的请求前端如何发送后端如何接收? 环境准备 创建处理器方法
Controller public class UserController { RequestMapping(/user/save) ResponseBody public String save(){System.out.println(user save …);return {module:user save};} } 使用PostMan进行GET调用与POST调用 GET请求与POST请求都能正常访问 技术分析 RequestMapping没有设置请求方式默认支持以下八种请求类型 指定请求方式后将不再支持其他类型请求类型 参数 基本数据类型 发送方式 URL地址传参 表单传参   接收方式 形参与参数名相同 此时可以直接获取请求参数 形参与参数名不同 需要设置 RequestParam 绑定请求参数与方法形参 知识点RequestParam 名称RequestParam类型形参注解位置SpringMVC控制器方法形参定义前面作用绑定请求参数与处理器方法形参间的关系相关参数required是否为必传参数 defaultValue参数默认值 POJO 简单数据类型一般处理的是参数个数比较少的请求如果参数比较多那么后台接收参数的时候就比较复杂这个时候我们可以考虑使用POJO数据类型。 POJO参数请求参数名与形参对象属性名相同定义POJO类型形参即可接收参数
新增POJO类 public class User {private String name;private Integer age;//setter…getter…略 } URL地址请求或表单请求 后台接收参数 //POJO参数请求参数与形参对象中的属性对应即可完成参数传递 RequestMapping(/pojoParam) ResponseBody public String pojoParam(User user){System.out.println(pojo参数传递 user user);return {module:pojo param}; } 注意: POJO参数接收前端GET和POST发送请求数据的方式不变。 请求参数key的名称要和POJO中属性的名称一致否则无法封装。
嵌套POJO 新增POJO类 public class User {private String name;private Integer age;private Address address;//setter…getter…略 }public class Address {private String province;private String city;//setter…getter…略 } URL地址请求或表单请求 请求参数名与形参对象属性名相同按照对象层次结构关系即可接收嵌套POJO属性参数 发送请求和参数: 后台接收参数 //POJO参数请求参数与形参对象中的属性对应即可完成参数传递 RequestMapping(/pojoParam) ResponseBody public String pojoParam(User user){System.out.println(pojo参数传递 user user);return {module:pojo param}; } 注意: 请求参数key的名称要和POJO中属性的名称一致否则无法封装 数组 请求参数名与形参对象属性名相同且请求参数为多个定义数组类型即可接收参数 URL地址请求或表单请求 后台接收参数 //数组参数同名请求参数可以直接映射到对应名称的形参数组对象中RequestMapping(/arrayParam)ResponseBodypublic String arrayParam(String[] likes){System.out.println(数组参数传递 likes Arrays.toString(likes));return {module:array param};} 集合List、Map List 数组能接收多个值那么集合是否也可以实现这个功能呢? 发送请求和参数: 1630484283773 错误接收方式: //集合参数同名请求参数可以使用RequestParam注解映射到对应名称的集合对象中作为数据 RequestMapping(/listParam) ResponseBody public String listParam(ListString likes){System.out.println(集合参数传递 likes likes);return {module:list param}; } 运行报错 错误原因 SpringMVC将List看做是一个POJO对象来处理将其创建一个对象并准备把前端的数据封装到对象中但是List是一个接口无法创建对象所以报错。
正确接收方式 使用RequestParam注解 //集合参数同名请求参数可以使用RequestParam注解映射到对应名称的集合对象中作为数据 RequestMapping(/listParam) ResponseBody public String listParam(RequestParam ListString likes){System.out.println(集合参数传递 likes likes);return {module:list param}; } 集合保存普通参数请求参数名与形参集合对象名相同且请求参数为多个RequestParam绑定参数关系 对于简单数据类型使用数组会比集合更简单些。 Map 发送请求和参数: 请求参数需要设置map的key值 接收方式 同List接收方式需要使用RequestParam注解 RequestMapping(/mapParam) ResponseBody public String mapParam(RequestParam MapString,String maps) {System.out.println(maps);return {module:mapParam}; } Date日期类型 URL地址请求或表单请求 后台接收参数 RequestMapping(/dateParam) ResponseBody public String dateParam(Date date,DateTimeFormat(pattern yyyy-MM-dd) Date date2,DateTimeFormat(pattern yyyy-MM-dd HH:mm:ss) Date date3){System.out.println(date:date);System.out.println(date2:date2);System.out.println(date3:date3);return {module:dateParam}; } 注意: SpringMvc默认时间格式为 yyyy/MM/dd 其他时间格式需要使用DateTimeFormat转换 知识点1DateTimeFormat
名称DateTimeFormat类型形参注解位置SpringMVC控制器方法形参前面作用设定日期时间型数据格式相关属性pattern指定日期时间格式字符串 File文件类型 前期准备 添加fileupload依赖 !–添加fileupload依赖– dependencygroupIdcommons-fileupload/groupIdartifactIdcommons-fileupload/artifactIdversion1.3.3/version /dependency 配置解析器  SpringMvcConfig 中配置 multipartResolver解析器,这里Bean的名称是固定的否则无法生效 Bean(multipartResolver) public CommonsMultipartResolver multipartResolver (){CommonsMultipartResolver resolver new CommonsMultipartResolver();resolver.setDefaultEncoding(UTF-8);resolver.setMaxUploadSize(1024*1024);return resolver; } POST请求方式 post请求选择 form-data 方式传递文件类型参数 后台接收参数 使用 MultipartFile 类型接收文件参数 RequestMapping(/fileParam) ResponseBody public String fileParam(MultipartFile file){if(!file.isEmpty()){try {file.transferTo(new File(D://test.txt));} catch (IOException e) {e.printStackTrace();}}return {module:file}; } JSON类型 现在比较流行的开发方式为异步调用。前后台以异步方式进行交换传输的数据使用的是JSON,所以前端如果发送的是JSON数据后端该如何接收? 前期准备 SpringMVC默认使用的是jackson来处理json的转换所以需要在pom.xml添加jackson依赖
dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.9.0/version /dependency 开启SpringMVC注解支持
在SpringMVC的配置类中开启SpringMVC的注解支持这里面就包含了将JSON转换成对象的功能。 Configuration ComponentScan(com.itheima.controller) //开启json数据类型自动转换 EnableWebMvc public class SpringMvcConfig { } json请求与接收 注意 接收json数据需要在形参变量前加 RequestBody注解 JSON对象数据 前端请求 后端接收 RequestMapping(/pojoParamForJson) ResponseBody public String pojoParamForJson(RequestBody User user) {System.out.println(user);return {module:pojoParamForJson}; } JSON普通数组 前端请求 后端接收 RequestMapping(/arrayParamForJson) ResponseBody public String arrayParamForJson(RequestBody String[] likes){System.out.println(Arrays.toString(likes));return {module:arrayParamForJson}; } JSON对象数据 前端请求 后台接收参数 RequestMapping(/arrayPojoParamForJson) ResponseBody public String arrayPojoParamForJson(RequestBody ListUser list){System.out.println(list);return {module:arrayPojoParamForJson}; } 中文乱码处理 GET请求 URL地址传参中文 响应结果中文乱码 解决方式
修改pom.xml来解决GET请求中文乱码问题 buildpluginsplugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.1/versionconfigurationport80/port!–tomcat端口号–path//path !–虚拟目录–uriEncodingUTF-8/uriEncoding!–访问路径编解码字符集–/configuration/plugin/plugins/build POST请求 POST表单传参 中文乱码 解决方式 配置过滤器
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[]{/};}//乱码处理Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter new CharacterEncodingFilter();filter.setEncoding(UTF-8);return new Filter[]{filter};} } CharacterEncodingFilter是在spring-web包中所以用之前需要导入对应的jar包。 4.响应结果处理 前期准备 编写模型类User
public class User {private String name;private int age;//getter…setter…toString省略 } webapp下创建page.jsp html body h2Hello Spring MVC!/h2 /body /html 响应页面 后端接口设置 RequestMapping(/toJumpPage)//注意//1.此处不能添加ResponseBody,如果加了该注入会直接将page.jsp当字符串返回前端//2.方法需要返回Stringpublic String toJumpPage(){System.out.println(跳转页面);return page.jsp;} 前端请求 响应字符串 1、后端接口设置 RequestMapping(/toText) ResponseBody public String toText(){return hello,springmvc; } 2、前端请求 响应JSON结果 返回值为实体类对象设置返回值为实体类类型即可实现返回对应对象的json数据需要依赖ResponseBody注解和EnableWebMvc注解 后端接口设置 RequestMapping(/toJson) ResponseBody public User toJson(){User user new User();user.setName(itheima);user.setAge(15);return user; } 前端请求 类型转换器 问题思考 前端传递字符串后端使用日期Date接收 前端传递JSON数据后端使用对象接收 后台需要的数据类型有很多种 前端传递字符串后端使用Integer接收 在数据的传递过程中存在很多类型的转换
问:谁来做这个类型转换? 答:SpringMVC 问SpringMVC是如何实现类型转换的? 答:Converter接口、HttpMessageConverter接口 Converter 用于实现简单数据型的类型转换逻辑的SPI
/**

  • S: the source type
  • T: the target type */ public interface ConverterS, T {Nullable//该方法就是将从页面上接收的数据(S)转换成我们想要的数据类型(T)返回T convert(S source); } 详细信息可查看官网介绍 HttpMessageConverter 用于转换HTTP请求和响应的策略接口 使用该接口实现了JSON、XML等数据类型的转换 详细信息可查看官网介绍 Web on Servlet Stack (spring.io) 注意事项 简单数据类型可以自动实现类型转换JSON等类型需要开启EnableWebMvc注解根据类型匹配对应的类型转换器。 5.RESTful风格 RESTful风格简介 RESTRepresentational State Transfer表现形式状态转换,它是一种软件架构风格 当我们想表示一个网络资源的时候可以使用两种方式: 传统风格资源描述形式 http://localhost/user/getById?id1 查询id为1的用户信息 http://localhost/user/saveUser 保存用户信息 REST风格描述形式 http://localhost/user/1 http://localhost/user
    传统方式一般是一个请求url对应一种操作这样做不仅麻烦也不安全因为会程序的人读取了你的请求url地址就大概知道该url实现的是一个什么样的操作。 按照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请求是用来做删除
    快速体验 环境准备 创建一个Web的Maven项目 pom.xml添加Spring依赖
    ?xml version1.0 encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.itheima/groupIdartifactIdspringmvc_06_rest/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingdependenciesdependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.2.10.RELEASE/version/dependencydependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.9.0/version/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.1/versionconfigurationport80/portpath//path/configuration/plugin/plugins/build /project 创建对应的配置类 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[]{/};}//乱码处理Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter new CharacterEncodingFilter();filter.setEncoding(UTF-8);return new Filter[]{filter};} }Configuration ComponentScan(com.itheima.controller) //开启json数据类型自动转换 EnableWebMvc public class SpringMvcConfig { } 编写模型类User和Book public class User {private String name;private int age;//getter…setter…toString省略 }public class Book {private String name;private double price;//getter…setter…toString省略 } 编写UserController和BookController Controller public class UserController {RequestMapping(/save)ResponseBodypublic String save(RequestBody User user) {System.out.println(user save…user);return {module:user save};}RequestMapping(/delete)ResponseBodypublic String delete(Integer id) {System.out.println(user delete… id);return {module:user delete};}RequestMapping(/update)ResponseBodypublic String update(RequestBody User user) {System.out.println(user update… user);return {module:user update};}RequestMapping(/getById)ResponseBodypublic String getById(Integer id) {System.out.println(user getById… id);return {module:user getById};}RequestMapping(/findAll)ResponseBodypublic String getAll() {System.out.println(user getAll…);return {module:user getAll};} }Controller public class BookController {RequestMapping(value /books,method RequestMethod.POST)ResponseBodypublic String save(RequestBody Book book){System.out.println(book save… book);return {module:book save};}RequestMapping(value /books/{id},method RequestMethod.DELETE)ResponseBodypublic String delete(PathVariable Integer id){System.out.println(book delete… id);return {module:book delete};}RequestMapping(value /books,method RequestMethod.PUT)ResponseBodypublic String update(RequestBody Book book){System.out.println(book update… book);return {module:book update};}RequestMapping(value /books/{id},method RequestMethod.GET)ResponseBodypublic String getById(PathVariable Integer id){System.out.println(book getById… id);return {module:book getById};}RequestMapping(value /books,method RequestMethod.GET)ResponseBodypublic String getAll(){System.out.println(book getAll…);return {module:book getAll};}} 最终创建好的项目结构如下: 思路分析 需求:将之前的增删改查替换成RESTful的开发方式。 之前不同的请求有不同的路径,现在要将其修改为统一的请求路径修改前: 新增: /save ,修改: /update,删除 /delete…修改后: 增删改查: /users根据GET查询、POST新增、PUT修改、DELETE删除对方法的请求方式进行限定发送请求的过程中如何设置请求参数? 修改RESTful风格 新增 Controller public class UserController {//设置当前请求方法为POST表示REST风格中的添加操作RequestMapping(value /users,method RequestMethod.POST)ResponseBodypublic String save() {System.out.println(user save…);return {module:user save};} } 将请求路径更改为/users 访问该方法使用 POST: http://localhost/users 使用method属性限定该方法的访问方式为POST 如果发送的不是POST请求比如发送GET请求则会报错 删除 Controller public class UserController {//设置当前请求方法为DELETE表示REST风格中的删除操作RequestMapping(value /users,method RequestMethod.DELETE)ResponseBodypublic String delete(Integer id) {System.out.println(user delete… id);return {module:user delete};} } 将请求路径更改为/users 访问该方法使用 DELETE: http://localhost/users
    访问成功但是删除方法没有携带所要删除数据的id,所以针对RESTful的开发如何携带数据参数? 答传递路径参数 前端发送请求的时候使用:http://localhost/users/1,路径中的1就是我们想要传递的参数。 后端获取参数需要做如下修改: 修改RequestMapping的value属性将其中修改为/users/{id}目的是和路径匹配 在方法的形参前添加PathVariable注解
    Controller public class UserController {//设置当前请求方法为DELETE表示REST风格中的删除操作RequestMapping(value /users/{id},method RequestMethod.DELETE)ResponseBodypublic String delete(PathVariable Integer id) {System.out.println(user delete… id);return {module:user delete};} } 思考如下两个问题: (1)如果方法形参的名称和路径{}中的值不一致该怎么办? (2)如果有多个参数需要传递该如何编写? 前端发送请求的时候使用:http://localhost/users/1/tom,路径中的1和tom就是我们想要传递的两个参数。 后端获取参数需要做如下修改: Controller public class UserController {//设置当前请求方法为DELETE表示REST风格中的删除操作RequestMapping(value /users/{id}/{name},method RequestMethod.DELETE)ResponseBodypublic String delete(PathVariable Integer id,PathVariable String name) {System.out.println(user delete… id,name);return {module:user delete};} } 修改 Controller public class UserController {//设置当前请求方法为PUT表示REST风格中的修改操作RequestMapping(value /users,method RequestMethod.PUT)ResponseBodypublic String update(RequestBody User user) {System.out.println(user update… user);return {module:user update};} } 将请求路径更改为/users 访问该方法使用 PUT: http://localhost/users 访问并携带参数: 根据ID查询 Controller public class UserController {//设置当前请求方法为GET表示REST风格中的查询操作RequestMapping(value /users/{id} ,method RequestMethod.GET)ResponseBodypublic String getById(PathVariable Integer id){System.out.println(user getById…id);return {module:user getById};} } 将请求路径更改为/users 访问该方法使用 GET: http://localhost/users/666
    查询所有 Controller public class UserController {//设置当前请求方法为GET表示REST风格中的查询操作RequestMapping(value /users ,method RequestMethod.GET)ResponseBodypublic String getAll() {System.out.println(user getAll…);return {module:user getAll};} } 将请求路径更改为/users 访问该方法使用 GET: http://localhost/users
    小结 RESTful入门案例我们需要学习的内容如下: (1)设定Http请求动作(动词) RequestMapping(value,method RequestMethod.POST|GET|PUT|DELETE) (2)设定请求参数(路径变量) RequestMapping(value/users/{id},method RequestMethod.DELETE)ReponseBodypublic String delete(PathVariable Integer id){} 知识点总结 PathVariable介绍 名称PathVariable类型形参注解位置SpringMVC控制器方法形参定义前面作用绑定路径参数与处理器方法形参间的关系要求路径参数名与形参名一一对应 形参注解对比 关于接收参数我们学过三个注解RequestBody、RequestParam、PathVariable,这三个注解之间的区别和应用分别是什么? 区别 注解类型作用备注RequestParam形参注解接收1.url地址参数2.表单参数RequestBody形参注解接收json参数一个处理器方法只能使用一次PathVariable形参注解接收路径参数 应用 后期开发中发送请求参数超过1个时以json格式为主RequestBody应用较广 如果发送非json格式数据选用RequestParam接收请求参数 采用RESTful进行开发当参数数量较少时例如1个可以采用PathVariable接收请求路径变量通常用于传递id值
    简化注解 做完了RESTful的开发你会发现好麻烦麻烦在哪? 问题1每个方法的RequestMapping注解中都定义了访问路径/books重复性太高。 问题2每个方法的RequestMapping注解中都要使用method属性定义请求方式重复性太高。 问题3每个方法响应json都需要加上ResponseBody注解重复性太高。 对于上面所提的这三个问题具体该如何解决? RestController //Controller ReponseBody RequestMapping(/books) public class BookController {//RequestMapping(method RequestMethod.POST)PostMappingpublic 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)PutMappingpublic 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)GetMappingpublic String getAll(){System.out.println(book getAll…);return {module:book getAll};}} 对于刚才的问题我们都有对应的解决方案 问题1每个方法的RequestMapping注解中都定义了访问路径/books重复性太高。 将RequestMapping提到类上面用来定义所有方法共同的访问路径。 问题2每个方法的RequestMapping注解中都要使用method属性定义请求方式重复性太高。 使用GetMapping PostMapping PutMapping DeleteMapping代替 问题3每个方法响应json都需要加上ResponseBody注解重复性太高。 1.将ResponseBody提到类上面让所有的方法都有ResponseBody的功能 2.使用RestController注解替换Controller与ResponseBody注解简化书写 RestController
    名称RestController类型类注解位置基于SpringMVC的RESTful开发控制器类定义上方作用设置当前控制器类为RESTful风格 等同于Controller与ResponseBody两个注解组合功能 GetMapping PostMapping PutMapping DeleteMapping
    名称GetMapping PostMapping PutMapping DeleteMapping类型方法注解位置基于SpringMVC的RESTful开发控制器方法定义上方作用设置当前控制器方法请求访问路径与请求动作每种对应一个请求动作 例如GetMapping对应GET请求相关属性value默认请求访问路径 实战案例 需求分析 需求一:图片列表查询从后台返回数据将数据展示在页面上 需求二:新增图片将新增图书的数据传递到后台并在控制台打印 说明:此次案例的重点是在SpringMVC中如何使用RESTful实现前后台交互所以本案例并没有和数据库进行交互所有数据使用假数据来完成开发。 步骤分析: 搭建项目导入jar包编写Controller类提供两个方法一个用来做列表查询一个用来做新增在方法上使用RESTful进行路径设置完成请求、参数的接收和结果的响应使用PostMan进行测试将前端页面拷贝到项目中页面发送ajax请求完成页面数据的展示 环境准备 创建一个Web的Maven项目 pom.xml添加Spring依赖
    ?xml version1.0 encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.itheima/groupIdartifactIdspringmvc_07_rest_case/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingdependenciesdependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.2.10.RELEASE/version/dependencydependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.9.0/version/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.1/versionconfigurationport80/portpath//path/configuration/plugin/plugins/build /project创建对应的配置类 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[]{/};}//乱码处理Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter new CharacterEncodingFilter();filter.setEncoding(UTF-8);return new Filter[]{filter};} }Configuration ComponentScan(com.itheima.controller) //开启json数据类型自动转换 EnableWebMvc public class SpringMvcConfig { } 编写模型类Book public class Book {private Integer id;private String type;private String name;private String description;//setter…getter…toString略 } 编写BookController Controller public class BookController {} 最终创建好的项目结构如下: 后台接口开发 编写Controller类并使用RESTful进行配置
    RestController RequestMapping(/books) public class BookController {PostMappingpublic String save(RequestBody Book book){System.out.println(book save book);return {module:book save success};}GetMappingpublic ListBook getAll(){System.out.println(book getAll is running …);ListBook bookList new ArrayListBook();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;}} 使用PostMan进行测试
    测试新增 {type:计算机丛书,name:SpringMVC终极开发,description:这是一本好书 } 测试查询 页面访问处理 拷贝静态页面 将资料\功能页面下的所有内容拷贝到项目的webapp目录下 访问pages目录下的books.html 打开浏览器输入http://localhost/pages/books.html 出现错误的原因? SpringMVC拦截了静态资源根据/pages/books.html去controller找对应的方法找不到所以会报404的错误。 SpringMVC为什么会拦截静态资源呢? 解决方案? SpringMVC需要将静态资源进行放行。
    Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport {//设置静态资源访问过滤当前类需要设置为配置类并被扫描加载Overrideprotected 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/);} }该配置类是在config目录下SpringMVC扫描的是controller包所以该配置类还未生效要想生效需要将SpringMvcConfig配置类进行修改
    Configuration ComponentScan({com.itheima.controller,com.itheima.config}) EnableWebMvc public class SpringMvcConfig { }或者Configuration ComponentScan(com.itheima) EnableWebMvc public class SpringMvcConfig { } 修改books.html页面 !DOCTYPE htmlhtmlhead!– 页面meta –meta charsetutf-8titleSpringMVC案例/title!– 引入样式 –link relstylesheet href../plugins/elementui/index.csslink relstylesheet href../plugins/font-awesome/css/font-awesome.min.csslink relstylesheet href../css/style.css/headbody classhold-transitiondiv idappdiv classcontent-headerh1图书管理/h1/divdiv classapp-containerdiv classboxdiv classfilter-containerel-input placeholder图书名称 stylewidth: 200px; classfilter-item/el-inputel-button classdalfBut查询/el-buttonel-button typeprimary classbutT clickopenSave()新建/el-button/divel-table sizesmall current-row-keyid :datadataList stripe highlight-current-rowel-table-column typeindex aligncenter label序号/el-table-columnel-table-column proptype label图书类别 aligncenter/el-table-columnel-table-column propname label图书名称 aligncenter/el-table-columnel-table-column propdescription label描述 aligncenter/el-table-columnel-table-column label操作 aligncentertemplate slot-scopescopeel-button typeprimary sizemini编辑/el-buttonel-button sizemini typedanger删除/el-button/template/el-table-column/el-tablediv classpagination-containerel-paginationclasspagiantioncurrent-changehandleCurrentChange:current-pagepagination.currentPage:page-sizepagination.pageSizelayouttotal, prev, pager, next, jumper:totalpagination.total/el-pagination/div!– 新增标签弹层 –div classadd-formel-dialog title新增图书 :visible.syncdialogFormVisibleel-form refdataAddForm :modelformData :rulesrules label-positionright label-width100pxel-rowel-col :span12el-form-item label图书类别 proptypeel-input v-modelformData.type//el-form-item/el-colel-col :span12el-form-item label图书名称 propnameel-input v-modelformData.name//el-form-item/el-col/el-rowel-rowel-col :span24el-form-item label描述el-input v-modelformData.description typetextarea/el-input/el-form-item/el-col/el-row/el-formdiv slotfooter classdialog-footerel-button clickdialogFormVisible false取消/el-buttonel-button typeprimary clicksaveBook()确定/el-button/div/el-dialog/div/div/div/div/body!– 引入组件库 –script src../js/vue.js/scriptscript src../plugins/elementui/index.js/scriptscript typetext/javascript src../js/jquery.min.js/scriptscript src../js/axios-0.18.0.js/scriptscriptvar vue new Vue({el: #app,data:{dataList: [],//当前页要展示的分页列表数据formData: {},//表单数据dialogFormVisible: false,//增加表单是否可见dialogFormVisible4Edit:false,//编辑表单是否可见pagination: {},//分页模型数据暂时弃用},//钩子函数VUE对象初始化完成后自动执行created() {this.getAll();},methods: {// 重置表单resetForm() {//清空输入框this.formData {};},// 弹出添加窗口openSave() {this.dialogFormVisible true;this.resetForm();},//添加saveBook () {axios.post(/books,this.formData).then((res){});},//主页列表查询getAll() {axios.get(/books).then((res){this.dataList res.data;});},}})/script /html 6.扩展 运行原理 技术架构 组件介绍 DispatcherServlet前端控制器是整体流程控制的中心由其调用其它组件处理用户的请求有效的降低了组件间的耦合性 HandlerMapping处理器映射器负责根据用户请求找到对应具体的Handler处理器 Handler处理器业务处理的核心类通常由开发者编写描述具体的业务 HandlAdapter处理器适配器通过它对处理器进行执行 View Resolver视图解析器将处理结果生成View视图 View视图最终产出结果常用视图如jsp、html
    源码解析 1、找到源码位置了解调用关系 找到Servlet容器配置类的继承类 AbstractDispatcherServletInitializer 找到 registerDispatcherServlet 方法 根据createDispatcherServlet 方法找到 DispatcherServlet类 DispatcherServlet中找到 doDispatch 方法
    Debug源码 调用 getHandler方法从HandlerMapping中获取处理器链 HandlerExecutionChain 调用 getHandlerAdapter方法从处理器链中获取处理器适配器 HandlerAdapter 调用 处理器适配器方法 handle 执行处理器返回ModelAndView 调用processDispatchResult方法解析返回值 ModelAndView ! null 调用视图解析器 viewResolver ModelAndView null 不再调用视图解析器加上ResponseBody后不再走视图解析器