文章目录
前言
前文已经讲述了 ,Spring的创建与注解的使用 ,还有SpringBoot简化Spring开发的一些工具,这篇博客, 主要讲解SPringMVC的使用
SpringMVC的背景
在Spring的介绍中提过, Spring可以帮助我们简化很多Java代码 , 而SPringMVC就是Spring简化Java Servlet 构建的框架 , 它正式的名称为 Spring WEB MVC, 通常简称SpringMVC
在开发中, MVC指的是Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分
MVC和SpringMVC的关系
MVC是一种实现,而SpringMVC是MVC实现的具体实现
SpringMVC的执行流程
①用户的请求首先到Controller
②然后哦Controller将请求转发给model
③model处理业务并将数据结构给Controller
④Controller将数据给了view引擎
⑤View转换数据生成最终的页面给用户
-
Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
-
View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
-
Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据, 控制⽤户输⼊,并向模型发送数据。
现在绝⼤部分的 Java 项⽬都是基于 Spring(或 Spring Boot)的,⽽ Spring 的核⼼就是 Spring
MVC。
在上文中,创建 Spring Boot 项⽬时,我们勾选的 Spring Web 框架其实就是 Spring MVC 框架
SpringMVC学那些功能
上面说了 , SpringMVC是Servlet的框架, 而Servlet中也有三个核心类 , 分别是 HttpServlet , HttpServletRequest ,HttpServletResp , 这三个核心类 ,在MVC中同样是重点 , 只不过运用方式变更了而已,基本原理还是Servlet那一套
①链接的功能 - 用户和程序之间链接功能
②获取参数的功能: 执行业务逻辑,获取参数
③输出数据的功能:执行业务逻辑, 将结果输出给用户
创建SpringMVC
注意:所有URL:全部小写, 多个单词用下划线分割
① 创建一个SpringBoot 项目
② 在选择导入的依赖出选择 , SpringWeb, 这个 就是SpringMVC(必选) 的框架 , 选择Lombok 帮助我们简化代码编写(可选) , SpringBoot DevTools (可选) 实现Spring热部署 .
热部署 : 不用咱们每次都重新启动项目, 一般等个3S 左右的时间, 修改后的项目就自动运行了
连接的功能
① @RequestMapping 即可修饰类,也可以修饰⽅法,(反正浏览器要一一对应路径)
当同时修饰类和⽅法时,访问的地址是类 + ⽅法。
通过在类上加上这个注解 ,代表的是一级路由 , 在方法上加上代表的是二级路由 ,通过浏览器访问的时候, 要路径一致才可以访问到
启动项目,然后从浏览器访问该路径,即可得到结果
package com.example.demo.comtroller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller // 让Spring框架启动时加载
@ResponseBody // 返回的是非页面的数据
@RequestMapping("/ca")//一级路由
public class CalcController {
@RequestMapping("/calc")//二级路由注册
public String calc() {
System.out.println("Hello World");
// if (num1 == null || num2 == null) return "参数错误";
// return "结果=" + (num1 + num2);
return "Hello World";
}
}
效果图
注: @RequestMapping 还可以指定请求访问方法 如下:
@RequestMapping(value = “/hi”, method = RequestMethod.POST)
注 : @RequestMapping 不指定访问方法时, 默认是GET方法和PSOT都能用
还可以如下方式指定 , 用指定方法写路径
@GetMapping("/hi")
public String sayHi(String name, Integer v) {
return "Hi," + name + " |v=" + v;
}
@GetMapping("/num")
public String getNum(Integer num) {
return "num=" + num;
}
② 使用GetMapping : 实现HTTP链接 ,但只支持get链接的请求
package com.example.demo.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController2 {
@GetMapping("sy2")
public String say(){
return "hello world - > get";
}
}
③使用PostMapping :效果和使用方法与GEtMapping一致,就不写了
①直接 传参
1 : 在SpringMVC ,支持直接传递参数来访问 如下
@Controller // 让Spring框架启动时加载
@ResponseBody // 返回的是非页面的数据
//@RequestMapping("/ca")
public class CalcController {
@RequestMapping("/calc")//路由注册
public String calc(Integer num1 ,Integer num2) {
if (num1 == null || num2 == null) return "参数错误";
return "结果=" + (num1 + num2);
}
用问号来传参
②接受普通对象参数化来访问的
package com.example.demo.comtroller;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
@RequestMapping("/resp")
public class RespController {
@RequestMapping("/hi")
public String sayHi(User user) {
System.out.println("id"+user.getId());
System.out.println("name"+user.getName());
return "/index.html";
}
}
package com.example.demo.model;
import lombok.Data;
@Data
public class User {
private int id;
private String name;
private int password;
private int age;
}
package com.example.demo.Controller;
import com.example.demo.model.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/add")
public User add(User user){
return user;
}
}
注:返回对象,前端那边接受的是JSON
③接受JSON对象
@RequestBody只能修饰参数,不能用来修饰方法与类
@PostMapping("/show-json-user")
public String showJSONUser(@RequestBody User user) {
return user.toString();
}
④接受前后端名称不一样的
注意使用了RequestParam,代表这个参数是必传的, 不传就会报错,也就是必须传n
或者在RequestParam设置成非必传的
@RequestParam(value = “n”,required = false)
@RequestMapping("/name")
public String name(@RequestParam("n") String name){
return name;
}
@RequestMapping("/login/{username}/{password}")
public String login(@PathVariable("username") String username,
@PathVariable("password") String password) {
return username + ":" + password;
}
还可以设置是否参数必传 和非必传的情况
@GetMapping("/show-time")
// public String showTime(String t, String t2) {
public String showTime(@RequestParam(value = "t", required = false) String startTime,
@RequestParam("t2") String endTime) {
// startTime/entTime...
return "开始时间:" + startTime + " | 结束时间:" + endTime;
}
⑤实现上传文件
注意: 上传文件一定用PSOT方式
用postMan模拟前端提交文件 - > 名称一定要等于@RequestPart(“myfile”)中的名字
@RequestMapping("/upfile")
//上传文件
public String upfile(@RequestPart("myfile") MultipartFile file) throws IOException {
String path = "D:\\Generate\\img.png";
// 保存文件
file.transferTo(new File(path));
return path;
}
生成唯一的名称使用UID(要唯一的名称就是用UID), + 得到源文件的后缀名
UUID就是全球唯一ID
@RequestMapping("/myupfile")
public String myUpFile(@RequestPart("myfile") MultipartFile file) throws IOException {
// 根目录
String path = "D:\\Generate\\";
// 根目录 + 【唯一的文件名】
path += UUID.randomUUID().toString().replace("-", "");
// 根目录 + 唯一的明文件 + 【文件的后缀】 ex:.png
path += file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
//
file.transferTo(new File(path));
return path;
}
获取Session / cookie / header
通过HttpServletRequest和HttpServletResponse
// Spring MVC(Spring Web) 内置了 HttpServletRequest 和 HttpServletResponse
@GetMapping("/getparam")
public String getParam(HttpServletRequest req) {
return req.getParameter("username");
}
还可以通过注解来获取Cookice 和Session
@RequestMapping("/getua")
public String getUA(@RequestHeader("User-Agent") String userAgent) {
return userAgent;
}
@RequestMapping("/setsess")
public String setSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("userinfo", "userinfo");
return "Set Session Success.";
}
返回数据
① 不加@ResponseBody注解, 返回的是静态页面
这个静态页面-hello.html在resource中的static中,如果没有.那么访问就会报错 -> 访问名字要一致(要带后缀!)
@RequestMapping("/hi")
public String process(){
return "hello.html";
}
② 加上@ResponseBody注解 ,返回的是数据 ,这个上面演示过了 就不演示了
③ 可以返回JSON格式的数据
@RequestMapping("/respjson")
public HashMap<String, String> respJson() {
HashMap<String, String> map = new HashMap<>();
map.put("Java", "Java Value");
map.put("MySQL", "MySQL Value");
map.put("Redis", "Redis Value");
return map;
}
④返回请求转发或请求重定向
return 不但可以返回⼀个视图,还可以实现跳转,跳转的⽅式有两种:
forward 是请求转发; 与 redirect:请求重定向
请求转发和请求重定向的区别
请求转发是一种服务器的行为 , 客户端只有一次请求,服务器端转发后会将请求对象保存,地址栏中的URL地址不会改变,得到响应后服务器端再将响应发给客户端
请求重定向 是 一种客户端行为,在服务器上获取不到数据,就从另一个服务器上获取数据 , 从本质上讲等同于两次请求,前一次请求对象不会保存,地址栏的URL地址会改变。
注 :请求重定向与直接访问新地址效果⼀直,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问
// 请求重定向
@RequestMapping("/index")
public String index(){
return "redirect:/index.html";
}
// 请求转发
@RequestMapping("/index2")
public String index2(){
return "forward:/index.html";
}
Spring中启动热部署-Spring版本
① 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
②开启项目自动编译
③ 在搜索中开启热部署, (快捷键 , 双击shift)
搜索Registry , 在里面选择这个勾选上了即可
④ 忽略3在SpringBoot中 , 在application.properties配置中添加以下代码
#热部署默认会重启
spring.devtools.restart.enabled=true
#添加那个目录的文件需要restart
spring.devtools.restart.additional-paths=src/main/java
#排除那个目录的文件不需要restart
spring.devtools.restart.exclude=static/**,public/**