学习目标
第一章-常用注解【重点】
知识点-常用的注解
1. 目标
2. 路径
- @RequestParam 【重点】
- @RequestBody 【重点】
- @PathVariable 【重点】
- @RequestHeader【重点】
- @CookieValue【了解】
3. 讲解
3.0 环境准备
3.0.1 导入依赖
<dependencies>
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--jsp-api-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!--servlet-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
</dependencies>
3.0.2 定义两个页面
- index.jsp
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/9/10
Time: 8:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>这是首页~!</h2>
</body>
</html>
- success.jsp
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/9/10
Time: 8:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>这是成功的页面~!</h2>
</body>
</html>
3.0.3 springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.itheima"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:default-servlet-handler/>
</beans>
3.0.4 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--配置前端控制器 DispatcherServlet-->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--springmvc已经定义好了过滤器,可以帮助我们解决post请求,中文乱码的问题,我们只需要配置即可-->
<filter>
<filter-name>char</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--设置编码,通过初始化参数来设置编码-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>char</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3.1 @RequestParam【重点】
3.1.1 使用说明
-
作用:
- 可以对浏览器请求做出参数上的要求,要求一定要有指定名字的参数,如果没有,就报错!
- 可以把请求提交上来的参数赋值给方法的形参。
-
属性
value: 要求携带的参数名字
required:请求参数中是否必须提供此参数。 默认值: true。表示必须提供,如果不提供将报错。defaultValue:默认值
3.1.2 使用示例
- Controller01.java
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/*
常用的注解:
*/
@Controller
public class Controller01 {
/*
@RequestParam:
作用: 要求客户端来访问的时候,一定要携带指定名称的参数,否则报错!
步骤:
1. 在方法参数的前面打注解 @RequestParam
属性:
name|value : 用来指定携带的参数名称,如果不指定,那么就以参数名为参考标准。
required: 表示是否一定要携带参数,默认值是true,
defaultValue: 默认值
*/
@RequestMapping("/requestParam")
public String requestParam(@RequestParam(value="abc" , required = false , defaultValue = "张三") String username , @RequestParam String password){
System.out.println("username = " + username);
System.out.println("password = " + password);
return "success";
}
}
@RequestParam 只能用于接收 url 的传参 ?name=xxx, form表单的提交。
无法接收提交的json数据(contentType=application/json)
3.2 @RequestBody【重点】
3.2.1 使用说明
-
作用
- 用于获取请求体内容。 直接使用得到是 key=value&key=value...结构的字符串。【不常用】
- 把获得json类型的数据转成JavaBean对象(后面再讲)【推荐】
**注意: get 请求方式不适用。 **
-
属性
required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值为 false, get 请求得到是 null。
- @RequestBody 不能使用get请求, 在Controller的方法参数里,@RequestBody它只能出现一次!
- 匹配json数据的获取,例如:request.getInputStream()
3.2.2 使用实例
- index.jsp 页面 追加以下内容
<h2>使用@RequestBody获取请求体:</h2>
<form action="/requestBody01" method="post">
用户名: <input type="text" name="username"/><br/>
密码: <input type="text" name="password"/><br/>
<input type="submit">
</form>
- Controller01.java
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/*
常用的注解:
*/
@Controller
public class Controller01 {
/*
@RequestBody
作用:
1. 可以获取表单提交上来的请求体,只有post请求才有请求体,get请求是没有请求体【不常用】
拿到的是一个字符串: username=admin&password=123456;
2. 可以接收页面提交上来的json数据,封装到JavaBe里面【常用】
步骤:
1. 方法参数的前面打上注解 @RequestBody,springmvc就会把请求体赋值给方法的参数。
*/
@RequestMapping("/requestBody01")
public String requestBody01(@RequestBody String body) throws UnsupportedEncodingException {
System.out.println("body = " + body);
/*
页面提交中文的时候,默认情况下,浏览器会对内容进行编码,使用URLEncoder.encode("张三","utf-8");
6张三7 ----URLEncoder.encode("张三","utf-8")-----6%E5%BC%A0%E4%B8%897
如果我们希望看到正常的张三:
1. 必须要设置过滤器,真正的解决中文乱码的问题。
2. 对这份数据解码即可:
6%E5%BC%A0%E4%B8%897 ----------URLDecoder.decode("6%E5%BC%A0%E4%B8%897", utf-8);
*/
String data = URLDecoder.decode(body, "utf-8");
System.out.println("data = " + data);
return "success";
}
}
3.2.3 接收json数据
需求描述
- 客户端发Ajax请求,提交json格式的数据
- 服务端接收json格式的数据,直接封装成User对象
前提条件
- pom.xml中添加jackson的依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
- springmvc.xml中,增加配置静态资源的处理
因为发请求,需要ajax的支持。
<!--配置静态资源的处理-->
<mvc:default-servlet-handler/>
需求实现
- index.jsp 添加以下内容
<h2>使用@RequestBody来获取json数据</h2>
<input type="button" onclick="sendJSON()" value="点我发送JSON数据"/>
<script src="js/axios-0.18.0.js"></script>
<script>
function sendJSON(){
//1. 定义一份json数据
var data = {"username":"admin" , "password":"123456"};
//2. 使用axios发起异步请求
axios.post("/requestBody02" , data);
}
</script>
- Controller01
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/*
常用的注解:
*/
@Controller
public class Controller01 {
/*
@RequestBody:
接收页面提交上来的json数据,封装到JavaBean对象身上。
步骤:
1. 前端页面必须提交的是一份json数据
2. 添加进来jackson-databind的依赖
如果不加依赖,会报错: 415 Unsupported Media Type
3. 定义一个JavaBean,属性名字不能乱写,必须和json里面的KEY一样。
4. 在Controller方法参数的前面加上注解@RequestBody
如果不打注解,那么得到都是null.
*/
@RequestMapping("/requestBody02")
public String requestBody02(@RequestBody User user ) {
System.out.println("user = " + user);
return "success";
}
}
3.3 @PathVariable【重点】
3.3.1 使用说明
-
作用:
用于截取请求地址(url)里面的某些部分的数据。这个需要配合RestFul风格来说明
以前删除用户: localhost:82/deleteUser?id=3 restFul : localhost:82/delete/3
-
属性:
value: 用于指定 url 中占位符名称。
required:是否必须提供占位符。
- 场景:获取路径中的参数,与restful编程风格一起,通常微服架构中使用
3.3.2 使用实例
- index.jsp 页面添加以下内容
<h2>使用@PathVariable来获取地址中的参数</h2>
<a href="/delete/1">点我发请求</a>
<a href="/delete02/30/40">点我发请求2</a>
- Controller01.java
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/*
常用的注解:
*/
@Controller
public class Controller01 {
/*
现在以 按照id来删除用户举例:
以前的写法: localhost:82/delete?id=1
restFul: localhost:82/delete/1
@PathVariable:
作用: 用来截取地址栏中的参数,赋值给方法的形参
步骤:
1. 在映射地址里面使用 {占位符名字} 来占位,表示匹配这个位置的数据
2. 在方法参数的前面加上注解 @PathVariable("占位的名字")
属性:
name | value : 用来指定|设置 占位符的名称。
如果name和value不写,只有一种情况可以不写,就是占位符的名字和方法的参数名字一样!
*/
@RequestMapping("/delete/{a}")
public String pathVariable(@PathVariable(value="a") int id) {
System.out.println("id = " + id);
return "success";
}
@RequestMapping("/delete02/{id}/{id2}")
public String pathVariable02(@PathVariable int id , @PathVariable int id2) {
System.out.println("id = " + id);
System.out.println("id2 = " + id2);
return "success";
}
}
3.4 @RequestHeader【重点】
3.4.1 使用说明
- 作用:
获取指定名字的请求头数据,赋值给方法参数。 - 属性:
value:提供消息头名称
required:是否必须有此消息头 , 默认值是true - 从请求头中获取参数,鉴权(token 畅购open auth 2.0 jwt token) Authorization
3.4.2 使用实例
- index.jsp 页面 添加以下内容
<h2>使用@ReqeustHeader来获取请求头的数据</h2>
<a href="/requestHeader">点我发请求</a>
- Controller01.java
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/*
常用的注解:
*/
@Controller
public class Controller01 {
/*
@RequestHeader:
作用: 用来获取指定名称的请求头数据,赋值给方法的参数
*/
@RequestMapping("/requestHeader")
public String requestHeader(@RequestHeader("User-Agent") String data) {
System.out.println("data = " + data);
return "success";
}
}
3.5 @CookieValue【了解】
3.5.1 使用说明
-
作用:
用于把指定 cookie 名称的值传入控制器方法参数。
-
属性:
value:指定 cookie 的名称。
required:是否必须有此 cookie, 默认值是:true
3.5.2 使用实例
- index.jsp 页面添加以下内容
<h2>使用@CookieValue来获取Cookie的值</h2>
<a href="/cookieValue">点我发请求</a>
- Controller01.java
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/*
常用的注解:
*/
@Controller
public class Controller01 {
/*
@CookieValue
作用: 用来获取指定名称的cookie的值,赋值给方法的形参。
属性:
name&value : 指定cookie的名字!
JESSIONID:
1. 这是session作用域的id的名称,它会存放到cookie里面去。
2. 当我们打开首页的时候,访问的是index.jsp ----背后会被翻译成========> Servlet
3. 在这个翻译成的servlet里面,它会创建session对象,并且把session的地址存放到cookie里面去。
存放的cookie的KEY 叫做: JSESSIONID.
*/
@RequestMapping("/cookieValue")
public String cookieValue(@CookieValue("JSESSIONID") String data) {
System.out.println("data = " + data);
return "success";
}
}
4. 小结
- 这几个注解都使用作用在方法的参数上,不是写在方法上。他们或多或少都是对客户端提交的数据有这样或者那样的要求
- @RequestParam : 要求客户端必须要携带指定的参数。
- @RequestBody: 要求必须有请求体,一般它是作用于 页面提交上来的json数据,转化成 javabean对象
- @PathVariable : 路径变量,配合RestFul风格使用,用于截取地址里面的数据
- @RequestHeader: 用来获取的指定的请求头数据,赋值给方法形参
- @CookieValue: 用来获取的cookie数据,赋值给方法的形参。
第二章-响应数据和视图【重点】
知识点-返回页面视图
1.目标
2.路径
- 请求转发
- 返回页面文件名字符串 success 逻辑视图
- 返回字符串关键字forward:物理视图
- 返回ModelAndView 对象
- 重定向
- 返回字符串关键字redirect:
- 转发与重定向的区别
3.讲解
3.1 返回页面文件名
controller方法返回的字符串会被解析成页面视图(即:页面的地址路径)
3.1.1. 返回逻辑视图名称
- 方法返回的字符串,和视图解析器里的前缀、后缀拼接得到真实路径,再进行跳转
- 不管是物理视图(完整的写法)还是逻辑视图(简写),默认采用的都是请求转发跳转
3.1.2. 返回带前缀的物理视图
- 请求转发:
forward:/success.jsp
- 重定向:
redirect:/success.jsp
- 注意:如果带有
forward
或者redirect
,那么路径必须是完整的真实路径 , 不受视图解析器影响
使用示例
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/*
响应视图: 跳转页面
1. springmvc跳转页面的时候,默认是采用请求转发去跳转
2. 跳转的写法:
2.1 逻辑视图
只要写上页面的名字即可
2.2 物理视图
要写完整的页面的路径地址才行。
a. 不带前缀的写法
会受到视图解析器的影响
b. 带前缀的写法
不会受到视图解析器的影响
forward:物理视图路径 表示使用请求转发跳转
redirect:物理视图路径 表示使用重定向跳转
*/
@Controller
public class Controller02 {
//逻辑视图跳转: 只要写上视图的名字即可
@RequestMapping("/page01")
public String page01(){
System.out.println("page01...");
return "success";
}
//物理视图跳转: 写上视图的完整路径
@RequestMapping("/page02")
public String page02(){
System.out.println("page02...");
return "/success.jsp";
}
//物理视图跳转:加上前缀 forward:
// forward: 表示 使用请求转发跳转,并且它不会受到视图解析器的影响
@RequestMapping("/page03")
public String page03(){
System.out.println("page03...");
return "forward:/success.jsp";
}
//物理视图跳转,加上前缀 redirect:
// redirect: 表示使用重定向跳转,并且不会受到视图解析器的影响
@RequestMapping("/page04")
public String page04(){
System.out.println("page04...");
return "redirect:/success.jsp";
}
}
3.2 请求转发并传递数据【重点】
ModelAndView
是SpringMVC提供的组件之一,其中Model
,模型,用于封装数据(Springmvc会把数据放到了request域中)View
,视图,就是页面,用于展示数据
- 如果我们设置了视图名称,并且封装了数据模型,SpringMVC会:
- 把Model的数据放到request域对象中,然后请求转发到指定的视图(页面)
- 我们可以视图页面中获取数据显示出来
**使用示例 **
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/*
跳转页面,并且携带数据到页面上显示!
1. 使用ModelAndView来封装数据和视图
*/
@Controller
public class Controller03 {
//1. 自己new ModelAndView对象
@RequestMapping("/page05")
public ModelAndView page05(){
//1. 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
//2. 装数据: 会把这份数据保存到request作用域里面
mv.addObject("username", "page05");
//3. 装视图 : 会受视图解析器的影响。
mv.setViewName("success");
//4. 返回mv;
return mv ;
}
//在参数里面定义ModelAndView,要求springmvc传递进来对象
@RequestMapping("/page06")
public ModelAndView page06(ModelAndView mv){
//2. 装数据: 会把这份数据保存到request作用域里面
mv.addObject("username", "page06");
//3. 装视图 : 会受视图解析器的影响。
mv.setViewName("success");
//4. 返回mv;
return mv ;
}
//参数传递进来Model对象,封装数据,使用返回值返回视图。
@RequestMapping("/page07")
public String page07(Model model){
//装数据
model.addAttribute("username","page07");
//4. 返回mv;
return "success" ;
}
//========================可以使用以前的request对象或者session对象来存值===============
@RequestMapping("/page08")
public String page08(HttpServletRequest req){
//装数据
req.setAttribute("username", "page08");
//4. 返回mv;
return "success" ;
}
@RequestMapping("/page09")
public String page09(HttpSession session){
//装数据
session.setAttribute("username", "page09");
//4. 返回mv;
return "success" ;
}
//是用重定向的方式跳转页面
@RequestMapping("/page10")
public String page10(HttpSession session){
//装数据
session.setAttribute("username", "page10");
//4. 返回mv;
//return "success" ; //请求转发方式跳转
return "redirect:/success.jsp" ; //重定向方式跳转!
}
}
- 在index.jsp视图页面中,取出数据显示出来
<h2>这是成功的页面 ${username}</h2>
4.小结
-
返回页面文件名
- 返回逻辑视图
- 方法返回的字符串,和视图解析器里的前缀、后缀拼接得到真实路径,再进行跳转
- 是请求转发跳转
- 返回带前缀的物理视图 (不受视图解析器的影响)
- 请求转发:
forward:/success.jsp
- 重定向:
redirect:/success.jsp
- 请求转发:
- 返回逻辑视图
-
方法返回
ModelAndView
public ModelAndView jump(){
ModelAndView mav = new ModelAndView();
mav.setViewName("视图名称");
mav.addObject("数据名称", "值");
return mav;
}
public ModelAndView jump(ModelAndView mav){
mav.setViewName("视图名称");
mav.addObject("数据名称", "值");
return mav;
}
- 方法返回String:视图名称
public String jump(Model model){
model.addAttribute("数据名称", "值");
return "视图名称";
}
知识点-返回数据【重要】
1.目标
2.路径
- 直接返回字符串
- 返回json数据【重点】
3. 讲解
3.1 直接响应字符串【了解】
- 两种方式
- 使用Servlet原生的
response
对象,返回响应数据 response.getWrite().write("xxxx"); - 方法上使用
@ResponseBody
注解,springmvc就会把方法的返回值当成字符串来看待,不会再识别成页面的地址路径
- 使用Servlet原生的
3.1.1 使用示例
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
返回数据给页面: 字符串 & JSON
*/
@Controller
public class Controller04 {
/*
返回字符串: 使用response对象, 把字符串写出去!
*/
@RequestMapping("/returnStr01")
public void returnStr01(HttpServletResponse resp) throws IOException {
resp.getWriter().write("returnStr01...");
}
/*
返回字符串:
1. 直接在方法的返回值返回字符串
2. 要加上注解 @ResponseBody, springMVC会把返回值看成是字符串,否则会被看成是页面的路径
*/
@ResponseBody
@RequestMapping("/returnStr02")
public String returnStr02(){
return "returnStr02...";
}
}
3.1.2 拓展
- 如果使用
@ResponseBody
响应的中文字符串,即使配置了CharacterEncodingFilter
,也会有乱码
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
返回数据给页面: 字符串 & JSON
*/
@Controller
public class Controller04 {
//=================返回字符串(包含中文)=========================
/*
使用@ResponseBody 返回字符串的时候,如果返回中文字符串,即使设置了编码过滤器,那么页面看到的仍然是乱码!
解决:
有两种办法解决:
1. 使用标准的写法来设置编码,在springmvc.xml中设置
只要配置了,那么对全局都是有效的!
2. 使用投机取巧的办法!
在requestMapping里面使用produces来设置编码,仅对当前的方法生效!
*/
@ResponseBody
@RequestMapping("/returnStr03")
public String returnStr03(){
return "中文03...";
}
// 在requestMapping里面使用produces来设置编码,仅对当前的方法生效!
@ResponseBody
@RequestMapping(value = "/returnStr04", produces = "text/html;charset=utf-8")
public String returnStr04(){
return "中文04...";
}
}
- 解决方法:在
springmvc.xml
里配置如下:- 配置SpringMVC的
StringHttpMessageConverter
进行字符串处理转换,设置采用utf-8
字符集
- 配置SpringMVC的
<mvc:annotation-driven>
<!--设置消息转换器-->
<mvc:message-converters>
<!--设置从后端给前端返回的字符串的消息转换器,设置它的转换的编码-->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="utf-8"/>
<!--针对不同的数据类型,设置不同的编码-->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=utf-8</value>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
3.2 返回json数据【重要】
- 两种方式介绍
- 自己把JavaBean对象转换成json格式的字符串,响应给客户端
- 方法返回JavaBean对象,使用
@ResponseBody
注解Springmvc帮我们转换成json格式 【推荐】
3.2.1 前提条件
- 在pom.xml中导入依赖:
jackson-databind
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
- springmvc.xml中开启mvc注解开关
<mvc:annotation-driven/>
3.2.2 使用示例
package com.itheima.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/*
返回json字符串
1. 手动把JavaBean和转化成json字符串,然后返回字符串
2. 直接返回javaBean即可
*/
@Controller
public class Controller05 {
// 手动把JavaBean对象转化成Json字符串,返回。
@ResponseBody
@RequestMapping(value = "/returnJson01" , produces = "application/json;charset=utf-8")
public String returnJson01() throws JsonProcessingException {
//1. 构建User
User user = new User("管理员01","123456");
//2. 把这个对象手动转化成Json字符串
ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(user);
return json;
}
/*
1. 直接返回JavaBean,springmvc会把这个JavaBean转化成json字符串返回。
2. 要想使用这种操作,那么必须要在pom.xml里面添加jackson-databind的依赖
*/
@ResponseBody
@RequestMapping("/returnJson02")
public User returnJson02() throws JsonProcessingException {
return new User("管理员02","123456");
}
}
4.小结
- 如果要直接响应数据,使用response对象
public void method1(HttpServletResponse response){
//如果响应普通文本数据
//response.setContentType("text/html;charset=utf-8");
//如果响应json格式的字符串
response.setContentType("application/json;charset=utf-8");
response.getWriter().print("xxxx");
}
- 如果要bean对象 , 使用注解@ResponseBody
如果返回的是json数据,需要添加jackson-databind的依赖!
@RequestMapping("/method2")
@ResponseBody
public User method2(){
return new User();
}
第三章-RestFul【了解】
知识点-介绍
1.目标
2.路径
- RestFul 历史
- 接口结构
3.讲解
3.1 RestFul介绍
3.1.1 概述
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Fielding是一个非常重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。所以,他的这篇论文一经发表,就引起了关注,并且立即对互联网开发产生了深远的影响。
他这样介绍论文的写作目的:
"本文研究计算机科学两大前沿----软件和网络----的交叉点。长期以来,软件研究主要关注软件设计的分类、设计方法的演化,很少客观地评估不同的设计选择对系统行为的影响。而相反地,网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。"
RESTful 是一种设计风格。它不是一种标准,也不是一种软件,而是一种思想。
3.1.2 特点
- 每一个URI(请求地址)代表1种资源;
- 以前我们认为url地址它是一个动作: 增删改查的动作
- localhost:8080/项目名/findAllUser
- lolcahost:8080/项目名/deleteUser?id=3
- rest设计风格认为地址是一种资源,体现的只有名词,而没有动词。
- localhost:8080/项目名/user/3 : 删除id为3
- localhost:8080/项目名/user/3 : 查询id为3
- 以前我们认为url地址它是一个动作: 增删改查的动作
- 客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;、
- 由于地址不能体现出来动作,包含的都是名词,没有动词,那么服务端如何区分出来客户端想要执行的是什么操作呢?
- 采用请求方式来区分 localhost:8080/项目名/user/3
- 新增 ----- post请求
- 查询 ----- get请求
- 删除 ----- delete请求
- 更新 ----- put请求
- 客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息
3.2 接口结构
3.2.1 如何设计接口
-
域名
应该尽量将API部署在专用域名之下。 第三方SDK来说,比较有用。
-
版本
将API的版本号放在url中:http://www.example.com/api/v1.0
-
路径
在RESTful架构中,每个地址代表一种资源(resource),所以地址中不能有动词,只能有名词,而且所用的名词往往与数据库的表名对应。
-
具体操作
对于资源的具体操作类型,由HTTP动词表示。常用的HTTP动词有下面四个(括号里是对应的SQL命令)
GET(SELECT):从服务器取出资源(一项或多项)。 POST(CREATE):在服务器新建一个资源。 PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。 DELETE(DELETE):从服务器删除资源。 还有三个不常用的HTTP动词。 PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。 HEAD:获取资源的元数据。 OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的
3.2.2 示例说明
-
示例
GET /user:列出所有用户
POST /user:新建一个用户
GET /user/{id}:获取某个指定用户的信息
PUT /user:更新某个指定用户的信息(提供该用户的全部信息)
DELETE /user/{id}:删除某个用户
-
原来的方式
http://127.0.0.1/user/find?id=3 GET方法,根据用户id获取数据
http://127.0.0.1/user/update POST方法,用户修改
http://127.0.0.1/user/add POST方法,用户新增
http://127.0.0.1/user/deleteUser?id=3 GET/POST方法,用户根据id删除 -
RestFul方式
http://127.0.0.1/user/{id} GET方法,根据用户id获取数据
http://127.0.0.1/user/{id} DELETE方法,用户根据id删除http://127.0.0.1/user/ GET 方法 查询所有的用户
http://127.0.0.1/user/ PUT方法,用户修改
http://127.0.0.1/user/ POST方法,用户新增
4.小结
- RESTful 是一种设计风格 , 可以用,也可以不用!
- 每一个URI代表1种资源,地址里面只能出现名词,不能出现动词。
- 客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;
案例-最佳实践
1. 需求
2. 分析
- 创建Maven web工程
- 创建Pojo
- 创建Controller ,定义增删改查方法
- 分别使用 get | post | put | delete 来指定方法请求方式
3. 实现
3.1 基本实现
在postman工具里面测试
- User
package com.itheima.bean;
import lombok.Data;
@Data
public class User {
private String username;
private String password;
}
- UserController
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/*
这是用来处理一切与用户有关请求的controller
*/
@Controller
public class UserController {
/*
新增:
以前: localhost:82/addUser GET|POST
restFul : localhost:82/user POST
*/
// @RequestMapping(value = "/user", method = RequestMethod.POST)
@ResponseBody
@PostMapping("/user")
public String add(User user ){
System.out.println("add..." + user);
return "add success...";
}
/*
删除:
以前: localhost:82/deleteUser?id=1 GET
restFul: localhost:82/user/1 DELETE
*/
@ResponseBody
@DeleteMapping("/user/{id}")
public String delete(@PathVariable int id){
System.out.println("delete...id=" + id);
return "delete success...";
}
/*
修改:
以前: localhost:82/updateUser GET|POST
restFul: localhost:82/user PUT
更新的操作比较特殊一些:
springmvc不会从put请求里面拿请求体的数据出来,赋值给方法参数。
所以看到的都是null!
*/
@ResponseBody
@PutMapping("/user")
public String update(User user){
System.out.println("update..." + user);
return "update success...";
}
/*
根据id来查询用户:
以前: localhost:82/findUserById?id=1 GET
restFul: localhost:82/user/1 GET
*/
@ResponseBody
@GetMapping("/user/{id}")
public String findById(@PathVariable int id){
System.out.println("findById..." + id);
return "findById success...";
}
/*
查询所有:
以前: localhost:82/findAll GET
restFul: localhost:82/user GET
*/
@ResponseBody
@GetMapping("/user")
public String findAll(){
System.out.println("findAll..." );
return "findAll success...";
}
}
3.2 拓展【了解】
- HTML页面的form表单的提交方式只有两种: GET 和 POST
- 添加操作: 页面可以使用form表单 ----- 使用POST提交
- 删除操作: 页面是一个超链接 ,点击之后,执行一个JS方法,在JS里面使用: axios.delete() ;
- 修改操作: 页面上有form表单来提交数据====== 不能使用PUT请求!
- 查询操作: 可以在JS方法里面使用: axios.get();
put 请求方式无法提交form表单, GET 和 POST请求可以,为了满足RestFul风格的接口设计,需要做两个工作:
- 页面提交表单的方式还是post, 配置隐藏域,告知SpringMVC,最终处理的请求方式
- 后台还是 put请求方式的方法
- 但是前端的页面提交数据的时候,不能直接把form表单的提交方式设计成的method="delete" | method="put"
- 配置过滤器,使得SpringMVC背后会把post请求转化为 ,对应
DELETE
或者PUT
请求
- spring它是以什么标准来转化的? 它怎么知道要转化哪一个请求的请求方式呢?
- 需要在form表单里面添加一个隐藏域
-
- 页面配置隐藏域
name="_method" 是固定写法 , value 则是最终要使用的请求方式,如果是delete,则写delete 如果是put ,则写put.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
1. 默认情况下,页面的form表单是不允许提交put请求,只能使用GET | POST请求提交
2. 如果真的希望这个form表单的数据,能够提交到put请求的更新方法去,需要做以下的工作
2.1 请求的提交方式,必须设置为: post
2.2 在表单里面添加一个隐藏域: name的值是固定: _method value:就是我们想要提交的请求方式的名字,
如果我们想用put请求提交,就写上put
2.3 在web.xml中,配置过滤器!
--%>
<form action="/user" method="post" enctype="">
<input type="text" name="_method" value="put" hidden/><br/>
用户名:<input type="text" name="username"/><br/>
密 码:<input type="text" name="password"/><br/>
<input type="submit"/>
</form>
</body>
</html>
-
- 添加
HiddenHttpMethodFilter
把post
请求转化成delete
或者put
请求 , 它需要在form表单里面带上隐藏的域, name的名称为 _method , value为真正提交的方法,而提交的方式使用的post , 过滤器会把这个post请求转化成delete请求或者put请求
- 添加
<!--配置过滤器,以便使用put请求提交上来的表单数据,可以获取到-->
<filter>
<filter-name>put</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>put</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--这个过滤器主要是用来识别页面提交的form表单中的隐藏域,然后把表单的请求方式
转化成隐藏域里面设置的请求方式-->
<filter>
<filter-name>hidden</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hidden</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- controller
/*
修改:
以前: localhost:82/updateUser GET|POST
restFul: localhost:82/user PUT
更新的操作比较特殊一些:
springmvc不会从put请求里面拿请求体的数据出来,赋值给方法参数。
所以看到的都是null!
*/
@ResponseBody
@PutMapping("/user")
public String update(User user){
System.out.println("update..." + user);
return "update success...";
}
4. 小结
- 创建Maven web工程
- 创建Pojo
- 创建Controller ,定义增删改查方法
- 分别使用 get | post | put | delete 来指定方法请求方式
第四章-文件上传【重点】
知识点-文件上传
1.目标
2.路径
- 文件上传概述
- 文件上传要求
- 常见的文件上传jar包和框架
3.讲解
3.1 文件上传概述
就是把客户端(浏览器)的文件保存一份到服务器 说白了就是文件的拷贝
3.2 文件上传要求
3.2.1 浏览器端要求(通用浏览器的要求)
- 表单提交方式 post
- 提供文件上传框(组件) input type="file"
- 表单的enctype属性必须为
multipart/form-data
(没有这个属性值的话, 文件的内容是提交不过去的)
3.2.2 服务器端要求
- 要使用request.getInputStream()来获取数据.
- 如果前端页面的form表单提交的编码enctype="
multipart/form-data
" ,那么后端取值,request.getParameter("xxx")受影响。得到的值都是 null
注意:
- 若表单使用了 multipart/form-data ,使用原生request.getParameter()去获取参数的时候都为null
我们做文件上传一般会借助第三方组件(jar, 框架 SpringMVC)实现文件上传.
3.3 常见的文件上传jar包和框架
1. serlvet3.0
2. commons-fileupload : apache出品的一款专门处理文件上传的工具包
3. struts2(底层封装了:commons-fileupload)
4. SpringMVC(底层封装了:commons-fileupload)
4.小结
- 前端三要素
- form表单提交方式为 post,
- encpt=multipart/form-data,
- input type=file
- 使用commons-fileupload, 原生的api处理太复杂了,它帮我们简化了开发
案例-传统文件上传
1.需求
2.分析
2.1 原理介绍
- 如果表单form标签的
enctype="multipart/form-data"
时,request.getParameter
方法将失效- 当
enctype="application/x-www-form-urlencoded"
时,提交的表单数据格式是:name=value&name=value&...
- 当
enctype="multipart/form-data"
时,提交的表单数据格式就变成多部分形式
- 当
- 客户端提交多部分表单时,会把文件内容一并提交:
- 服务端使用
request.getInputSteam()
可以获取到客户端提交数据,包含文件数据- 数据的格式:以指定分隔符隔开了,每一部分是一个表单项的数据
- 分隔符以请求头中,提交到服务端为基准
- 使用指定分隔符,把得到的数据进行分割,然后解析得到其中的每项数据
- 把文件项的数据保存在服务器中
- 服务端使用
2.2 工具包
- 使用第三方jar包
commons-fileupload
, 可以实现更简单的文件上传 commons-fileupload
的maven坐标如下:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
- SpringMVC又对
commons-fileupload
做了再封装,实现文件上传,更加简单了
2.3 具体步骤
- 导入依赖:增加commons-fileupload
- 创建页面,在页面上提供表单:要符合文件上传的三要素
- 编写控制器代码
- 配置 文件解析器
CommonsMultipartResolver
3.实现
- 导入依赖
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
- 创建页面,在页面上提供表单
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/9/10
Time: 15:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>传统文件上传</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
请选择文件:<input type="file" name="uploadFile"/><br>
<input type="submit"/>
</form>
</body>
</html>
- 编写控制器代码
package com.itheima.controller;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
/*
用于处理文件上传
*/
@Controller
public class UploadController {
/*
1. 定义好页面
2. 定义参数,参数的名字不能乱写,必须要写页面name属性的值!
请选择文件:<input type="file" name="uploadFile"/>
3. 为了方便我们拿到文件数据,commons-fileupload里面提供了一个类 MultipartFile
4. 把文件保存到硬盘上!
*/
@RequestMapping("/upload")
public String upload(MultipartFile uploadFile) throws IOException {
//1. 得到原文件名 abc.doc xxx.mp3
String oldName = uploadFile.getOriginalFilename();
//2. 截取后缀
String suffix = oldName.substring(oldName.lastIndexOf(".")); // .doc .mp3
//3. 构建新的文件名
String newName = UUID.randomUUID().toString() + suffix;
//4. 构建文件对象,表示一会文件要保存到这个位置!
File file = new File("D:/"+newName);
//5. 把文件保存到上面的定位的位置去!
uploadFile.transferTo(file);
return "success";
}
}
- 配置
文件解析器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1. 扫描包-->
<context:component-scan base-package="com.itheima"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:default-servlet-handler/>
<!--要想实现文件上传,这里需要配置一个文件解析器 有一个固定的要求:id必须要写成multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--最大可以上传的文件大小,单位是: 字节。 这里是500K-->
<property name="maxUploadSize" value="512000"/>
</bean>
</beans>
4.小结
- 在pom.xml里导入依赖:
commons-fileupload
- 在springmvc.xml里配置文件解析器,bean名称必须是
multipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--maxUploadSize:上传的文件最大尺寸,单位byte-->
<property name="maxUploadSize" value="10240000"/>
<!--maxUploadSizePerFile:每个文件最大的尺寸,单位byte-->
<property name="maxUploadSizePerFile" value="1024000"/>
</bean>
- 在Controller里写代码接收保存文件
//注意:方法形参名称,必须和表单项名称相同
public String upload(MultipartFile file){
file.transferTo(new File("目标文件存储位置"));
return "success";
}
案例-跨服务器文件上传
1.需求
2.分析
2.1 开发中的服务器
- 在实际开发中,为了提高程序效率,我们可以提供多个服务器,每个服务器负责不同的工作。
- 常见的服务器有:
- 应用服务器:部署web应用的服务器,我们安装了Tomcat的电脑
- 数据库服务器:负责数据存取服务,我们安装了MySql的电脑
- 缓存和消息服务器:负责处理高并发访问时的缓存和消息,我们安装了redis的电脑
- 文件服务器:存储文件的服务器
2.2 具体步骤
- 准备一个文件服务器(准备一个Tomcat),允许文件的存取
- 编写程序,提供文件上传功能;使用jersey把上传的文件保存到文件服务器上
3.实现
1. 准备一个文件服务器
-
拷贝一个Tomcat,在其
webspps
文件夹中创建项目(创建一个文件夹),名称为:files
-
打开
conf/web.xml
文件,搜索DefaultServlet
,设置初始化参数readonly
,值为false
-
启动服务器(注意不要端口冲突了)
-
修改tomcat的端口,不要让它是默认的8080端口,否则我们的上传文件的项目无法部署到自己的tomcat
-
Tomcat里files项目的访问地址是:
http://localhost:18080/files
-
2. 编写程序,提供文件上传功能
-
在我们项目中导入
jersey
包的依赖<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.9</version> </dependency>
-
提供页面
<%-- Created by IntelliJ IDEA. User: xiaomi Date: 2021/9/10 Time: 15:20 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h2>跨服务器文件上传</h2> <form action="/upload02" method="post" enctype="multipart/form-data"> 请选择文件:<input type="file" name="uploadFile"/><br> <input type="submit"/> </form> </body> </html>
-
编写控制器的方法,实现文件上传功能
package com.itheima.controller; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; /* 用于处理文件上传 */ @Controller public class UploadController { /* 跨服务器文件上传 1. 当我们这个方法收到浏览器提交上来的文件时,不把这文件保存在自己的电脑上 2. 保存在另一台服务器上。 */ @RequestMapping("/upload02") public String upload02(MultipartFile uploadFile) throws IOException { //1. 得到原文件名 abc.doc xxx.mp3 String oldName = uploadFile.getOriginalFilename(); //2. 截取后缀 String suffix = oldName.substring(oldName.lastIndexOf(".")); // .doc .mp3 //3. 构建新的文件名 String newName = UUID.randomUUID().toString() + suffix; //4. 构建一个客户端对象 Client client = new Client(); //5. 定位位置 WebResource resource = client.resource("http://localhost:18080/files/" + newName); //6. 保存文件 resource.put(uploadFile.getBytes()); return "success"; } }
-
配置文件解析器
<!--要想实现文件上传,这里需要配置一个文件解析器 有一个固定的要求:id必须要写成multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--最大可以上传的文件大小,单位是: 字节。 这里是500K--> <property name="maxUploadSize" value="512000"/> </bean>
4.总结
-
在pom.xml里导入依赖:
commons-fileupload, jersey-client
-
在springmvc.xml里配置文件解析器
-
在Controller里:使用jersey把文件推送保存到文件服务器上
总结:
常用注解:
@RequestParam:
要求要提供指定名称请求参数,把指定名称参数赋值给方法的形参
@RequestBody:
1. 要求要有请求体,可以把请求体赋值给方法的形参 : name=value&name2=value2...
2. 把页面提交的json数据转化成JavaBean
@RequestMapping("/add")
public String add(@RequestBody User user){
}
@PathVariable:
要搭配RestFul使用,用来截取请求地址中的参数。
@RequestHeader:
把指定名字的请求头的数据赋值给方法的参数
@CookieValue:
把指定名字的cookie的数据赋值给方法的参数
响应数据和视图
响应视图
逻辑视图
return "success";
物理视图:
带前缀:
return "forward:/success.jsp";
return "redirect:/success.jsp";
不带前缀: return "/success.jsp";
响应数据和视图
1. ModelAndView对象
2. Model对象
响应数据
1. 返回字符串
2. 返回JSON字符串
@RequestMapping("/findUser")
@ResponseBody
public User findUser(){
return new User("zhangsan","123456");
}
RestFul
1. 所有的请求地址,都应该被看成是一种资源。
2. 只能包含名词,不能出现动词。
3. 要想让服务端能明白客户端想要做什么具体操作,就要搭配请求方式:
新增 == POST
删除 == DELETE
修改 == PUT
查询 == GET
文件上传
传统文件上传
跨服务器文件上传