文章目录
一、HTTP协议
http协议:超文本传输协议,规定了浏览器和服务器之间数据传输的规则
- 特点:
- 基于TCP协议:面向连接,安全
- 基于请求——响应模型:一次请求对应一次响应
- HTTP协议是无状态的协议,对事务处理没有记忆能力,每次请求响应都是独立的。
- 优点:速度快
- 缺点:多次请求不能共享数据
1.请求数据格式
请求行:第一行
请求头:从第二行开始,key-value形式
参数 | 作用 |
---|---|
Host | 请求主机名 |
User-Agent | 浏览器的版本 |
Accept | 表示浏览器能接受的资源类型 eg:test/*指文本类型 |
Accept-Language | 浏览器以此返回语言 |
Accpet_Encoding | 浏览器支持大的压缩类型 |
Content-Type | 请求主体的数据类型 |
Content-Length | 请求主体的大小(字节) |
请求体:post请求专有,用于存放请求参数
2.响应数据格式
相应行:协议、状态码、描述
响应头:格式是key-value
响应体:最后一行,存放响应数据
状态码 | 描述 |
---|---|
1xx | 响应中 |
2xx | 相应成功 |
3xx | 请求服务器A但被A转移到了B,并从B中获取数据 |
4xx | 客户端错误,eg:请求不存在的资源 |
5xx | 服务器错误 |
二、JDBC概念
JDBC 是sun公司开发的一套操作所有关系型数据库的规范即接口(api)各公司只需要实现这套接口,提供数据库驱动jar包,使用步骤:
1.注册驱动
2.获取连接对象
3.获取执行sql的对象statement ,执行sql,返回结果
4.封装结果数据
5.释放资源
BS 架构和CS架构
BS架构指 Browerser/server 浏览器/服务器模式,维护快,速度慢
CS架构指Client/server 客户端/服务器模式。用户需下载app,速度快但维护较为复杂
三、MYBATIS概念
mybatis则是一个优秀的持久层(指dao层)框架,用于简化jdbc的开发.
mybatis步骤:
1.准备工作,创建spring boot工、数据库表、实体类(用于封装数据库信息),
2.引入mybatis相关依赖,配置mybatis(数据库连接信息 四要素:驱动、url、username、passwd)
3.编写sql语句
四、spring常用注解
注解 | 作用 |
---|---|
@RestController | 标识此类是请求处理类 =@Controller + @ResponseBody |
@ResponseBody | 用在controller类或方法上,被标识的类或方法都将作为响应数据 |
@RequesMapping(“路径”) | 此方法可通过此路径访问 |
@Service | 标识此类是spring服务层,并且将实体类交给IOC容器管理 |
@Mapper | 标识此类是spring数据访问层,并且自动将实体类交给IOC容器管理 |
@Autowired | 依赖注入 |
@GetMapping | 指定请求方式是Get |
@PostMapping | 指定请求方式是post |
@deleteMapping | 指定请求方式是delete |
@RequestBody | 用于接收JSON格式数据,将JSON格式数据映射到形参实体类对象中 |
五、sping接收前端参数的六种方式
1.简单参数接收
1-1.请求参数名称和方法参数变量名相同时,spring会自动类型转换,请求参数不传递则值返回null
@RestController
public class restController{
// http://localhost:8080/simpleParam?name=Tom &age=10
@RequesMapping("/simpleParam")
public void test1(String name,Integer age ) {
System.out.println(name+":"+age);
return "OK";
}
}
1-2.请求参数名称和方法参数变量名不同,可以用@RequestParam()指定,其中属性required默认为true即请求参数必须传递,否则报错
@RestController
public class restController{
// http://localhost:8080/simpleParam?name=Tom &age=10
@RequesMapping("/simpleParam")
public void test1(@REquestParam(name="name")String usernme,Integer age){
Sustem.out.println(username +":"+age)
return "OK";
}
}
2.实体参数接收
2-1.简单实体参数
请求参数有几个,方法中就要有一个形参,多时可以封装到一个实体类中,封装时属性名称和请求参数要相同
@RestController
public class restController{
// http://localhost:8080/simpleParam?name=Tom &age=10
//实体类user中有name和age两属性
@RequesMapping("/simpleParam")
public void test2(User user){
Sustem.out.println(user)
return "OK";
}
}
2-2.复杂实体参数
@RestController
public class restController{
//http://localhost:8080/example?name=Tom &age=10&addres.prives='河南'&addres.city='郑州'
//实体类addres中有prives和city两属性
//实体类user中有name和age和addres三属性
@RequesMapping("/example")
public void test2(User user){
Sustem.out.println(user)
return "OK";
}
}
3.数组集合参数接收
3-1.数据参数接收
数字名称和请求参数名称一致即可
@RestController
public class restController{
// http://localhost:8080/arrayParam?hobby = 'java'&hobby='python'
@RequesMapping("/arrayParam")
public void test3(String[]hobby){
Sustem.out.println(Arrays.toString(hobby))
return "OK";
}
}
3-2.集合参数接收
默认封装在数组中,可以用@RequestParam注解绑定参数关系,且集合名称和请求参数名称相同
@RestController
public class restController{
// http://localhost:8080/listParam?hobby = 'java'&hobby='python'
@RequesMapping("/listParam")
public void test3(@RequestParam List<String> hobby){
Sustem.out.println(hobby)
return "OK";
}
}
4.日期时间类参数
使用@DataTimeFormat(patten=)声明日期时间格式
@RestController
public class restController{
//http://locahost:8080/dateParam?updateTime = 2024-2-22 17:36:00
@RequestMapping("/dateParam")
public void test4(@DataTimeFormat(patten="yyyy-M-dd HH:mm:ss")LocalDateTime updateTime){
System.out.print(updateTime)
return "Ok";
}
}
5.Json格式参数
http://localhost:8080/jsonParam
{
“name”:“Tom”,
“age”:20,
addres:{
province:“shanghai”,
city:“shanghai”
}}
实体类对象中的属性应与请求参数中的名称一致,@RequestBody将JSON格式数据映射到形参实体类对象中
//实体类address
public class Address{
private provice;
private city;
}
//实体类user
public class User{
private name;
private age;
Address address;
}
//启动类中
@RestController
public class restController{
@RequestMapping("/jsonParam")
public string test5(@RequestBody User user){
System.out.println(user);
return"OK";
}
}
6.路径参数接收
6-1.单个路径参数
1.使用@PathVariable获取路径参数
2.通过请求url直接获取请求参数,并使用{}标识,动态获取路径参数
@RestController
public class restController{
//http://localhost:8080/path/1
@RequestMapping("path/{id}")
public void test6(@PathVariable Integer id){
System.out.println(id);
return"OK";
}
}
6-2.多个路径参数
只需将参数用“/”隔开即可
@RestController
public class restController{
//http://localhost:8080/path/1/Tom
@RequestMapping("path/{id}/{name}")
public void test6(@PathVariable Integer id,@PathVariable String name){
System.out.println(id+","+name);
return"OK";
}
}
六、后端响应前端数据
1.如何响应
@ResponseBody:用于Controller类/方法上,被此注解注释的类或方法都会作为响应数数据,若返回值类型为实体类对象/集合,将会转换成JSON格式数据响应。
2. 统一响应数据格式
为什么?因为响应数据格式随意,不便于后期维护和解析
怎么办?单独开一个响应数据格式类Result
public vlass Result{
//设置响应码 1代表成功,0代表失败
private Integer code;
//设置提示信息
private String msg;
//设置返回数据
private Object data;
//增删改成功响应
public static Result success(){return new Result(code:1,msg:"success",data:null);}
//查询成功响应
public static Result success(Object data){return new Result(code:1,msg:"success",data);}
//响应失败
public static Result error(String msg){return new Result(code:0,msg,data:null)}
}
#七、 web三层架构
- Controller:控制层(表示层)接受请求,处理请求并响应数据
- Service:业务控制层 处理集体的业务逻辑
- Dao:数据访问层(持久层)负责数据访问处理操作,eg:增删改查
分层解耦:解除耦合 高内聚!低耦合!
- 内聚:软件中各功能模块内部的联系
- 耦合:软件中各层/模块之间的依赖、关联程度
八、IOC、DI
- 控制反转:IOC,对象的创建由程序转移到外部(IOC容器)
- 依赖注入:DI,容器为程序运行时提供,所依赖的资源
- bean对象:IOC容器中创建并管理的对象,称为bean对象(默认时类名首字母小写)
注解 | 作用(IOC) |
---|---|
@Componet | 用于不属于三层架构的类上 |
@Controller | 用在控制层上 |
@Service | 用在服务层上 |
@Repository | 用于数据访问层上,但由于mybatis整合,用的很少 |
注解 | 作用(DI) |
---|---|
@Autowried | 依赖注入,注入在IOC容器中的对象 |
- bean组件
声明的注解想要生效必须经过@ComponentScan扫描 - 没有设置@Component为什么没有报错
because 此注解已经包含在启动类生命注解@SpringBootApplication中。
默认扫描范围是启动类所在包及其子包
九、数据库连接池概念
数据库连接池是一个容器,用于分配、管理数据据连接
它允许应用程序重复使用一个现有的数据库连接,而不是重建一个。他会释放空闲时间超过最大空闲时间的数据库库连接,来避免因为没有释放而引起的数据库连接遗漏
优势:资源重用、提升系统反应速度、减少数据库遗漏
产品:Druid、Hikari、C3po、 Dbcp
Druid是阿里巴巴开源数据库连接池项目,性能优秀,功能强大,是java语言性能最好的书库据连接池之一。spring默认使用hikari
替换连接池:
1.引入连接池依赖
2.在properties文件中配置数据库连接信息
十、LOMBOK
lombok是一个使用Java类库,能够通过注解的方式来生成各种方法,并且能够自动化的生成日志变量,从而简化Java开发,提高效率
注解 | 作用 |
---|---|
@Getter/setter | 给属性生成 get/set方法 |
@toString | 给类自动生成toString方法 |
@EqualsAndHashCode | 根据类所拥有的非静态字段自动重写equal和hashcode方法 |
@Data | 相当于 @Getter/setter + @toString +@ EqualsAndHashCode |
@NoArgsConstructor | 为实体类生成无参构造方法 |
@AllArfsConstructor | 为实体类生成除了static修饰的字段外的各种参数的构造方法 |
十一、参数占位符
1.#{…} 执行替换操作,将#{…}替换成?生成预编译sql
2.${…} 执行拼接,直接将参数拼接在sql语句中,存在sql注入问题
sql注入
select count(*) from emp where username - "..." and passwd = ".." or '1' = '1'
//(会有很多条结果)
十二、简单的增删改查
背景:学工系统 数据库表: emp
//实体类Emp
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp{
private Integer id;
private String username; //用户名
private String password;//密码 默认123456
private String name;//姓名
private Short gender; //1.男 2.女
private String image;//图片
private Short job; //1.班主任 2.讲师 3.学工主管 4.教研主管 5.咨询师
private LocalDate entrydate; //入职时间
private Integer deptId;//部门id
private LocalDateTime createTime; //创建时间
private LocalDateTime updateTime;//修改时间
}
1.新增
//mapper类
@Mapper //交给IOC容器管理
public class EmpMapper{
@Insert("insert"+
"emp (username,name,gender,image,job,entrydate,dept_id,create_time,update_time)"+
"values"+
"(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},"+
"#{updateTime})")
public void insert(Emp emp);
}
//test测试类
@Test
public Test{
@AutoWride
private EmpMapper empMapper;
public void insert(){
Emp emp = new Emp();
emp.setUsername("Tom");
emp.setName("汤姆");
emp.setGender((short) 1);
emp.setImage("1.pig");
emp.setJob((short)1);
emp.setEntrydate(LoclData.of(year:2024,month:2,dayOfMonth:22));
emp.setCreateTime(LocalDataTime.Now());
emp.setUpdateTime(LocalDataTime.Now());
empMapper.insert(emp);
}
}
2.删除
2-1.无返回值
//EmpMapper类
@Mapper
public class EmpMapper{
@Delete("delete emp where id = #{id}")
public void delete(Integer Id)
}
//Test类
@Test
public class test{
@Autowride
private EmpMapper empMapper;
public void delete(){
empMapper.delete(1);
}
}
2-2.有返回值
//EmpMapper类
@Mapper
public class EmpMapper{
@Delete("delete emp where id = #{id}")
public int delete(Integer Id)
}
//Test类
@Test
public class test{
@Autowride
private EmpMapper empMapper;
public void delete(){
int de = empMapper.delete(1);
System.out.println(de);//输出删除了几条数据
}
}
3.更新
根据id修改数据
//EmpMapper
@Mapper
public class EmpMapper{
@Update("update emp set username = #{username},name=#{name},gender=#{gender},"+
"image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},"+
"update_time = #{updateTime} where id = #{id}" )
public void update(Emp emp )
}
//test
@Test
public calss test{
@Autowride
private EmpMapper empMapper;
public void update(){
Emp emp =new Emp();
emp.setId(14);
emp.setUsername("zhangsanfeng");
emp.setName("张三丰");
emp.setGender((short) 1);
emp.setImage("14.jpg");
emp.setJob((short)2);
emp.setEntrydate(LocalDate.of(2002, 8, 1));
emp.setDeptId(2);
emp.setUpdateTime(LocalDateTime.now());
empMapper.update(emp);
}
}
4.查询
4-1.根据id查询
//EmpMapper类
@Mapper
public class EmpMapper{
@Select("select * from emp where id =#{id}")
public emp select(Integer id);
}
//test类
@Test
public class empMapper{
@Autowride
private EmpMapper empMapper;
public void empTest(){
Emp emp = empMapper.select(15);
System.out.print(emp);
}
}
结果
deptId、createTime、updateTime结果为null因为数据表字段名和实体类属性名不一致,数据无法自动封装;
解决数据封装
当实体类属性名和数据库查询返回字段名不相同时,mybatis不会自动封装
方法一:给名字不一致的字段名起别名
//empMapper类
public class EmpMapper{
@Select("select id,username,password,name,gender,image,job,entrydate,dept_id deptId,create_time createTime,update_time updateTime from emp where id = #{id} ")
public Emp getById(Integer id);
}
方法二:通过@Results和@Result注解手动映射封装
//Column:字段名,property:实体类属性名
@Mapper
public class EmpMapper{
@Results({
@Result(Column = "dept_id",property="deptId")
@Result(Column = "create_time",property="createTime")
@Result(Column = "update_time",property="updateTime")
})
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);
}
方法三: 开启mybatis的驼峰命名自动映射开关,自动将 a_column字段封装到实体类中的 aColumn属性中(推荐!)
//properties文件中开启驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true
//自动将a_cloumn自动封装在aCloumn中
4-2.条件查询(姓名、性别、入职日期范围)
//EmpMapper类
@Mapper
public class {
@Select("select * from emp where username like concat('%',#{name},'%') and gender = #{gender} and entrydate between #{begin } and #{end} order by update_time desc ")
public List<Emp> select(String name, short gender, LocalDate begin,LocalDate end);
}
//Test类
@Test
public class test{
@Autowride
private EmpMapper empMapper;
public void empTest(){
List<Emp> empList = empMapper.select("张",(short)1,LocalDate.of(2000,1,1),LocalDate.of(2024,2,27));
System.out.println(empList);
}
}
//非常繁琐并且不宜后期维护,所以复杂查询推荐使用xml映射文件
十三、XML映射文件
简介:通过xml配置文件的形态来配置sql语句
规范:
- xml映射文件的名称要与Mapper接口名一致,并且要放置在相同包下,(同包同名);
- xml映射文件中namepace属性为Mapper接口的全限定名
- xml映射文件中sql语句的id为Mapper接口中的方法名,并且返回类型要一致
同包同名:
约束:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper接口的全限定名">
//sql语句
</mapper>
动态SQl
简介:随着用户的输入或外部条件的变化而变化的SQl语句
1.if条件判断
1-1.test属性:使用标签中的test进行条件判断,若test属性为true,则拼接判断语句
<if test = "name != null">
name like concat('%',#{name},'%')
<if>
1-2.where标签
作用:
- 动态生成where关键字,若条件都不成立则不会生成where
- 会自动删除多余的and或or
举例:根据姓名、性别、入职日期范围查询信息
//EmpMapper类
@Mapper
public class EmpMapper{
public List<Emp> list(String name,(short)gender,LocalDate begin,LocalDate end)
}
//Xml文件
public class EmpMapper{
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itzhen.mapper.EmpMapper">
// id属性:和方法名相同,resultType属性:为单条记录所封装的类型的全限定名
<select id = list,resultType = "com.itzhen.pojo.Emp">
select * from emp
<where>
<if test name != null and name != ' '>
username like concat('%',#{name},'%')
</if>
<if test gender != null>
and gender = #{gender}
</if>
<if test begin != null and end !=null>
and entrydate between #{begin} and #{end}
</if>
</where>
</select>
</mapper>
}
2.foreach遍历循环
常见属性:
- collection: 遍历的集合(参数名)
- item : 遍历出的元素(变量名)
- seprator :元素之间用什么分隔
- open:循环遍历前拼接的sql片段
- close:循环遍历后拼接的sql片段
举例:根据id批量删除数据
//test类
@Test
public class test{
@Autowride
private EmpMapper empMapper;
public void testMapper(){
list<Integer> ids = Arrays.asList(12,16,19);
empMapper.deleteById(ids)
}
}
//Mapper类
public class EmpMapper{
public void deleteById(List<Integer> ids);
}
//EmpMapper.Xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itzhen.mapper.EmpMapper">
<delete id = deleteById>
delete * from emp where id in
<foreach collection ="ids" ,item = "id" ,seprator = "," ,open = "(",close = ")">
#{id} //遍历出来的元素
</foreach>
</delete>
</mapper>