你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github gitee
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^)
想看更多 那就点个关注吧 我会尽力带来有趣的内容
CSDN 图片导入做的不是很好,因此如果有没有出现的图片请去这里 传送 https://juejin.cn/user/1942157160101860/posts
掘金的文档写作体验比CSDN好多了。。。。里面好像也有不少大佬
快速入门Web开发(中)后端开发(有重点)
为什么你能通过一小段代码来访问网页?(重点)
要明白这件事,首先要知道我们是如何访问网站的
访问网页的本质涉及多个技术层面,从用户输入网址到最终在浏览器上看到页面的过程包含了多个步骤:
-
域名解析:当你在浏览器中输入一个网址(URL),比如
http://www.example.com
,浏览器首先需要将这个域名解析成对应的 IP 地址。这个过程通过域名系统(DNS)完成,将易于记忆的域名映射到实际的服务器 IP 地址。(本地) -
发起连接:一旦浏览器获得了服务器的 IP 地址,它就会通过网络协议(通常是 HTTP 或 HTTPS)与服务器建立连接。这个过程涉及多个网络层的交互,包括 TCP/IP 协议等。(网络通信)
-
发送请求:浏览器发送一个 HTTP 请求给服务器,这个请求包含了请求的类型(GET、POST 等)、路径、头部信息(例如浏览器类型)、可能的请求体(对于 POST 请求)等。(网络通信)
-
服务器处理:服务器接收到请求后,根据请求的路径以及其他信息,决定要执行哪些操作。这通常涉及到服务器端的应用程序,比如一个 Web 应用程序。在以上的图片中,就是 Spring Boot 中的控制器方法。(服务器本地)
-
生成响应:服务器处理请求后,会生成一个 HTTP 响应。这个响应包括了响应的状态码(例如 200 OK、404 Not Found)、响应头部(例如内容类型),以及响应体(实际的数据内容)。(服务器本地)
-
传输响应:服务器将生成的 HTTP 响应通过网络传输回浏览器。(网络通信)
-
浏览器处理:浏览器接收到响应后,会根据响应的内容类型(例如 HTML、CSS、JavaScript 等)进行处理。浏览器会解析 HTML,构建 DOM(文档对象模型),加载和解析 CSS 样式,执行 JavaScript 等操作。(本地)
-
渲染页面:浏览器根据 DOM 结构和 CSS 样式对页面进行渲染,最终在浏览器窗口中呈现出用户可见的页面。(本地)
当你启动 Spring Boot 项目并且访问 http://localhost:8080
或其他定义的路径时,Spring Boot 内置的 Web 服务器( Tomcat 或其他容器)会拦截这些请求,并将请求映射到相应的控制器方法。控制器方法执行完成后,返回的内容会被直接写入 HTTP 响应,然后返回给浏览器进行显示。
后端工具
Maven
- 依赖管理:因为要导入的jar包很多,所以使用Maven来快捷、方便的进行导包
- 统一的结构:idea和eclipse等开发软件生成的项目结构不一样,使用maven可以直接导入
- 快速的完成以上功能
https://maven.apache.org/
maven的架构
- 本地没有jar包的情况下,看有无链接私服,有则去私服找,没有就去中央找。私服本身没有,则私服去中央找
- 其中bing目录存放可执行文件
- conf存放maven配置文件
- lib存放maven依赖的jar包资源
步骤二
- conf中settings的第五十三行代码复制下,并填上maven仓库的地址(自定义)
步骤三
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
- 通过mvn -v校验是否成功。成功标志为出现版本号
配置maven
- 将maven使用jdk和编译器使用的设置成相同
- 在idea2022中直接创建普通的项目,选择java中的maven即可
Maven项目导入
- 调出maven
- 点击加号即可
添加Maven依赖
<!--添加依赖-->
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<dependencies>
:这个标签是pom.xml文件的根标签,用于包含所有的依赖项。<dependency>
:这个标签用于描述一个具体的依赖项。<groupId>
:这个标签指定了依赖项的组织或公司的唯一标识符。在这个例子中,依赖项的groupId是ch.qos.logback,表示这个依赖项是由logback项目组提供的。<artifactId>
:这个标签指定了依赖项的名称或标识符。在这个例子中,依赖项的artifactId是logback-classic,表示这个依赖项是logback日志框架的经典版本。<version>
:这个标签指定了依赖项的版本号。在这个例子中,依赖项的版本号是1.2.3,表示使用logback-classic的1.2.3版本。
什么是依赖
依赖就好比是一个软件模块需要借助其他模块或组件才能正常工作。类比一下,你可以把依赖想象成一个人需要使用其他人的工具才能完成任务。比如,你要修理自行车,但是你需要用到一个扳手,而你自己没有。这时,你就需要依赖别人借给你一个扳手才能完成修理任务。
在软件开发中,也是类似的情况。一个软件模块可能需要使用其他模块提供的功能,比如某个库或框架。这样,它就需要在项目中引入这个库或框架的代码,以便能够调用它提供的功能。为了方便管理这些依赖关系,开发人员通常会使用依赖管理工具。这个工具会帮助自动下载和引入所需的库、框架或其他依赖项,确保项目能够正常构建和运行。
- 点击重写加载后
在maven页面可以看到依赖是否生效
依赖与jar包
依赖与jar包作用是一样的,但是依赖更容易维护与直接修改
依赖特性
- 运行后面的依赖,前面的依赖也会执行
- 在同一套生命周期中,运行后面阶段,前面阶段都会运行
- maven所有操作由插件执行
Tomcat
- 一个web服务器
- 默认端口号为8080
postman
想要发出post请求得自己编写程序,可以用postman来代替
SpringBoot初体验
package com.example.springboot_one.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
// 请求处理类
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
System.out.printf("hello");
return "hello";
}
}
- 运行SpringbootOneApplication这个文件
- Tomcat又称servlet容器
- BS架构体验一般指对宽带需求大,现在已经不是问题
- CS架构虽然可以在本地处理一些数据,但不同平台要开发不同的版本
http协议
- 请求头和请求体之间的空行是必须的
请求
路径由
变成
- get请求的参数就在这里面了(通过?来实现),而post请求的参数不在
响应
- 重定向指的是原来要访问的资源被转移到了另一台服务器或者本服务器的另一个位置了。这时候服务器会放回一个3开头的状态码和被转移后资源的位置,受到返回的浏览器会自动找这个资源
状态码大类
状态码分类 | 说明 |
---|---|
1xx | 响应中——临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它 |
2xx | 成功——表示请求已经被成功接收,处理已完成 |
3xx | 重定向——重定向到其它地方:它让客户端再发起一个请求以完成整个处理。 |
4xx | 客户端错误——处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等 |
5xx | 服务器端错误——处理发生错误,责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等 |
常见的响应状态码
状态码 | 英文描述 | 解释 |
---|---|---|
200 | OK | 客户端请求成功,即处理成功,这是我们最想看到的状态码 |
302 | Found | 指示所请求的资源已移动到由Location 响应头给定的 URL,浏览器会自动重新访问到这个页面 |
304 | Not Modified | 告诉客户端,你请求的资源至上次取得后,服务端并未更改,你直接用你本地缓存吧。隐式重定向 |
400 | Bad Request | 客户端请求有语法错误,不能被服务器所理解 |
403 | Forbidden | 服务器收到请求,但是拒绝提供服务,比如:没有权限访问相关资源 |
404 | Not Found | 请求资源不存在,一般是URL输入有误,或者网站资源被删除了 |
405 | Method Not Allowed | 请求方式有误,比如应该用GET请求方式的资源,用了POST |
428 | Precondition Required | 服务器要求有条件的请求,告诉客户端要想访问该资源,必须携带特定的请求头 |
429 | Too Many Requests | 指示用户在给定时间内发送了太多请求(“限速”),配合 Retry-After(多长时间后可以请求)响应头一起使用 |
431 | Request Header Fields Too Large | 请求头太大,服务器不愿意处理请求,因为它的头部字段太大。请求可以在减少请求头域的大小后重新提交。 |
500 | Internal Server Error | 服务器发生不可预期的错误。服务器出异常了,赶紧看日志去吧 |
503 | Service Unavailable | 服务器尚未准备好处理请求,服务器刚刚启动,还未初始化好 |
状态码大全:https://cloud.tencent.com/developer/chapter/13553
SpringBoot
HttpServletRequest对象
HttpServletRequest
是Java Servlet API中的一个接口,用于表示客户端的HTTP请求。它提供了许多方法来获取关于请求的信息,如请求的URL、参数、头部信息等。通过HttpServletRequest
,可以从客户端接收数据并对请求进行处理。
HttpServletRequest
对象提供了以下方法来获取请求的各种信息:
- 请求行信息:如请求的URL、请求的方法(GET、POST等)、HTTP协议版本等。
- 请求头信息:如User-Agent、Referer、Accept-Language等。
- 请求参数:可以通过
getParameter()
方法来获取请求的参数,如表单提交的参数、URL中的查询参数等。 - 请求体信息:对于POST请求,请求体中可能包含请求的实体内容,可以通过
getInputStream()
或getReader()
方法来获取请求体的内容。
通过HttpServletRequest
对象,开发者可以获取到客户端发送过来的各种信息,并根据这些信息进行相应的处理和响应。
接收参数
简单参数
原始方法
@RequestMapping("/simpleParam")
public String simpleParam(HttpServletRequest request) {
String name = request.getParameter("name");
String ageStr = request.getParameter("age");
/*
getParameter()是HttpServletRequest接口中的一个方法,用于获取HTTP请求中的参数值。
它接收一个String类型的参数名称,并返回对应参数名称的值。
getParameter()方法会根据参数名称在请求中查找对应的值,并将其作为String类型返回。
如果请求中不存在该参数或参数值为空,则getParameter()方法返回null。
需要注意的是,getParameter()方法只能获取到请求中的查询参数或表单提交的参数。
对于其他类型的请求体,如JSON或XML数据,需要使用其他方法来获取请求体中的数据。*/
int age= Integer.parseInt(ageStr);
System.out.printf(name+":"+age);
return "OK";
}
运行结果
SptingBoot版本
@RequestMapping("/simpleParam")
public String simpleParam(String name,int age) {//此处也可以改为Integer
System.out.printf(name+":"+age);
return "OK";
}
- 结果一样
以上都是get请求,如何使用post请求呢?
- 参数名不一致时候会放回null
参数名映射
实体参数映射(设置网站内容页)
复杂实体
- 通过创建两个类来满足需要。一个类包含另一个
数组集合参数
-
只要数组名相同
-
默认封装成数组,需要加一下符号
日期参数
json参数
- json格式数据使用不了get
- 需要做到key与实体对象的属性名相同
路径参数
-
@PathVariable是Spring框架中的一个注解,用于将URL中的参数绑定到方法的参数上。
可以使用@PathVariable注解来获取URL中的动态参数。这些参数可以是在URL路径中的一部分,用花括号{}括起来,并通过@PathVariable注解来绑定到方法的参数上。
-
使用这个注解后,可以使得访问路径是变化的。如 localhost:8080/path/2和localhost:8080/10
什么是控制器?
控制器(Controller)是MVC(Model-View-Controller)设计模式中的一个组件,用于接收用户的请求并处理请求的逻辑。控制器负责从用户请求中提取数据,调用合适的业务逻辑进行处理,并返回响应给用户。
控制器在Web应用程序中起到了桥梁的作用,它接收来自用户的请求,并根据请求的内容决定如何处理。控制器通常包含多个处理方法,每个方法对应不同的请求路径和请求方法,用于处理不同的请求。
控制器的主要作用包括:
- 接收请求:控制器监听来自客户端的请求,根据请求的路径和方法来确定调用哪个处理方法。
- 处理请求:控制器中的处理方法会根据业务逻辑对请求进行处理,可能会操作数据库、调用其他服务等。
- 提取数据:控制器从请求中提取所需的数据,例如请求参数、请求头、请求体等。
- 调用服务:控制器可能需要调用其他服务或组件来完成请求的处理,例如调用业务逻辑组件、数据访问组件等。
- 返回响应:控制器根据请求的处理结果生成响应数据,可以是HTML页面、JSON数据、XML数据等。
在Web开发中,控制器通常与视图(View)和模型(Model)一起工作,通过模型从数据库或其他数据源中获取数据,并将数据传递给视图进行渲染,最终返回给用户显示。
- 控制器的表现形式就是注解
@RestController
- 是一个注解,用于将类标记为RESTful风格的控制器。
@RequestMapping
- 这个注解使得被拦截的请求能与被注解的方法进行配对,配对成功了,就按照方法内的代码工作。其中,返回是返回给客户端的
**基本用法:**在控制器类或方法上使用 @RequestMapping
注解,指定请求的 URL 路径。例如:
javaCopy code@RequestMapping("/hello")
public String hello() {
return "Hello, World!";
- 该注解有很多用法,自行百度
为什么你能通过一小段代码来访问网页?(重点)
要明白这件事,首先要知道我们是如何访问网站的
访问网页的本质涉及多个技术层面,从用户输入网址到最终在浏览器上看到页面的过程包含了多个步骤:
-
域名解析:当你在浏览器中输入一个网址(URL),比如
http://www.example.com
,浏览器首先需要将这个域名解析成对应的 IP 地址。这个过程通过域名系统(DNS)完成,将易于记忆的域名映射到实际的服务器 IP 地址。(本地) -
发起连接:一旦浏览器获得了服务器的 IP 地址,它就会通过网络协议(通常是 HTTP 或 HTTPS)与服务器建立连接。这个过程涉及多个网络层的交互,包括 TCP/IP 协议等。(网络通信)
-
发送请求:浏览器发送一个 HTTP 请求给服务器,这个请求包含了请求的类型(GET、POST 等)、路径、头部信息(例如浏览器类型)、可能的请求体(对于 POST 请求)等。(网络通信)
-
服务器处理:服务器接收到请求后,根据请求的路径以及其他信息,决定要执行哪些操作。这通常涉及到服务器端的应用程序,比如一个 Web 应用程序。在以上的图片中,就是 Spring Boot 中的控制器方法。(服务器本地)
-
生成响应:服务器处理请求后,会生成一个 HTTP 响应。这个响应包括了响应的状态码(例如 200 OK、404 Not Found)、响应头部(例如内容类型),以及响应体(实际的数据内容)。(服务器本地)
-
传输响应:服务器将生成的 HTTP 响应通过网络传输回浏览器。(网络通信)
-
浏览器处理:浏览器接收到响应后,会根据响应的内容类型(例如 HTML、CSS、JavaScript 等)进行处理。浏览器会解析 HTML,构建 DOM(文档对象模型),加载和解析 CSS 样式,执行 JavaScript 等操作。(本地)
-
渲染页面:浏览器根据 DOM 结构和 CSS 样式对页面进行渲染,最终在浏览器窗口中呈现出用户可见的页面。(本地)
当你启动 Spring Boot 项目并且访问 http://localhost:8080
或其他定义的路径时,Spring Boot 内置的 Web 服务器( Tomcat 或其他容器)会拦截这些请求,并将请求映射到相应的控制器方法。控制器方法执行完成后,返回的内容会被直接写入 HTTP 响应,然后返回给浏览器进行显示。
响应数据
- 以上几个方法被称为功能接口
- 这样开发不便管理
package com.itheima.pojo;
/**
* 统一响应结果封装类
*/
public class Result {
private Integer code ;//1 成功 , 0 失败
private String msg; //提示信息
private Object data; //数据 date
public Result() {
}
public Result(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static Result success(Object data){
return new Result(1, "success", data);
}
public static Result success(){
return new Result(1, "success", null);
}
public static Result error(String msg){
return new Result(0, msg, null);
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
@RequestMapping("/hello")
public Result hello(){
System.out.println("Hello World ~");
//return new Result(1,"success","Hello World ~");
return Result.success("Hello World ~");
}
- 仔细观看以上代码就懂了
案列
//文件寻址
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
this.getClass()
:获取当前对象所属的类。getClassLoader()
:获取类加载器对象。getResource("emp.xml")
:通过类加载器对象的getResource()
方法,传入资源文件的相对路径(相对于类路径),返回一个URL
对象,指向该资源文件。getFile()
:通过URL
对象的getFile()
方法,获取资源文件在文件系统中的绝对路径。
最终,将获取到的绝对路径赋值给file
变量
关于类加载器
类加载器对象(ClassLoader Object)是Java中用于加载类文件的工具。它负责将类的字节码文件加载到Java虚拟机中,并转换为可执行的类对象。
在Java中,每个类加载器都是一个ClassLoader对象。ClassLoader对象负责查找类文件、加载类文件、定义类和管理类的生命周期。每个类加载器都有一个父类加载器(除了引导类加载器),它们按照一定的层次结构进行组织。
package com.itheima.controller;
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class EmpController {
@RequestMapping("/listEmp")
public Result list(){
//1. 加载并解析emp.xml(获取数据)
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
System.out.println(file);
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);//XmlParserUtils对象用来处理xml文件
//2. 对数据进行转换处理 - gender, job(处理数据)
empList.stream().forEach(emp -> {//使用lambda表达式,相当于js中的箭头函数。
//处理 gender 1: 男, 2:
String gender = emp.getGender();//类里面
//为什么emp没有声明为Emp类型的数据却能使用Emp类中的方法?
//因为lambda表达式中的emp(这个位置的变量)是通过上下文来判断类型。
//而empList是Emp类数据
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if("2".equals(job)){
emp.setJob("班主任");
}else if("3".equals(job)){
emp.setJob("就业指导");
}
});
//3. 响应数据
return Result.success(empList);
}
}
package com.itheima.pojo;
public class Emp {
private String name;
private Integer age;
private String image;
private String gender;
private String job;
public Emp() {
}
public Emp(String name, Integer age, String image, String gender, String job) {
this.name = name;
this.age = age;
this.image = image;
this.gender = gender;
this.job = job;
}
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 String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", age=" + age +
", image='" + image + '\'' +
", gender='" + gender + '\'' +
", job='" + job + '\'' +
'}';
}
}
见
https://www.bilibili.com/video/BV1m84y1w7Tb?p=74&spm_id_from=pageDriver&vd_source=077127c579b82c23164b07dbc24cd570
分层解耦
三层结构
-
使得一个类或者一个接口只做一件事
-
其中,数据的来源可能有很多。因此凭借接口实现dao层
- 这样将代码单一功能化,也称为高内聚
分层解耦(高内聚低耦合(最好没有耦合))
- 因为引用,现在会有耦合
- 要切换成b类,不止一处地方需要变动
- 使用容器来解耦
controller层与前端交互
控制反转
- 一种设计的思路
-
@Component
是一个注解(Annotation),在Spring框架中用于标识一个类为组件(Component)。在Spring中,组件是指可被自动扫描和实例化的类。通过使用
@Component
注解,告诉Spring框架将被标注的类作为组件进行管理。被标注的EmpserviceA称为loc中的bean -
@Autowired
是一个注解(Annotation),在Spring框架中用于实现依赖注入(Dependency Injection)。依赖注入是指将一个对象的依赖关系由容器动态地注入到对象中,而不是由对象自己创建或查找依赖对象。通过使用
@Autowired
注解,可以告诉Spring框架自动装配相应的依赖对象。 -
容器需要把要用的都加到容器里去
当要切换不同的dao层时,就通过操作@Component来改变容器存储不同
- 寻找RestController的实现
组件扫描
- 指定后,默认扫描包会更改,因此还要加上原来的包
- Primary更改优先级别
- Qualifier/Resource设置访问
数据库(有重点)
通用规则
流程
- 创建数据库一般有这两个字段
DQL
查询所有字段不要用星号,效率低下
-- if语句
select if(gender=1,'男性','女性'),count(*)
from tb_emp group by gender ;
-- case语句
select (case job when 1 then '班主任' when 2 then '讲师' when 3 then '学工主管' when 4 then '教研主管' else '无职位' end)
,count(*)
from tb_emp
group by job;
表关系及对应
一对多
- 多的一方添加外键
一对一
多对多
多表设计的流程
- 步骤一画er图
多表查询
内连接
外连接
- 左外连接会包含左表中的所有数据
- 右外连接会包含右表中的所有数据
- 可以解决一方值为空,对应不到对方的情况
- 基本用左外,右外可以替换成左外
子查询
- 以上出现了两种方式
-- 查询每个分类下最贵的菜品,展示出分类的名称、最贵的菜品的价格
select c.name,max(d.price)-- 不一定要用子查询,可以直接筛选出最贵的
from category c,
dish d
where d.category_id = c.id
group by c.id;
事物
索引
- 索引将原本的挨个查询变成使用数据结构来查询
写MySQl代码的方式(重点)
1、分析需要用到那几张表(提前做好er图),然后再开始写代码
2、先写查询条件再写查询显示项
mysql语句的难点(重点)
优先级,你需要知道每个语句的优先级
-- 查询每个分类下最贵的菜品,展示出分类的名称、最贵的菜品的价格
select c.name,max(d.price)
from category c,
dish d
where d.category_id = c.id
group by c.id;
- 比如以上的案列,我以为是先执行语句是从左边执行到右边,于是认为先查询最贵的价格了,而最贵的价格只有一个,因此只会出现一个拥有最贵的分类。但代码不是这么运作的。
一个用的到的函数—concat()
- 函数格式是CONCAT(‘参数1’,’参数2’,’参数3’)
- 使用该函数可以将括号中的参数拼接在一起,用于sql的预编译
JDBC
- sun公司提供的api
数据库链接池
- 用户使用数据库连接池用完了还回去
切换数据库链接池
在配置文件中增加德鲁伊数据库链接池即可
//德鲁伊数据库链接词
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
lombik(注解简化代码)
-
写在类的前面
-
原理就是根据注解生成相应的方法
Mybatis基于注解来配置sql
- 只需要定义接口就好不需要定义实现类
#配置数据库中的链接信息
# mysql项目的application.properties配置
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456
@Mapper
@Mapper
是一个MyBatis注解,用于标注DAO层的Mapper接口。
MyBatis是一个支持定制化SQL、存储过程以及高级映射的优秀持久层框架。在MyBatis中,DAO层的Mapper接口负责与数据库交互,封装各种CRUD操作。
@Mapper
注解用于告诉MyBatis框架,该接口需要被自动实现为Mapper代理。MyBatis会在应用启动时自动扫描带有@Mapper
注解的接口,并为这些接口生成实现类。
-
标注在类上面,即可使用
-
也是交给loc容器管理
@Select与其他的语句映射
查询就是@select,删除就是@delete
MyBatis通过注解的方式,可以直接将SQL语句映射到DAO方法上,无需编写XML映射文件。
//根据ID删除数据
@Delete("delete from emp where id=#{id}")
//mybatis实现了根据 #{} 来实现注释绑定的注释方法传参
public void delete(Integer id);
//public int delete(Integer id);
//可以有返回值。返回值意思是影响的记录数
Test
- 使用@test注解可以进行测试
日志与预编译
- 通过?(预编译)使得能够高性能的工作
- 登录的本质就是将输入的用户名和密码拿去查询,看是否能查到
其中count(*)能够统计查询到的总行数
- 使用$()是直接拼接字符串
- 使用#()是使用预编译
SQL注入
-
没有使用预编译的SQL可以通过输入密码或者账号时,改为mysql语句的形式,来修改。
-
使用预编译,将把输入的字符都变为一个参数,代替问号
Mybatis使用
- 注意,上面的链接那边要填写自己的数据库名称
配置sql
增加员工(涉及主键返回问题)
- 出现以上数据过多时,可以通过列多个参数,也可以通过使用一个对象
- 以上字母是emp中的属性名称
多对多关系(两张表)
- 需要使用共通的id,使用@Options
更新数据
- 以上想要实现模糊查询,但是#{}会被替换成?,所以不能使用。而是要用 ${}
- 使用concat函数解决
//方式二
@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +
"entrydate between #{begin} and #{end} order by update_time desc ")
public List<Emp> list(String name, Short gender, LocalDate begin , LocalDate end);
变量映射
方案一: 给字段起别名, 让别名与实体类属性一致
@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注解手动映射封装
@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);
- 方案三配置application.properties文件
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库链接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#3306后面内容是要链接数据库的名称
#链接数据库的用户名
spring.datasource.username=root
#链接数据库的密码
spring.datasource.password=123456
#开启mybatis的驼峰命名自动映射开关 a_bbb ----> aBbb
mybatis.configuration.map-underscore-to-camel-case=true
#配置mybatis的日志 指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
XML文件定义的三种规范
一、同包同名
比如我要配置com.example.webcase下mapper的xml,那么便要如以下一样
二、一个xml文件对应一个接口,且名称完全一致
如图
三、xml中SQL语句的id要与mapper接口中的方法名保持一致,并且放回类型也是一致的
- mapper接口中的方法名为list,返回值是List
- xml中的id也为list,返回值为List
XML映射文件来配置sql
-
一个接口与一个映射文件相对应
-
红色是要求一,紫色是要求二
<?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">
- 每次配置xml文件时候,根据配置东西的不同要选择不同的约束。比如以上就是mysql的约束
访问mybatis中文网获得
https://mybatis.net.cn/getting-started.html
动态SQL
- 指查询条件随着用户所填变化而变化
- 以上if有一个缺陷,当name为空而gender有值的时候,会出现语法错误
动态查询
- 使用where解决
动态更新
- 通过Alt+回车可以自动生成动态sql代码
-
不同的关键字能生成不同
-
也会if限制,多个 ,
批量删除
代码复用
- 用于代码的复用性
配置文件
使用application.properties配置文件
不同的配置文件
011)]
XML映射文件来配置sql
[外链图片转存中…(img-x4YKjqVs-1714007817011)]
-
一个接口与一个映射文件相对应
-
红色是要求一,紫色是要求二
<?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">
- 每次配置xml文件时候,根据配置东西的不同要选择不同的约束。比如以上就是mysql的约束
访问mybatis中文网获得
https://mybatis.net.cn/getting-started.html
[外链图片转存中…(img-x1DGCwa8-1714007817011)]
[外链图片转存中…(img-pyMgdDtU-1714007817012)]
[外链图片转存中…(img-ns5YgnHb-1714007817012)]
动态SQL
[外链图片转存中…(img-TMZ5N4Z2-1714007817012)]
- 指查询条件随着用户所填变化而变化
- 以上if有一个缺陷,当name为空而gender有值的时候,会出现语法错误
动态查询
[外链图片转存中…(img-7qvdoCno-1714007817013)]
- 使用where解决
动态更新
[外链图片转存中…(img-POn4JMiQ-1714007817014)]
- 通过Alt+回车可以自动生成动态sql代码
[外链图片转存中…(img-1361I06g-1714007817014)]
-
不同的关键字能生成不同
-
也会if限制,多个 ,
[外链图片转存中…(img-LuWRjqH0-1714007817014)]
[外链图片转存中…(img-DHfKCUpS-1714007817015)]
批量删除
[外链图片转存中…(img-IYeQxTWd-1714007817015)]
代码复用
[外链图片转存中…(img-lSHub1Zt-1714007817016)]
- 用于代码的复用性
配置文件
使用application.properties配置文件
[外链图片转存中…(img-c56FDcEe-1714007817016)]
[外链图片转存中…(img-Tr1oaWUZ-1714007817016)]
不同的配置文件
[外链图片转存中…(img-3gaN4fAv-1714007817017)]
[外链图片转存中…(img-uM9nInYb-1714007817017)]
[外链图片转存中…(img-cXZyXj6a-1714007817018)]
[外链图片转存中…(img-uhWTISOU-1714007817018)]