Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架 ,从⼀开始就包含在 Spring 框架中。它的 正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring
MVC"。
Servlet 是⼀种实现动态⻚⾯的技术. 准确来讲Servlet是⼀套 Java Web 开发的规范,或者说是⼀套 Java Web 开发的技术标准 . 只有规范并不能做任何事情,必须要有⼈去实现它. 所谓实现 Servlet 规 范,就是真正编写代码去实现 Servlet 规范提到的各种功能,包括类、⽅法、属性等.
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构设计模式,它把软件系统分 为模型、视图和控制器三个基本部分。

1. 打开Idea,创建项目时选择Spring Boot,在选择Type时选择Maven

2. 选择Spring Boot版本,不建议选择带有SNAPSHOT的版本,该版本不稳定可能会更新,选择Web,勾选Spring Web

3. 创建后项目文件目录如下:

里面有用的是src和pom文件,其他可以删掉,如果要打开别人的项目要将.idea删掉,因为那是别人idea的配置信息,不一定适合自己的配置。
Spring框架的一大特点就是大量使用注解,其中网络路径的访问使用@RequestMapping来进行设置。
@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/hello")
public String hello() {
return "hello SpringBoot";
}
}设置该注解后我们再启动程序,我们就可以通过访问链接http://localhost:8080/input/hello来运行方法。结果:

该注解既可以修饰类也可以修饰方法,方法最终的访问路径是 类+方法 的路径,但是此路径是唯一的不允许产生重复,否则运行时会报错。
@RestController作用 告诉程序,在查找路径的时候要扫描这个程序,这是为了避免在查找路径的时候扫描一些其他无关的程序,该作用是从扫描的就从所有代码缩小到一小部分代码,提高识别的效率,如果不写该注解网络路径将会无法访问。
@RequestMapping是默认不限制访问方法的,我们可以通过参数进行限制。
@RequestMapping(value = "/hello",method = RequestMethod.POST)如上述设置后该方法将只能通过POST方法进行访问,该参数是一个数组类型,可以传入多个参数。
修改该注解后,此时我们再使用浏览器访问该方法,就会产生405报错,这是因为浏览器默认使用GET方式进行访问,该方法不允许GET,因此返回了405。

和@RequestMapping注解类似的注解还有: @GetMapping:只能使用GET方式访问,不能修改方式参数,其他功能一致。 @PostMapping:只能使用POST方式访问,不能修改方式参数,其他功能一致。 ..............
@RequestParam用于从查询字符串中获取变量,该注解作用于参数上。
该注解有三个参数: value:要查询字符串中变量的名称,默认为空字符串。 defaultValue:没有找到该变量时的值,默认为空字符串。 required:一个布尔类型的值,true表示请求时必须带含有value名称的查询字符串,否则无法访问该方法,false表示不必须带有,该参数默认为true。
@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/t4")
public String t4(@RequestParam String account) {
return "account=" + account;
}
}此时我们启动程序后,访问链接http://localhost:8080/input/t4?account=123
结果:

该注解会将查询字符串中名称为account的值自动赋值给该变量,当该注解没有设置value值时,两者的名称必须一致,否则无法正确赋值。
@RequestMapping("/input")
@RestController
public class hello {
public String t4(@RequestParam("aaa") String account) {
return "account=" + account;
}
}当注解设置了value值时(只有一个参数时默认是value),查询字符串中的名称就必须是该值,不能再是account。
链接:http://localhost:8080/input/t4?aaa=abc
结果:

设置该参数的作用是: 将接受到的前端参数在后端重命名为其他名称,这是为了保证前端的保密性也保证了后端代码的可读性。
当我们不设置required值时,默认该参数是一个必须传入的值,我们依旧使用上一个的代码作为案例,此时我们不再传入aaa值,返回的就是一个400的错误信息。
链接:http://localhost:8080/input/t4

解决这个问题有两种方案,一种是将required设为false,另一种是设置默认值defaultValue。
@RequestMapping("/input")
@RestController
@RequestMapping("/t4")
public String t4(@RequestParam(value = "aaa", required = false) String account) {
return "account=" + account;
}
}结果:

@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/t4")
public String t4(@RequestParam(value = "aaa", defaultValue = "三必回") String account) {
return "account=" + account;
}
}结果:

数组的传递和上面的方法类似,但是基础类型数组可以选择不添加@RequestParam注解,这是框架内建的约定,但是为了统一以及便捷性推荐加上注解。
@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/t5")
public String t5(String[] list) {
return "list=" + Arrays.toString(list);
}
}链接:http://localhost:8080/input/t5?list=11&list=12&list=abc
结果:

对于集合来说,@RequestParam注解不可以省略,否则无法将多个值组装成集合。
@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/t5")
public String t5(@RequestParam List<Integer>list) {
return "list=" + list;
}
}链接:http://localhost:8080/input/t5?list=11&list=12&list=13
结果:

@RequestBody 主要用于接收 HTTP 请求体中的数据,通常这些数据是 JSON 或 XML 格式(大多数情况下是 JSON),然后 Spring 会根据请求的 Content-Type(比如 application/json)将其自动转换为 Java 对象。
假设对象结构为:
public class UserInof {
public String name;
public Integer age;
public String gender;
@Override
public String toString() {
return "UserInof{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/t6")
public String t6(@RequestBody UserInof userInof) {
return userInof.toString();
}
}此时我们借用Postman工具在Body中输入json数据:

