• 快速入门Web开发(中)后端开发(有重点)


    你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github gitee

    如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^)

    想看更多 那就点个关注吧 我会尽力带来有趣的内容
    CSDN 图片导入做的不是很好,因此如果有没有出现的图片请去这里 传送 https://juejin.cn/user/1942157160101860/posts
    掘金的文档写作体验比CSDN好多了。。。。里面好像也有不少大佬

    快速入门Web开发(中)后端开发(有重点)

    image-20230814133911909

    为什么你能通过一小段代码来访问网页?(重点)

    image-20230817141426063

    要明白这件事,首先要知道我们是如何访问网站的

    访问网页的本质涉及多个技术层面,从用户输入网址到最终在浏览器上看到页面的过程包含了多个步骤:

    1. 域名解析:当你在浏览器中输入一个网址(URL),比如 http://www.example.com,浏览器首先需要将这个域名解析成对应的 IP 地址。这个过程通过域名系统(DNS)完成,将易于记忆的域名映射到实际的服务器 IP 地址。(本地)

    2. 发起连接:一旦浏览器获得了服务器的 IP 地址,它就会通过网络协议(通常是 HTTP 或 HTTPS)与服务器建立连接。这个过程涉及多个网络层的交互,包括 TCP/IP 协议等。(网络通信)

    3. 发送请求:浏览器发送一个 HTTP 请求给服务器,这个请求包含了请求的类型(GET、POST 等)、路径、头部信息(例如浏览器类型)、可能的请求体(对于 POST 请求)等。(网络通信)

    4. 服务器处理:服务器接收到请求后,根据请求的路径以及其他信息,决定要执行哪些操作。这通常涉及到服务器端的应用程序,比如一个 Web 应用程序。在以上的图片中,就是 Spring Boot 中的控制器方法。(服务器本地)

    5. 生成响应:服务器处理请求后,会生成一个 HTTP 响应。这个响应包括了响应的状态码(例如 200 OK、404 Not Found)、响应头部(例如内容类型),以及响应体(实际的数据内容)。(服务器本地)

    6. 传输响应:服务器将生成的 HTTP 响应通过网络传输回浏览器。(网络通信)

    7. 浏览器处理:浏览器接收到响应后,会根据响应的内容类型(例如 HTML、CSS、JavaScript 等)进行处理。浏览器会解析 HTML,构建 DOM(文档对象模型),加载和解析 CSS 样式,执行 JavaScript 等操作。(本地)

    8. 渲染页面:浏览器根据 DOM 结构和 CSS 样式对页面进行渲染,最终在浏览器窗口中呈现出用户可见的页面。(本地)

    当你启动 Spring Boot 项目并且访问 http://localhost:8080 或其他定义的路径时,Spring Boot 内置的 Web 服务器( Tomcat 或其他容器)会拦截这些请求,并将请求映射到相应的控制器方法。控制器方法执行完成后,返回的内容会被直接写入 HTTP 响应,然后返回给浏览器进行显示。

    后端工具

    Maven

    image-20230814134030079

    image-20230814134131233

    • 依赖管理:因为要导入的jar包很多,所以使用Maven来快捷、方便的进行导包
    • 统一的结构:idea和eclipse等开发软件生成的项目结构不一样,使用maven可以直接导入
    • image-20230814134736034

    image-20230814134825447

    • 快速的完成以上功能
    https://maven.apache.org/
    maven的架构

    image-20230814135311572

    • 本地没有jar包的情况下,看有无链接私服,有则去私服找,没有就去中央找。私服本身没有,则私服去中央找

    image-20230814135504050

    image-20230814184141573

    • 其中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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 通过mvn -v校验是否成功。成功标志为出现版本号
    配置maven

    image-20230814185336520

    • 将maven使用jdk和编译器使用的设置成相同

    image-20230814191035396

    • 在idea2022中直接创建普通的项目,选择java中的maven即可

    image-20230814200120942

    image-20230814200007935

    Maven项目导入

    image-20230814200814378

    • 调出maven

    image-20230814200833548

    • 点击加号即可
    添加Maven依赖
    
        
            
                ch.qos.logback
                logback-classic
                1.2.3
            
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • :这个标签是pom.xml文件的根标签,用于包含所有的依赖项。
    • :这个标签用于描述一个具体的依赖项。
    • :这个标签指定了依赖项的组织或公司的唯一标识符。在这个例子中,依赖项的groupId是ch.qos.logback,表示这个依赖项是由logback项目组提供的。
    • :这个标签指定了依赖项的名称或标识符。在这个例子中,依赖项的artifactId是logback-classic,表示这个依赖项是logback日志框架的经典版本。
    • :这个标签指定了依赖项的版本号。在这个例子中,依赖项的版本号是1.2.3,表示使用logback-classic的1.2.3版本。
    什么是依赖

    依赖就好比是一个软件模块需要借助其他模块或组件才能正常工作。类比一下,你可以把依赖想象成一个人需要使用其他人的工具才能完成任务。比如,你要修理自行车,但是你需要用到一个扳手,而你自己没有。这时,你就需要依赖别人借给你一个扳手才能完成修理任务。
    在软件开发中,也是类似的情况。一个软件模块可能需要使用其他模块提供的功能,比如某个库或框架。这样,它就需要在项目中引入这个库或框架的代码,以便能够调用它提供的功能。为了方便管理这些依赖关系,开发人员通常会使用依赖管理工具。这个工具会帮助自动下载和引入所需的库、框架或其他依赖项,确保项目能够正常构建和运行。

    • 点击重写加载后
    • image-20230814201550985

    在maven页面可以看到依赖是否生效

    依赖与jar包

    依赖与jar包作用是一样的,但是依赖更容易维护与直接修改

    依赖特性

    image-20230814202123906

    image-20230814203627849

    image-20230814203822822

    image-20230814204058265

    image-20230814204130144

    • 运行后面的依赖,前面的依赖也会执行

    image-20230814204202348

    • 在同一套生命周期中,运行后面阶段,前面阶段都会运行

    image-20230814204244505

    • maven所有操作由插件执行

    Tomcat

    • 一个web服务器

    image-20230815210700859

    • 默认端口号为8080

    image-20230815211422723

    image-20230815211606528

    image-20230815211621832

    postman

    想要发出post请求得自己编写程序,可以用postman来代替

    SpringBoot初体验

    image-20230814204917978

    image-20230815100644949

    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";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 运行SpringbootOneApplication这个文件

    image-20230815214140858

    image-20230815214518840

    image-20230815214547303

    image-20230816081024440

    • Tomcat又称servlet容器

    image-20230816081403878

    • BS架构体验一般指对宽带需求大,现在已经不是问题
    • CS架构虽然可以在本地处理一些数据,但不同平台要开发不同的版本

    http协议

    image-20230815201341081

    image-20230815202042539

    • 请求头和请求体之间的空行是必须的

    请求

    • image-20230815201718780

    image-20230815202235820

    路径由

    image-20230815202326423

    变成

    image-20230815202402362

    • get请求的参数就在这里面了(通过?来实现),而post请求的参数不在

    响应

    image-20230815204032139

    image-20230815204046530

    image-20230815204145246

    • 重定向指的是原来要访问的资源被转移到了另一台服务器或者本服务器的另一个位置了。这时候服务器会放回一个3开头的状态码和被转移后资源的位置,受到返回的浏览器会自动找这个资源
    状态码大类
    状态码分类说明
    1xx响应中——临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它
    2xx成功——表示请求已经被成功接收,处理已完成
    3xx重定向——重定向到其它地方:它让客户端再发起一个请求以完成整个处理。
    4xx客户端错误——处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等
    5xx服务器端错误——处理发生错误,责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等
    常见的响应状态码
    状态码英文描述解释
    200OK客户端请求成功,即处理成功,这是我们最想看到的状态码
    302Found指示所请求的资源已移动到由Location响应头给定的 URL,浏览器会自动重新访问到这个页面
    304Not Modified告诉客户端,你请求的资源至上次取得后,服务端并未更改,你直接用你本地缓存吧。隐式重定向
    400Bad Request客户端请求有语法错误,不能被服务器所理解
    403Forbidden服务器收到请求,但是拒绝提供服务,比如:没有权限访问相关资源
    404Not Found请求资源不存在,一般是URL输入有误,或者网站资源被删除了
    405Method Not Allowed请求方式有误,比如应该用GET请求方式的资源,用了POST
    428Precondition Required服务器要求有条件的请求,告诉客户端要想访问该资源,必须携带特定的请求头
    429Too Many Requests指示用户在给定时间内发送了太多请求(“限速”),配合 Retry-After(多长时间后可以请求)响应头一起使用
    431 Request Header Fields Too Large请求头太大,服务器不愿意处理请求,因为它的头部字段太大。请求可以在减少请求头域的大小后重新提交。
    500Internal Server Error服务器发生不可预期的错误。服务器出异常了,赶紧看日志去吧
    503Service Unavailable服务器尚未准备好处理请求,服务器刚刚启动,还未初始化好

    状态码大全:https://cloud.tencent.com/developer/chapter/13553

    image-20230815210511295

    SpringBoot

    HttpServletRequest对象

    HttpServletRequest是Java Servlet API中的一个接口,用于表示客户端的HTTP请求。它提供了许多方法来获取关于请求的信息,如请求的URL、参数、头部信息等。通过HttpServletRequest,可以从客户端接收数据并对请求进行处理。

    HttpServletRequest对象提供了以下方法来获取请求的各种信息:

    1. 请求行信息:如请求的URL、请求的方法(GET、POST等)、HTTP协议版本等。
    2. 请求头信息:如User-Agent、Referer、Accept-Language等。
    3. 请求参数:可以通过getParameter()方法来获取请求的参数,如表单提交的参数、URL中的查询参数等。
    4. 请求体信息:对于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";
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果

    image-20230818155713620

    image-20230818155726140

    SptingBoot版本
     @RequestMapping("/simpleParam")
      public String simpleParam(String name,int age) {//此处也可以改为Integer
        System.out.printf(name+":"+age);
        return "OK";
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 结果一样
    以上都是get请求,如何使用post请求呢?

    image-20230818161816944

    • 参数名不一致时候会放回null
    参数名映射

    image-20230818162319948

    image-20230818162401135

    实体参数映射(设置网站内容页)

    image-20230818162528467

    image-20230818162709330

    复杂实体

    image-20230818162747001

    • 通过创建两个类来满足需要。一个类包含另一个

    image-20230818163051065

    image-20230818163107487

    数组集合参数

    image-20230818163214699

    • 只要数组名相同

    • image-20230818163350728

    • 默认封装成数组,需要加一下符号

    image-20230819090312561

    image-20230819090432879

    日期参数

    image-20230819090533039

    json参数

    image-20230819090822511

    • json格式数据使用不了get

    image-20230819090930068

    • 需要做到key与实体对象的属性名相同
    路径参数

    image-20230819091349972

    • @PathVariable是Spring框架中的一个注解,用于将URL中的参数绑定到方法的参数上。

      可以使用@PathVariable注解来获取URL中的动态参数。这些参数可以是在URL路径中的一部分,用花括号{}括起来,并通过@PathVariable注解来绑定到方法的参数上。

    • 使用这个注解后,可以使得访问路径是变化的。如 localhost:8080/path/2和localhost:8080/10

    image-20230819091938301

    什么是控制器?

    控制器(Controller)是MVC(Model-View-Controller)设计模式中的一个组件,用于接收用户的请求并处理请求的逻辑。控制器负责从用户请求中提取数据,调用合适的业务逻辑进行处理,并返回响应给用户。

    控制器在Web应用程序中起到了桥梁的作用,它接收来自用户的请求,并根据请求的内容决定如何处理。控制器通常包含多个处理方法,每个方法对应不同的请求路径和请求方法,用于处理不同的请求。

    控制器的主要作用包括:

    1. 接收请求:控制器监听来自客户端的请求,根据请求的路径和方法来确定调用哪个处理方法。
    2. 处理请求:控制器中的处理方法会根据业务逻辑对请求进行处理,可能会操作数据库、调用其他服务等。
    3. 提取数据:控制器从请求中提取所需的数据,例如请求参数、请求头、请求体等。
    4. 调用服务:控制器可能需要调用其他服务或组件来完成请求的处理,例如调用业务逻辑组件、数据访问组件等。
    5. 返回响应:控制器根据请求的处理结果生成响应数据,可以是HTML页面、JSON数据、XML数据等。

    在Web开发中,控制器通常与视图(View)和模型(Model)一起工作,通过模型从数据库或其他数据源中获取数据,并将数据传递给视图进行渲染,最终返回给用户显示。

    • 控制器的表现形式就是注解

    @RestController

    • 是一个注解,用于将类标记为RESTful风格的控制器。

    @RequestMapping

    • 这个注解使得被拦截的请求能与被注解的方法进行配对,配对成功了,就按照方法内的代码工作。其中,返回是返回给客户端的

    **基本用法:**在控制器类或方法上使用 @RequestMapping 注解,指定请求的 URL 路径。例如:

    javaCopy code@RequestMapping("/hello")
    public String hello() {
      return "Hello, World!";
    
    
    • 1
    • 2
    • 3
    • 4
    • 该注解有很多用法,自行百度

    为什么你能通过一小段代码来访问网页?(重点)

    image-20230817141426063

    要明白这件事,首先要知道我们是如何访问网站的

    访问网页的本质涉及多个技术层面,从用户输入网址到最终在浏览器上看到页面的过程包含了多个步骤:

    1. 域名解析:当你在浏览器中输入一个网址(URL),比如 http://www.example.com,浏览器首先需要将这个域名解析成对应的 IP 地址。这个过程通过域名系统(DNS)完成,将易于记忆的域名映射到实际的服务器 IP 地址。(本地)

    2. 发起连接:一旦浏览器获得了服务器的 IP 地址,它就会通过网络协议(通常是 HTTP 或 HTTPS)与服务器建立连接。这个过程涉及多个网络层的交互,包括 TCP/IP 协议等。(网络通信)

    3. 发送请求:浏览器发送一个 HTTP 请求给服务器,这个请求包含了请求的类型(GET、POST 等)、路径、头部信息(例如浏览器类型)、可能的请求体(对于 POST 请求)等。(网络通信)

    4. 服务器处理:服务器接收到请求后,根据请求的路径以及其他信息,决定要执行哪些操作。这通常涉及到服务器端的应用程序,比如一个 Web 应用程序。在以上的图片中,就是 Spring Boot 中的控制器方法。(服务器本地)

    5. 生成响应:服务器处理请求后,会生成一个 HTTP 响应。这个响应包括了响应的状态码(例如 200 OK、404 Not Found)、响应头部(例如内容类型),以及响应体(实际的数据内容)。(服务器本地)

    6. 传输响应:服务器将生成的 HTTP 响应通过网络传输回浏览器。(网络通信)

    7. 浏览器处理:浏览器接收到响应后,会根据响应的内容类型(例如 HTML、CSS、JavaScript 等)进行处理。浏览器会解析 HTML,构建 DOM(文档对象模型),加载和解析 CSS 样式,执行 JavaScript 等操作。(本地)

    8. 渲染页面:浏览器根据 DOM 结构和 CSS 样式对页面进行渲染,最终在浏览器窗口中呈现出用户可见的页面。(本地)

    当你启动 Spring Boot 项目并且访问 http://localhost:8080 或其他定义的路径时,Spring Boot 内置的 Web 服务器( Tomcat 或其他容器)会拦截这些请求,并将请求映射到相应的控制器方法。控制器方法执行完成后,返回的内容会被直接写入 HTTP 响应,然后返回给浏览器进行显示。

    响应数据

    image-20230819092035893

    image-20230819092515108

    • 以上几个方法被称为功能接口
    • 这样开发不便管理

    image-20230819092613743

    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 +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
        @RequestMapping("/hello")
        public Result hello(){
            System.out.println("Hello World ~");
            //return new Result(1,"success","Hello World ~");
            return Result.success("Hello World ~");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 仔细观看以上代码就懂了

    image-20230819154058552

    案列

    image-20230819155202293

    //文件寻址
     String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
    
    
    • 1
    • 2
    • 3
    1. this.getClass():获取当前对象所属的类。
    2. getClassLoader():获取类加载器对象。
    3. getResource("emp.xml"):通过类加载器对象的getResource()方法,传入资源文件的相对路径(相对于类路径),返回一个URL对象,指向该资源文件。
    4. 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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    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 + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    https://www.bilibili.com/video/BV1m84y1w7Tb?p=74&spm_id_from=pageDriver&vd_source=077127c579b82c23164b07dbc24cd570

    分层解耦

    三层结构

    image-20230819175558776

    • 使得一个类或者一个接口只做一件事

    • 其中,数据的来源可能有很多。因此凭借接口实现dao层

    image-20230819192654901

    image-20230819192720170

    • 这样将代码单一功能化,也称为高内聚

    分层解耦(高内聚低耦合(最好没有耦合))

    image-20230819193054985

    • 因为引用,现在会有耦合

    • 要切换成b类,不止一处地方需要变动
    • 使用容器来解耦

    image-20230819193430342

    controller层与前端交互

    控制反转

    • 一种设计的思路

    image-20230819193633886

    • @Component是一个注解(Annotation),在Spring框架中用于标识一个类为组件(Component)。

      在Spring中,组件是指可被自动扫描和实例化的类。通过使用@Component注解,告诉Spring框架将被标注的类作为组件进行管理。被标注的EmpserviceA称为loc中的bean

    • @Autowired是一个注解(Annotation),在Spring框架中用于实现依赖注入(Dependency Injection)。

      依赖注入是指将一个对象的依赖关系由容器动态地注入到对象中,而不是由对象自己创建或查找依赖对象。通过使用@Autowired注解,可以告诉Spring框架自动装配相应的依赖对象。

    • 容器需要把要用的都加到容器里去

    当要切换不同的dao层时,就通过操作@Component来改变容器存储不同

    image-20230819204604449

    • 寻找RestController的实现

    image-20230819204231554

    image-20230819204326038

    组件扫描

    image-20230819204914394

    image-20230819205034529

    • 指定后,默认扫描包会更改,因此还要加上原来的包

    image-20230819205445354

    • Primary更改优先级别
    • Qualifier/Resource设置访问

    image-20230819205612530

    数据库(有重点)

    image-20230819205832656

    image-20230819205928970

    image-20230819210451187

    image-20230819210604445

    通用规则

    image-20230819210633288

    image-20230819210754866

    流程

    image-20230819210933250

    image-20230819212026490

    image-20230820092133254

    image-20230820165427306

    • 创建数据库一般有这两个字段

    image-20230820165656633

    image-20230820170459003

    DQL

    image-20230820170725484

    查询所有字段不要用星号,效率低下

    image-20230820184354108

    image-20230820184855913

    image-20230820190911999

    image-20230820191322391

    image-20230820191449731

    -- 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    image-20230820195038839

    image-20230820195103819

    表关系及对应

    一对多

    image-20230820203323898

    image-20230820203701278

    image-20230820205704964

    • 多的一方添加外键
    一对一

    image-20230820205829382

    多对多

    image-20230820210033094

    多表设计的流程

    • 步骤一画er图

    image-20230820210642354

    image-20230820211057866

    image-20230820211107070

    image-20230820211116048

    image-20230820211128707

    多表查询

    内连接

    image-20230820211853123

    image-20230820212140491

    外连接

    -

    • 左外连接会包含左表中的所有数据
    • 右外连接会包含右表中的所有数据
    • 可以解决一方值为空,对应不到对方的情况
    • 基本用左外,右外可以替换成左外

    image-20230820212548134

    子查询

    image-20230820212625557

    image-20230820212725729

    image-20230820213006371

    • 以上出现了两种方式

    image-20230820213055727

    -- 查询每个分类下最贵的菜品,展示出分类的名称、最贵的菜品的价格
    select c.name,max(d.price)-- 不一定要用子查询,可以直接筛选出最贵的
    from category c,
         dish d
    where d.category_id = c.id
    group by c.id;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    事物

    image-20230831085934329

    image-20230831090155081

    索引

    image-20230904125849617

    • 索引将原本的挨个查询变成使用数据结构来查询

    image-20230904130057073

    image-20230904130548526

    image-20230904130508383

    image-20230904140253253

    image-20230904140311703

    写MySQl代码的方式(重点)

    1、分析需要用到那几张表(提前做好er图),然后再开始写代码

    2、先写查询条件再写查询显示项

    mysql语句的难点(重点)

    优先级,你需要知道每个语句的优先级

    image-20230821110151079

    -- 查询每个分类下最贵的菜品,展示出分类的名称、最贵的菜品的价格
    select c.name,max(d.price)
    from category c,
         dish d
    where d.category_id = c.id
    group by c.id;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 比如以上的案列,我以为是先执行语句是从左边执行到右边,于是认为先查询最贵的价格了,而最贵的价格只有一个,因此只会出现一个拥有最贵的分类。但代码不是这么运作的。

    一个用的到的函数—concat()

    • 函数格式是CONCAT(‘参数1’,’参数2’,’参数3’)
    • 使用该函数可以将括号中的参数拼接在一起,用于sql的预编译

    JDBC

    • sun公司提供的api

    image-20230821183545242

    image-20230821183652525

    image-20230821183758600

    数据库链接池

    image-20230821184035024

    • 用户使用数据库连接池用完了还回去

    image-20230821184618520

    切换数据库链接池

    在配置文件中增加德鲁伊数据库链接池即可

    //德鲁伊数据库链接词
    <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>druid-spring-boot-starter</artifactId>
       <version>1.2.8</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20230821185356328

    lombik(注解简化代码)

    image-20230821185538703

    image-20230821185605351

    • 写在类的前面

    • 原理就是根据注解生成相应的方法

    image-20230821190746504

    Mybatis基于注解来配置sql

    image-20230821152916276

    • 只需要定义接口就好不需要定义实现类
    #配置数据库中的链接信息
    # 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    @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);
     //可以有返回值。返回值意思是影响的记录数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20230821202134399

    Test

    • 使用@test注解可以进行测试

    日志与预编译

    image-20230904101721085

    image-20230904101857307

    • 通过?(预编译)使得能够高性能的工作

    image-20230904102225560

    • 登录的本质就是将输入的用户名和密码拿去查询,看是否能查到

    其中count(*)能够统计查询到的总行数

    image-20230904123426467

    • 使用$()是直接拼接字符串
    • 使用#()是使用预编译

    image-20230904123618089

    SQL注入

    image-20230904101917252

    image-20230904123014411

    • 没有使用预编译的SQL可以通过输入密码或者账号时,改为mysql语句的形式,来修改。

    • 使用预编译,将把输入的字符都变为一个参数,代替问号

    Mybatis使用

    image-20230821162355520

    image-20230821162545972

    • 注意,上面的链接那边要填写自己的数据库名称

    image-20230821162607648

    image-20230821162614418

    配置sql

    image-20230821162843721

    image-20230821163115531

    增加员工(涉及主键返回问题)

    image-20230904124656807

    • 出现以上数据过多时,可以通过列多个参数,也可以通过使用一个对象

    image-20230904124854578

    • 以上字母是emp中的属性名称

    image-20230904125003350

    多对多关系(两张表)

    image-20230904140724424

    • 需要使用共通的id,使用@Options

    image-20230904140920165

    更新数据

    image-20230904141353378

    image-20230904142717134

    image-20230904145216524

    • 以上想要实现模糊查询,但是#{}会被替换成?,所以不能使用。而是要用 ${}

    image-20230904150002081

    • ​ 使用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);
    
    • 1
    • 2
    • 3
    • 4

    image-20230904150247629

    变量映射

    image-20230904142731893

        方案一: 给字段起别名, 让别名与实体类属性一致
        @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);
    
       
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
     方案二: 通过@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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 方案三配置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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20230904144504441

    XML文件定义的三种规范

    一、同包同名

    比如我要配置com.example.webcase下mapper的xml,那么便要如以下一样

    image-20230908101118859

    二、一个xml文件对应一个接口,且名称完全一致

    如图

    image-20230908101625184

    三、xml中SQL语句的id要与mapper接口中的方法名保持一致,并且放回类型也是一致的

    • mapper接口中的方法名为list,返回值是List

    image-20230908102346432

    • xml中的id也为list,返回值为List

    image-20230908112248704

    XML映射文件来配置sql

    image-20230904164814418

    • 一个接口与一个映射文件相对应

    • 红色是要求一,紫色是要求二

    <?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">
    
    • 1
    • 2
    • 3
    • 4
    • 每次配置xml文件时候,根据配置东西的不同要选择不同的约束。比如以上就是mysql的约束

    访问mybatis中文网获得

    https://mybatis.net.cn/getting-started.html

    image-20230904201751172

    image-20230904202113105

    image-20230904202128958

    动态SQL

    image-20230904202522574

    • 指查询条件随着用户所填变化而变化
    • 以上if有一个缺陷,当name为空而gender有值的时候,会出现语法错误
    动态查询

    image-20230904212414679

    • 使用where解决
    动态更新

    image-20230904212838552

    • 通过Alt+回车可以自动生成动态sql代码

    image-20230904213230494

    • 不同的关键字能生成不同

    • 也会if限制,多个 ,

    image-20230904213328757

    image-20230904213347708

    批量删除

    image-20230904213814634

    代码复用

    image-20230904214111467

    • 用于代码的复用性

    配置文件

    使用application.properties配置文件

    image-20230911104738662

    image-20230911110057162

    不同的配置文件

    image-20230911110821711

    image-20230911110921959

    image-20230911111110916

    image-20230911113337864

    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">
    
    • 1
    • 2
    • 3
    • 4
    • 每次配置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)]

  • 相关阅读:
    解决docker Error response from daemon故障
    Vue3 - 异步组件(写法及详细示例)
    windows环境CLion调试SRS流媒体服务器源码
    Synopsys Sentaurus TCAD系列教程之-Tcl《2》
    Filter
    leetcode - 学习计划之数据结构入门
    2024npm国内镜像源
    LeetCode 41. First Missing Positive
    安卓面经_安卓基础面全解析<4/30>之内容提供者全解析
    跨境电商测评内幕及自养号技术教学
  • 原文地址:https://blog.csdn.net/qq_61654952/article/details/138175820