文章目录
- Spring MVC
- 一、概念
- 二、原理
- 三、Spring MVC项目准备
- 四、Spring MVC的响应
- 1、概念
- 2、 代码
- 3、注解介绍
- 五、Spring MVC的请求
- 1、Get请求
- 1.1、注意事项
- 1.2、代码
- 1.3、常见报错
- 2、Post请求
- 1.1、执行过程
- 1.2、代码
- 1.2.1、前端代码
- 1.2.2、Student类代码(Model 层,pojo,封装数据)
- 1.2.3、StudentController类代码
- 1.2.4、准备数据库和表
- 1.2.5、IDEA连接数据库
- 1.2.6、修改pom.xml文件,添加jar包的依赖
- 1.2.7、JDBC代码参数入库
- 1.2.8、运行前端和后端进行测试
- 3、Restful风格请求
- 1.1、注解介绍
- 1.2、注意事项
- 1.3、代码
Spring MVC
一、概念
框架:是一个结构,框架提供了很多的类,由框架控制每个类调用的过程流程。
SSM:S(Spring MVC),S(Spring),M(Mybaits)。
Spring。
Spring MVC主要作用:
- 接受请求(解析请求参数)
- 给出响应
Model(模型,Bean,pojo,封装,存储数据,封装数据)
View(视图,html,页面展示,展示数据)
Controller(控制,控制浏览器如何请求,做出数据的响应,Servlet)
提高代码的复用性,达到了松耦合的效果,三个部分相互独立,互不干扰,如果某一个模块发生变化,不影响其它两个模块。
持久层Dao:持久层用来和数据库读写ORM。
业务层Service:业务层用来处理复杂的业务逻辑。
控制层Controller:控制层用来处理MVC的控制。
二、原理
- 前端控制器(DispatcherServlet):当浏览器发生请求成功后,充当这调度者的角色,负责调度每个组件
- 处理器映射器(HandlerMapping):根据请求的URL路径,找到能处理请求的类名和方法名
- 处理器适配器(HandlerAdaptor):开始处理业务,并返回结果给(DispatcherServlet)
- 视图解析器(ViewResolver):找到正确的,能展示数据的视图,准备展示数据
- 视图(View):展示数据
三、Spring MVC项目准备
- 创建一个Spring Initializr项目,使用 Spring Boot 封装的 Spring 的jar包
- 创建一个Module的Maven项目
- 准备一个启动类RunApp,用于启动服务器
- 运行RunApp方法
- 打开浏览器访问 http://localhost:8080
四、Spring MVC的响应
1、概念
Spring MVC可以接受请求,和给出响应数据,数据类型非常丰富。响应就是返回数据。
2、 代码
/**
* 作者:沈公子
* 日期:2022/7/18 - 12:03
* 需求:Spring MVC的角色,给出响应,C控制器
*
*/
// 标记这个类是控制器,接受请求,响应JSON串
@RestController
// 规定浏览器url访问路径,严格区分大小写,不能存在相同的路径名,可以加 / ,也可以不加 /
@RequestMapping("/car")
public class HelloController {
@RequestMapping("get")
public String show() {
// 得到数据:123
// 访问数据:http://localhost:8080/car/get
// 规定浏览器url访问路径,严格区分大小写
// 字符串
return "123";
}
// 整形
@RequestMapping("getInt")
public int show2() {
return 100;
}
// 浮点型
@RequestMapping("getD")
public double show3() {
return 1.2;
}
// 对象
@RequestMapping("getNew")
public Car show4() {
Car car = new Car();
// 给客户端准备数据
car.setId(718);
car.setName("保时捷");
car.setType("Cayman T");
car.setColor("红色");
car.setPrice(641000);
return car; // 把对象信息变成 JSON 字符串在浏览器展示
}
// 布尔型
@RequestMapping("getB")
public boolean show5() {
return false;
}
// 数组
@RequestMapping("getArr")
public int[] show6() {
int[] arr = {1, 2, 3, 4, 5};
return arr;
}
}
3、注解介绍
- @RestController:
- 只能标记类
- 标记某个类是控制器
- 接受请求
- 给出响应
- @RequestMapping(“规定url访问路径”):
- 可以标记类和方法
- 固定浏览器的url访问路径,严格区分大小写,一个类中不能存在相同路径名,可以加 / ,也可以不加 /
- 建议在类上标记一个路径
五、Spring MVC的请求
请求方式8种,常见的就是get、post、restful风格的数据,用来简化了get的写法。
请求时需要给请求参数,参数最好使用引用类型,不要使用基本数据类型。
- get:http://localhost:8080/test/one?id=1&name=张三&age=20
- post:地址栏无法看到路径
- restful:http://localhost:8080/test/one/1/张三/20
1、Get请求
1.1、注意事项
- 方法中定义的参数就是url地址。
- 方法中的参数类型和名称规定了地址栏输入类型和名称,地址栏和参数数量可以不一致,可以改变顺序,八大基本数据类型除外。
- 参数中有八大基本数据类型,类型和名称一致,地址栏和参数数量一致,不能改变顺序,尽量使用引用类型。
- 方法中参数过多的情况下,可以将参数封装成对象,使用对象接受参数,框架会自动封装属性的值,类型和名称一致,地址栏和参数数量可以不一致,可以改变顺序。
- 总结:使用引用类型,按照正常顺序来
1.2、代码
/**
* 作者:沈公子
* 日期:2022/7/18 - 16:29
* 需求:Spring MVC 解析get请求参数
*/
// 接受请求做出响应
@RestController
// 规定了浏览器url地址访问方式
@RequestMapping("get")
public class GetController {
/*
404:找不到资源
400:参数类型不匹配
500:服务器代码错误,IDEA会抛出异常
*/
/*
这里的参数类型和名称规定了地址栏输入类型和名称
例: 这里的参数id就是地址栏要输入的 id,如果输入 a 或者其它的,否则报错500
*/
// 浏览器地址栏输入:http://localhost:8080/get/param?id=100
// 用 Spring MVC 解析get数据
// 一个参数
@RequestMapping("param")
public String param(int id) {
return "您的请求参数里的id=" + id;
}
// 浏览器地址栏输入:http://localhost:8080/get/param2?id=100&name=张三
// 两个参数
@RequestMapping("param2")
public void param2(int id, String name) {
System.out.println(id);
System.out.println(name);
}
// 浏览器地址栏输入:http://localhost:8080/get/param3?id=100&name=张三&price=9.9&type=X6&color=red
// 多个参数
@RequestMapping("param3")
public String param3(int id, String name, double price, String type, String color) {
return id + name + price + type + color;
}
// 浏览器地址栏输入:http://localhost:8080/get/param4?id=100&name=张三&price=9.9&type=X6&color=red
// 对象接收参数,框架会自动封装属性的值,参数太多,可以封装参数对象,地址栏输入的参数如果少于封装的参数也可以正常使用,地址栏和参数数量可以不一致
@RequestMapping("param4")
public Car param4(Car car) {
return car;
}
// 参数中有基本数据类型url地址必须输入基本数据类型,没有输入的其它类型会为 null,此时可以交换顺序
@RequestMapping("param5")
public String param5(String name, String type, byte b, int id, boolean a, short s, long l, float f, char c) {
return id + name + type + b + a + s + l + f + c;
}
// 数组
@RequestMapping("param7")
public void param7(int[] arr,String s) {
System.out.println(Arrays.toString(arr));
System.out.println(s);
}
// http://localhost:8080/test/one?id=1&name=张三&age=20
// get解析数据,传统方法
@Test
public void get1() {
String url = "http://localhost:8080/test/one?id=1&name=张三&age=20";
String[] a = url.split("\\?")[1].split("&");
for (String s : a) {
String data = s.split("=")[1];
System.out.println(data);
}
}
}
1.3、常见报错
- 404:找不到资源
- 400:参数类型不匹配
- 500:服务器代码错误,IDEA会抛出异常
2、Post请求
1.1、执行过程
填写内容 -> 提交 -> action=“http://localhost:8080/stu/add” -> 找到后台 -> 封装数据set -> 获取数据get -> JDBC操作数据库
1.2、代码
1.2.1、前端代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>学生信息管理系统MIS</title>
<style>
body{
font-size: 17px;
background-color: bisque;
}
.a{
width: 350px;
height: 40px;
padding: 5px;
font-size: 15px;
}
input[type="submit"]{
width: 100px;
height: 50px;
background-color: blue;
color: #ffffff;
border-color: blue;
font-size: 15px
}
input[type="button"]{
width: 100px;
height: 50px;
background-color: pink;
color: #ffffff;
border-color: pink;
font-size: 15px
}
</style>
</head>
<body>
<!--
利用表单,向服务器发送数据
默认是 get 提交,通过method属性修改提交方式
action属性,指定数据提交的位置
name属性,提交数据,与后端交互
value属性,传输的数据,数据库存储的值
checked="checked",默认选中
-->
<form method="POST" action="http://localhost:8080/stu/add">
<table>
<tr>
<td>
<h2>学生信息管理系统MIS<h2>
</td>
</tr>
<tr>
<td>
姓名:
</td>
</tr>
<tr>
<td>
<input type="text" class="a" name="name" placeholder="请输入姓名...">
</td>
</tr>
<tr>
<td>
年龄:
</td>
</tr>
<tr>
<td>
<input type="number" class="a" name="age" placeholder="请输入年龄...">
</td>
</tr>
<tr>
<td>
性别:(单选框)
<input type="radio" name="sex" value="1" checked="checked">男
<input type="radio" name="sex" value="0">女
</td>
</tr>
<tr>
<td>
兴趣:(多选框)
<input type="checkbox" name="hobby" value="ppq" checked="checked">乒乓球
<input type="checkbox" name="hobby" value="ps">爬山
<input type="checkbox" name="hobby" value="cg">唱歌
</td>
</tr>
<tr>
<td>
学历:(下拉框)
<select name="edu">
<option value="1">本科</option>
<option value="2">研究生</option>
<option value="3">大专</option>
</select>
</td>
</tr>
<tr>
<td>
入学日期:<br />
<input type="date" name="intime">
</td>
</tr>
<tr>
<td>
<input type="submit" value="保存">
<input type="button" value="取消">
</td>
</tr>
</table>
</form>
</body>
</html>
1.2.2、Student类代码(Model 层,pojo,封装数据)
/**
* 作者:沈公子
* 日期:2022/7/19 - 11:03
* 需求:Model 模型层,用来封装数据,就是一个pojo(封装的属性get/set)
* 前端name = 后端变量 = 数据库字段
*/
public class Student {
// 属性与前端匹配
// 属性(成员变量):变量类型 变量名
// 提交数据的类型 页面上name属性的值
// 如果前端name的值和后端变量名不一样,则无法封装
private String name;
private Integer age; // Integer避免了一些异常,如果是int类型,不传参数时可能会报错
private Integer sex;
private String[] hobby;
private Integer edu;
/*
浏览器上提交的日期默认是String类型,2022/7/19,报错400,参数类型不匹配
浏览器上提交的日期默认是String类型,把String类型的日期转成Date日期,
使用@DateTimeFormat,且可以进行格式设置 pattern 属性,y年,M月,d日
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date intime;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String[] getHobby() {
return hobby;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
public Integer getEdu() {
return edu;
}
public void setEdu(Integer edu) {
this.edu = edu;
}
public Date getIntime() {
return intime;
}
public void setIntime(Date intime) {
this.intime = intime;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", hobby=" + Arrays.toString(hobby) +
", edu=" + edu +
", intime=" + intime +
'}';
}
}
1.2.3、StudentController类代码
/**
* 作者:沈公子
* 日期:2022/7/19 - 11:01
* 需求:Controller 控制层。用来接收请求和给出响应
* 填写内容 -> 提交 -> action="http://localhost:8080/stu/add" -> 找到后台 -> 封装数据,反射set -> 展示,反射get -> JDBC操作数据库
*/
@RestController
@RequestMapping("stu") // 与前端匹配
public class StudentController {
@RequestMapping("add") // 与前端匹配
public Object add(Student student) throws ClassNotFoundException, SQLException {
// JDBC代码
return student;
}
}
1.2.4、准备数据库和表
CREATE TABLE tb_student(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(50),
age INT,
sex INT,
hobby VARCHAR(100),
edu INT,
intime DATE
)
1.2.5、IDEA连接数据库
1.2.6、修改pom.xml文件,添加jar包的依赖
<dependencies>
<!--连接数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
</dependencies>
1.2.7、JDBC代码参数入库
/**
* 作者:沈公子
* 日期:2022/7/19 - 11:01
* 需求:Controller 控制层。用来接收请求和给出响应
* 填写内容 -> 提交 -> action="http://localhost:8080/stu/add" -> 找到后台 -> 封装数据,反射set -> 展示,反射get -> JDBC操作数据库
*/
@RestController
@RequestMapping("stu") // 与前端匹配
public class StudentController {
@RequestMapping("add") // 与前端匹配
public Object add(Student student) throws ClassNotFoundException, SQLException {
// 实现入库 JDBC insert
// 1、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取连接
String url = "jdbc:mysql://localhost:3306/sgz?characterEncoding=utf-8";
Connection connection = DriverManager.getConnection(url, "root", "111111");
// 3、SQL语句,获取传输器
String sql = "insert into tb_student values (null,?,?,?,?,?,?)";
PreparedStatement ps = connection.prepareStatement(sql);
// 4、给SQL插入数据
ps.setObject(1, student.getName()); // 第一个 ? 的位置
ps.setObject(2, student.getAge());
ps.setObject(3, student.getSex());
// 数据库没有数组的概念,需要转成字符串,使用Arrays.toString()工具类
ps.setObject(4, Arrays.toString(student.getHobby()));
ps.setObject(5, student.getEdu());
ps.setObject(6, student.getIntime());
// 5、执行SQL,执行增删改的SQL
ps.executeUpdate();
// 6、提示一句话
System.out.println("数据插入成功!");
// 7、释放资源
ps.close();
connection.close();
return student;
}
}
1.2.8、运行前端和后端进行测试
3、Restful风格请求
1.1、注解介绍
- @PathVariable
- 在参数中使用
- 与 @RequestMapping 搭配使用,映射路径
例:{id} 对应 @PathVariable Integer id
1.2、注意事项
- {id} 对应 @PathVariable Integer id,名称要一样,可以交换顺序,但是不能缺少参数,一一对应即可
- 通过 {} 访问路径中携带的参数,@PathVariable 获取 {} 中间变量的值
1.3、代码
/**
* 作者:沈公子
* 日期:2022/7/19 - 9:32
* 需求:restful风格解析
*/
//@Controller
//@ResponseBody
@RestController
@RequestMapping("car")
public class CarController {
// 解析restful风格参数:http://localhost:8080/car/get2/1/张三
// {id} 对应 @PathVariable Integer id,名称要一样
// 解析时可以交换顺序,但是不能缺少参数
// 通过 {} 访问路径中携带的参数
// @PathVariable 获取 {} 中间变量的值
// 尽量一一对应
@RequestMapping("get2/{id}/{name}")
public String get2(@PathVariable Integer id, @PathVariable String name) {
return id + name;
}
@RequestMapping("get3/{id}/{name}/{color}/{price}")
public String get3(@PathVariable Integer id, @PathVariable String name, @PathVariable String color, @PathVariable double price) {
return id + name + color + price;
}
}