一.Spring MVC的概念
1.1概述
是Spring框架的明星产品,用来 接受浏览器发来的请求 + 并返回数据
遵循MVC思想: 主要是想要松耦合,实现代码间的高内聚, 提高代码的可维护性
M 是Model, 模型层, 用来封装数据
V 是View, 视图层, 用来展示数据
C 是Controller, 控制层 作用就是用来 接受请求和给出响应
1.2工作原理
五个核心的组件
1, 前端控制器DispatcherServlet: 接受请求并分发请求
2, 处理器映射器HandlerMapping: 根据请求,找到具体能处理请求的类名,方法名
3, 处理器适配器HandlerAdapter: 正式开始调用方法处理请求,并返回结果
4, 视图解析器ViewResolver: 把页面找到,把数据进行解析
5, 视图渲染View: 具体展示数据并返回给浏览器
1.3测试
创建maven module
选中工程-右键-New-Module-选中Maven-next-输入module名-finish
创建启动类
package cn.tedu.hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication//作为启动类,用来启动服务器
public class RunApp {
public static void main(String[] args) {
//利用springboot运行指定类
SpringApplication.run(RunApp.class);
}
}
创建CarController类
package cn.tedu.hello;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//需求: http://localhost:8080/car/get
@RestController//是springmvc提供的,可以被浏览器访问
@RequestMapping("car")//是springmvc提供的,规定了浏览器访问这个类的方式
public class CarController {
//访问方式:http://localhost:8080/car/get
@RequestMapping("get")
public void get(){
System.out.println("浏览器访问成功!");
}
}
测试
打开浏览器访问: http://localhost:8080/car/get
二,springmvc框架解析请求参数
1,get方式
把数据用?拼接在地址栏中,多数据之间用& 连接 :
http://localhost:8080/car/add?id=10
解析复杂的参数
package cn.tedu.hello;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//需求: http://localhost:8080/car/get
/*
总结:
1, SpringMVC可以接受请求,并解析请求参数
只要在方法的参数列表中声明就可以:public void add(int id,String name)
2, 为了避免400或者500的异常,最好把参数列表的参数类型改成引用类型
改后:public void add(Integer id,String name)
3, 参数列表可以提供一个对象,框架可以解析参数,并且可以把参数直接给对象的属性赋值
public void save2(Car c)
*/
@RestController//是springmvc提供的,可以被浏览器访问
@RequestMapping("car")//是springmvc提供的,规定了浏览器访问这个类的方式
public class CarController {
@RequestMapping("get")
public void get(){
System.out.println("浏览器访问成功!");
}
//springmvc解析get方式的请求参数
//练习1: http://localhost:8080/car/add?id=10
@RequestMapping("add")
public void add(Integer id){
//参数列表的写法:1,参数类型必须和请求的参数类型一致 2,参数名称必须和请求的参数名称一致
System.out.println("浏览器访问成功add!"+id);
}
//练习2: http://localhost:8080/car/add2?id=10&name=jack
@RequestMapping("add2")
public void add(Integer id,String name){
System.out.println("浏览器访问成功add!"+id+name);
}
//练习3: http://localhost:8080/car/save?id=1&color=red&price=100
//HandlerMapping:处理器映射器,拿着地址栏的访问方式找到哪个类哪个方法
//Map<String,Object> {"/car/save", new CarController().save()}
@RequestMapping("save")
public void save(Integer id,String color,Double price){
//基本类型的参数,访问时必须传参否则400 500异常,
//引用类型不传入参数也行,就会用默认值null
//优化1:推荐使用引用类型,因为规避了异常的发生!!!
System.out.println(id+color+price);
}
//练习4:http://localhost:8080/car/save2?id=1&color=red&price=100&pinpai=BMW&type=X7
//框架的作用:1,解析了请求参数 2,把解析到的参数调用c.setXxx()设置值
@RequestMapping("save2")
public void save2(Car c){
System.out.println(c);
//Car{id=1, color='red', price=100.0, pinpai='BMW', type='X7'}
}
}
创建Car类
package cn.tedu.hello;
//http://localhost:8080/car/save2?
// id=1&color=red&price=100&pinpai=BMW&type=X7
//这个类用来存,springmvc框架解析到的请求参数
public class Car {
private Integer id;
private String color;
private Double price;
private String pinpai;
private String type ;
//set get tostring --右键-generate
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getPinpai() {
return pinpai;
}
public void setPinpai(String pinpai) {
this.pinpai = pinpai;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String toString() {
return "Car{" +
"id=" + id +
", color='" + color + '\'' +
", price=" + price +
", pinpai='" + pinpai + '\'' +
", type='" + type + '\'' +
'}';
}
}
2,restful方式
在IDEA里创建后端代码UserController 类
package cn.tedu.hello;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//需求:解析restful风格提交的数据,简化了get提交数据的写法
//普通get方式:http://localhost:8080/user/insert?id=1&name=张三&age=18
//restful方式:http://localhost:8080/user/insert/1/张三/18
@RestController
@RequestMapping("user")
public class UserController {
//解析get数据:http://localhost:8080/user/insert?id=1&name=张三&age=18
@RequestMapping("insert")
public Object insert(Integer id,String name,Integer age){
return id+name+age;
}
//解析restful数据:http://localhost:8080/user/insert2/1/张三/18
//步骤:1,利用{}获取地址栏中的参数,个数和顺序要和地址栏里的参数匹配
//2,利用@PathVariable注解,获取花括号中间的变量的值
@RequestMapping("insert2/{id}/{name}/{age}")
public void insert2(@PathVariable Integer id,
@PathVariable String name,
@PathVariable Integer age){
System.out.println(id+name+age);
}
}
在HB里创建前端html代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前后端整合</title>
</head>
<body>
<a href="http://localhost:8080/user/insert">普通访问</a>
<a href="http://localhost:8080/user/insert?id=10&name=rose&age=20">普通的get提交方式</a>
<a href="http://localhost:8080/user/insert2/10/rose/20">restful方式</a>
</body>
</html>
测试
练习:
需求
练习:
http://localhost:8080/car/save2?id=1&color=red&price=100&pinpai=BMW&type=X7
1,解析浏览器发来的请求参数
2,给浏览器返回数据
修改前端页面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前后端整合</title>
</head>
<body>
<a href="http://localhost:8080/user/insert">普通访问</a>
<a href="http://localhost:8080/user/insert?id=10&name=rose&age=20">普通的get提交方式</a>
<a href="http://localhost:8080/user/insert2/10/rose/20">restful方式</a>
<a href="http://localhost:8080/car/save3?id=1&color=red&price=100&pinpai=BMW&type=X7">点我获取汽车数据</a>
</body>
</html>
修改后端代码,创建类
package cn.tedu.hello;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("car")
public class CarController2 {
//1,解析浏览器发来的请求参数
//http://localhost:8080/car/save3?id=1&color=red&price=100&pinpai=BMW&type=X7
@RequestMapping("save3")
public Object save3(Car c){
//TODO 把解析到的请求参数 getXxx()入库--jdbc
//pom里加jdbc的坐标
//在数据库里创建car表(提供id,color,price,pinpai,type字段)
//注册驱动 获取数据库连接 获取传输器 执行SQL 解析结果集 释放资源
//{"id":1,"color":"red","price":100.0,"pinpai":"BMW","type":"X7"}
return c;
}
}
3,post方式
1.准备表单
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
body{
font-size: 17px; /* 字号 */
background-color: lightpink; /* 背景色 */
}
/* 输入框 */
.a{
width: 300px; /* 宽度*/
height: 40px; /* 高度 */
font-size: 20px; /* 字号 */
}
/* 保存按钮 */
input[type="submit"]{
/* 背景色 字的颜色 边框颜色 宽度 高度 */
background-color: #0000FF;
border-color: #0000FF;
color: white;
width: 100px;
height: 40px;
font-size: 20px; /* 字号 */
}
/* 取消按钮 */
input[type="button"]{
/* 背景色 字的颜色 边框颜色 宽度 高度 */
background-color: #FF69B4;
border-color: #FF69B4;
color: white;
width: 100px;
height: 40px;
font-size: 20px; /* 字号 */
}
</style>
</head>
<body>
<!-- 表单可以提交数据,默认get方式.
method="post"指定提交方式,action=""指定跳转的网址
要求:1,必须是form 2,必须有submit按钮 3,必须配置name属性
-->
<form method="post" action="http://localhost:8080/student/save">
<table>
<tr>
<td>
<h2>学生信息管理系统MIS</h2>
</td>
</tr>
<tr>
<td>姓名:</td>
</tr>
<tr>
<td>
<input class="a" type="text" placeholder="请输入姓名" name="name">
</td>
</tr>
<tr>
<td>年龄:</td>
</tr>
<tr>
<td>
<input class="a" type="number" placeholder="请输入年龄" name="age">
</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>
入学日期:
<input type="date" name="intime"/>
</td>
</tr>
<tr>
<td>
<input type="submit" value="保存"/>
<input type="button" value="取消"/>
</td>
</tr>
</table>
</form>
</body>
</html>
2.准备启动类
package cn.tedu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RunApp {
public static void main(String[] args) {
SpringApplication.run(RunApp.class);
}
}
3.准备Controller类,解析请求数据
package cn.tedu.controller;
import cn.tedu.pojo.Student;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//和浏览器交互,接受请求,给出响应
@RestController
@RequestMapping("student")
public class StudentController {
//解析请求参数
@RequestMapping("save")
// public String save(String name,Integer age,String sex,String hobby){
public String save(Student s){
//Student{name='jack', age=20, sex=0, hobby=[ppq, ps, cg], edu=2, intime=Wed Sep 15 00:00:00 CST 2021}
System.out.println(s);
return "保存成功!" ;
}
}
4.创建Student类,用来封装数据
package cn.tedu.pojo;
import java.util.Arrays;
import java.util.Date;
//充当了MVC的M层,model层,用来封装数据
//pojo类里只有属性和set() get()
public class Student {
//规则: 属性的类型 属性的名字
//和HTML页面保持一致:参考页面输入的值 参考页面中name属性的值
private String name;//用来封装用户在浏览器输入的用户名
private Integer age;//用来封装用户在浏览器输入的年龄
private Integer sex;//用来封装用户在浏览器选择的性别
private String[] hobby;//用来封装用户在浏览器选择的爱好--多选的结果存入数组
private Integer edu;
//400异常的原因:页面上输入的日期是String类型
//String->Date: @DateTimeFormat,需要指定日期的格式y是年M是月d是天
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date intime;//用来封装用户在浏览器选择的日期
//get set tostring
public String getName() {
return name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", hobby=" + Arrays.toString(hobby) +
", edu=" + edu +
", intime=" + intime +
'}';
}
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;
}
}
5.测试
6.扩展:入库
修改pom,添加jdbc的jar包
直接在最外面的pom里加就行了,里面的每个module都可以用
<!--添加了jdbc的jar包 右键-generate-dependency-搜 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
创建数据库表
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
sex INT,
hobby VARCHAR(100),
edu INT,
intime DATE
)
创建StudentController类,接受请求,包括入库
package cn.tedu.controller;
import cn.tedu.pojo.Student;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Arrays;
//和浏览器交互,接受请求,给出响应
@RestController
@RequestMapping("student")
public class StudentController {
//解析请求参数
@RequestMapping("save")
// public String save(String name,Integer age,String sex,String hobby){
public String save(Student s) throws Exception {
//TODO 把解析成功的学生数据 入库
//1,修改pom添加jar包(直接改了project里的pom.xml)
//2,建表student
/*
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
sex INT,
hobby VARCHAR(100),
edu INT,
intime DATE
)
*/
//3,写jdbc
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接
String url="jdbc:mysql://localhost:3306/cgb2107?characterencoding=utf8";
Connection con = DriverManager.getConnection(url,"root","root");
//获取传输器--插入的值的个数参考字段的个数,顺序也是参考字段的顺序
String sql="insert into student values(null,?,?,?,?,?,?)";
PreparedStatement p = con.prepareStatement(sql);
//设置SQL的参数
p.setObject(1,s.getName());
p.setObject(2,s.getAge());
p.setObject(3,s.getSex());
//注意:数据库里根本没有数组的类型,需要String[]->String,否则Data too long for column 'hobby' at row 1
p.setObject(4, Arrays.toString(s.getHobby()) );
p.setObject(5,s.getEdu());
p.setObject(6,s.getIntime());
//执行SQL
p.executeUpdate();
//释放资源
p.close(); con.close();
return "保存成功!" ;
}
}
总结
拓展:修改Tomcat端口号