结果:

传入json格式的数据,spirng会自动转换成对象的格式,传参必须是一一对应的,顺序无要求,但是名称要一致。
@PathVariable 用于获取 RESTful 风格 URL 中的动态路径参数。也就是说,当你的 URL 中包含了变化的值(通常用大括号 {} 包起来),你可以使用 @PathVariable 将这些值绑定到你的方法参数中。
@RequestMapping("/input")
@RestController
@RequestMapping("/article/{id}")
public String article(@PathVariable Integer id) {
return "id=" + id;
}
}此时我们访问链接:http://localhost:8080/input/article/10023
结果:

他会根据你输入的路径去自动寻找该变量对应的值,在默认情况下他是一个必传的,我们同样可以使用require来设置为非必传参数,同时我们也可以对变量进行重命名。
@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/article/{abc}")
public String article(@PathVariable(value = "abc", required = false) Integer id) {
return "id=" + id;
}
}链接:http://localhost:8080/input/article/10023
结果:

@RequestPart是Spring MVC中用于处理multipart/form-data请求的注解,主要用于文件上传和复杂数据绑定场景,该注解同样也可以进行重命名。
@RequestMapping("/input")
@RestController
public class hello {
@RequestMapping("/file")
public String FilePut(@RequestPart("file11") MultipartFile file) {
System.out.println(file.getOriginalFilename());
return "yes";
}
}其中getOriginalFilename方法是获取其原始文件名字。
使用Postman工具传入文件:

idea结果:

@Controller 是 Spring MVC 中传统的注解,用于标识一个类为 控制器,通常用于 返回视图(比如 HTML 页面)
@RequestMapping("/respose")
@Controller
public class ResposeDemo {
@RequestMapping("/html")
public String resHtml() {
return "/index.html";
}
}当我们访问这个URL的时候,Spring会先从resources/static文件目录下寻找index.html这个文件。

如果存在就以视图的形式返回这个文件。
显然我们是存在这个文件的,因此此时我们的代码会返回正确的html文件:

我们的返回的数据相当于是视图文件的名称,如果没有找到就会返回404 not found。
此时,我们故意将返回改错,显然index是一个错误的文件名称。
@RequestMapping("/html")
public String resHtml() {
return "/index";
}结果:

在请求访问时我们使用的@RestController是 Spring 4.0 引入的,它是@ResponseBody和@Controller注解的组合,也就是说:
@RestController = @Controller + @ResponseBody(表示返回数据)它只会返回数据而不是HTML页面。
@RequestMapping("/respose")
@RestController
public class ResposeDemo {
@RequestMapping("/html")
public String resHtml() {
return "/index.html";
}
}对于同样的代码,我们将注解修改为@RestController注解,此时我们的结果就会是纯粹的文本字符:

总的来说: @Controller返回的是一个视图,它会根据返回值先去寻找这个视图,如果没有就返回404。 @RestController返回的是数据,它没有寻找的过程,你给它什么它就给你返回什么。
如果一个类只需要返回数据的方法,使用@RestController注解。
如果一个类只需要返回页面的方法,使用@Controller注解。
如果一个类即要返回页面的方法,又要返回数据的方法,只能使用@Controller注解。
上述我们讲到@RestController = @Controller + @ResponseBody(表示返回数据)。
因此如果@Controller想要返回数据只需要加上一个@ResponseBody注解即可。
@RequestMapping("/respose")
@Controller
public class ResposeDemo {
//返回html页面
@RequestMapping("/html")
public String resHtml() {
return "/index.html";
}
//返回字符串
@ResponseBody
@RequestMapping("/data")
public String returnData() {
return "index.html";
}
}对于字符串类型的数据,返回的数据默认是以html的格式进行解析的。
例如我们返回一个含有html标签的字符串。
@RequestMapping("/respose")
@Controller
public class ResposeDemo {
@ResponseBody
@RequestMapping(value = "/data1")
public String returnData1() {
return "<h1>index.html<h1>";
}
}此时显示的结果就是使用了标签的文本:

如果我们想要设置返回类型为纯文本,需要对@RequestMapping的produces参数进行设置。
@RequestMapping(value = "/data1", produces = "text/plain")
public String returnData1() {
return "<h1>index.html<h1>";
}此时的结果就是纯文本了:

除了text/plain类型外,常用的类型还有:
text/html : HTML格式 text/plain :纯文本格式 text/xml : XML格式 image/gif :gif图片格式 image/jpeg :jpg图片格式 image/png:png图片格式
返回对象的时候,会默认返回json格式的数据,并不需要额外的设置。
@ResponseBody
@RequestMapping(value = "/json")
public UserInof returnJson() {
UserInof userInof = new UserInof();
userInof.name = "lyf";
userInof.gender = "n";
userInof.age = 1;
return userInof;
}结果:

除了上述的设置外,我们还可以通过HttpServletResponse来设置更多的内容。
HttpServletResponse是servlet原生的类,在功能上更加灵活,但是相对没有那么简洁。
设置响应头:
@ResponseBody
@RequestMapping(value = "/header")
public String header(HttpServletResponse response) {
response.setHeader("header", "111");
return "别看我,看头";
}结果

设置状态码:
@ResponseBody
@RequestMapping(value = "/json1")
public UserInof returnJson1(HttpServletResponse response) {
response.setStatus(404);
return userInof;
}其他设置:
