有关后端的知识整理合集

1. 有关数据库

1.1前端,后端,数据库之间是如何交互的?

举个例子:在这里我们有前端——用户界面Client,服务器后端Server以及数据库DB,在用户与整套系统交互时在前
端进行登录,这时用户输入用户名和密码,而前端将这些数据传给后端,后端将其对应的信息包含到能够执行查询的
SQL语句中,并利用嵌入式SQL等方式在数据库中执行查询,如:

    select * from Users where user_name='xxx' and pwd = 'xxx'

在上述语句中,后端向数据库发送的查询语句在用户表中查询对应用户基本信息,查询完成后后端通过校验是否匹配
来判定是否登录成功,并将结果返回前端,前段根据不同结果执行不同操作。

思考一下,如果我们把后端拿掉,只使用前端返回的参数到数据库去查询可行吗?

答案是可行,甚至速度更快了。但是这样操作十分的不安全。因为数据库本身会无条件相信前端提交的请求,而前段
运行的代码是不可控的,我们不能将敏感的业务逻辑放在前端处理。

1.2 SQL语言语法速览

SQL语言主要作用:可以创建模式,表,视图,索引等以及对数据的增删改查
主要操作:Create/Update/Read/Delete (CURD boy 必会)以及Select

1.2.1 建表

CREATE TABLE Student(
	[Sno] [nchar](8) NOT NULL,
	[Sname] [varchar](20) NULL,
	[Ssex] [nchar](2) NULL,
	[Sage] [tinyint] NULL,
	[Clsno] [char](6) NOT NULL,
	[Saddress] [nchar](20) NULL,
)
GO

使用create table语句完成建表,在表中添加对应的属性以及数据类型和限制。

1.2.2 插入,删除,更新

使用insert语句向表中插入数据

     insert into Student values('20031203','李华','男',20,'CS01','丹霞路486号')

使用delete语句删除表中信息

    delete from Student where Sname='李华'

使用update语句更新数据

	update Student set Saddress = '长江中路' where Sname = '李华'

1.2.3 查询

使用select语句完成查询

 	select * from Student
 	select Sname from Student where Sno = '20031203'
 	select distinct Sname where Saddress = '长江中路'
 	select * from Student limit 3,4 --分页查询,从下标为3的数据开始查询,共查询四条数据

1.3数据库优化

数据库中的索引可以加速查询和排序操作。索引可以看作是一个快速查找目录,其中保存着指向
数据行的指针,这些指针与数据表中的数据行保持一对一的关系。当查询涉及到大量的数据行时,没有索引,数据库
需要逐个比对每一行数据,查询的效率非常低;而有了索引,数据库可以先根据索引找到符合条件的数据行的指针,
然后再根据指针访问目标行的具体数据,相对来说查询速度会更快。

在数据库表中,通常会将索引与其中一个或多个列相关联,以便于快速的查找、筛选、排序等操作。索引可以大大提高数据库的查询效率,但需要占用一定的存储空间和增加更新操作的成本。

	建立索引:
	create index idx_on_tablename on table(column(length));
	create index idx_on_tablename on user(name);

2.有关后端的Java高级特性

在Java 后端开发中,有一些高级特性被广泛使用,能够帮助开发者更高效地开发应用。
这些高级特性可以极大地提高 Java 后端开发的效率和质量,但也需要开发者有足够的经验和技能使用。
(多线程、JDBC、注解与反射、maven包管理工具等)

2.1 多线程

Java 的多线程通过 java.lang.Thread 类和 java.lang.Runnable 接口来实现。

常见的线程操作包括:
创建线程对象:可以通过创建 Thread 对象或实现 Runnable 接口来创建一个新的线程对象。

	public class ThreadDemo implements Runnable 

在这个类中加入线程名ThreadName

	private final String threadName;

如果是继承的Runnable接口须覆写run方法

	@override
	public void run() {
        System.out.println("Running " + threadName);
        try {
            for(int i = 4; i > 0; i--) {
                System.out.println("Thread: " + threadName + ", " + i);
                // 让线程睡眠一段时间
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("Thread " + threadName + " interrupted.");
        }
        System.out.println("Thread " + threadName + " exiting.");
    }

启动线程:调用线程对象的 start() 方法来启动新线程。

	ThreadDemo T1 = new ThreadDemo( "Thread-1");
    T1.start();

加入线程:调用一条线程的 join() 方法,等待该线程执行完毕后再执行下一条线程。

	Thread T2 = new Thread(() -> {
            try {
                T1.join(); // 等待 T1 线程执行完毕
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            for (int i = 1; i <= 5; i++) {
                System.out.println("Thread 2: " + i);
            }
        });

线程同步:通过使用 synchronized 关键字或 Lock 接口来保护共享数据,避免多个线程同时访问同一资源。在以下情况下使用 synchronized:

多个线程访问共享数据,并且可能会修改数据时。

需要避免多个线程同时执行同一段代码时。

以下是一个示例,假设我们有一个账户类 Account,对于多个用户的取款和存款操作,需要保证同一时间只有一个线程可以修改账户的余额,以避免出现数据竞争和不一致问题。

	public class Account {
    private int balance;

    public Account(int balance) {
        this.balance = balance;
    }

    public synchronized void deposit(int amount) {
        balance += amount;
        System.out.println(Thread.currentThread().getName() + " Deposited: " + amount + ",  New Balance is: " + balance);
    }

    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println(Thread.currentThread().getName() + " Withdrawn: " + amount + ",  New Balance is: " + balance);
        } else {
            System.out.println(Thread.currentThread().getName() + " Withdrawal Failed: Insufficient Balance");
        }
    }
}

2.2 JDBC

1996年,Sun公司发布了第1版的Java数据库连接(JDBC)API,使编程人员可以通过这个API接口连接到
数据库,并使用结构化查询语言(即SQL)完成对数据库的查找与更新。(SQL通常发音为“sequel”,它是
数据库访问的业界标准。)JDBC自此成为Java类库中最常使用的API之一。JDBC的版本已更新过数次。

从一开始,Java技术开发人员就意识到了Java在数据库应用方面的巨大潜力。从1995
年开始,他们就致力于扩展Java标准类库,使之可以运用SOL访问数据库。他们最初希望
通过扩展Java,就可以让人们“纯”用Java语言与任何数据库进行通信。但是,他们很快发
现这是一项无法完成的任务:因为业界存在许多不同的数据库,且它们所使用的协议也各不
相同。尽管很多数据库供应商都表示支持Java提供一套数据库访问的标准网络协议,但是每
一家企业都希望Java能采用自己的网络协议。

所有的数据库供应商和工具开发商都认为,如果Java能够为SQL访问提供一套
“纯”Java APl,同时提供一个驱动管理器,以允许第三方驱动程序可以连接到特定的数据
库,那它就会显得非常有用。这样,数据库供应商就可以提供自己的驱动程序,将其插人到
驱动管理器中。这将成为一种向驱动管理器注册第三方驱动程序的简单机制。

JDBC规范将驱动程序归结为以下几类:
第1类驱动程序将JDBC翻译成ODBC,然后使用ODBC驱动程序与数据库进行通
信。较早版本的Java包含了一个这样的驱动程序:JD BC/ODBC桥,不过在使用这个
桥接器之前需要对ODBC进行相应的部署和正确的设置。在JD BC面世之初,桥接
器可以方便地用于测试,却不太适用于产品的开发。现在,有很多更好的驱动程序可
用,所以JDK已经不再提供JD BC/ODBC桥了
第2类驱动程序是由部分Java程序和部分本地代码组成的,用于与数据库的客户端
API进行通信。在使用这种驱动程序之前,客户端不仅需要安装Java类库,还需要安
装一些与平台相关的代码。
第3类驱动程序是纯Java客户端类库,它使用一种与具体数据库无关的协议将数据库
请求发送给服务器构件,然后该构件再将数据库请求翻译成数据库相关的协议。这简
化了部署,因为平台相关的代码只位于服务器端,
第4类驱动程序是纯Java类库,它将JDBC请求直接翻译成数据库相关的协议

大部分数据库供应商都为他们的产品提供第3类或第4类驱动程序。与数据库供应商提
供的驱动程序相比,许多第三方公司专门开发了很多更符合标准的产品,它们支持更多的平
台、运行性能也更佳,某些情况下甚至具有更高的可靠性
总之,JD BC最终是为了实现以下目标:
通过使用标准的SQL语句,甚至是专门的SQL扩展,程序员就可以利用Java语言开
发访问数据库的应用,同时还依旧遵守Java语言的相关约定。
数据库供应商和数据库工具开发商可以提供底层的驱动程序。因此,他们可以优化各
自数据库产品的驱动程序。

在传统的客户端/服务器模型中,通常是在服务器端部署数据库,而在客户端安装富GUI程序。在此模型中,JDBC
驱动程序应该部署在客户端。但是,如今三层模型更加常见。在三层应用模型中,客户端不直接调用数据库,而是
调用服务器上的中间件层由中间件层完成数据库查询操作。这种三层模型有以下优点:它将可视化表示(位于客户
端)从业务逻辑(位于中间层)和原始数据(位于数据库)中分离出来因此,我们可以从不同的客户端,如Java桌
面应用、浏览器或者移动App,来访问相同的数据和相同的业务规则。客户端和中间层之间的通信在典型情况下是
通过HTTP来实现的。JD BC管理着中间层和后台数据库之间的通信。

三层模型业务逻辑
三层业务逻辑

2.3 反射

现在,Class类是泛型的。例如,String.class实际上是一个Class类的对象(事实上,是唯一的对象)
类型参数十分有用,这是因为它允许Class方法的返回类型更加具有特定性。Class的以下方法就使用了类
型参数

	T new Instance(T cast(0 bj ect obj)
	T[]get E num Constants 0
	Class<super T>get Superclass(
	Constructor<T>get Constructor(Class...parameter Types)
	Constructor<T>get Declared Constructor(Class...parameter Types

new Instance方法返回这个类的一个实例,由无参数构造器获得。它的返回类型现在被声明为T,其类型与Class描述的类相同,这样就免除了类型转换。
如果给定对象的类型实际上是T的一个子类型,cast方法就会返回这个给定对象(现在声明为类型T),否则,会抛出一个Bad Cast Exception异常。
如果这个类不是enum类或T类型枚举值的数组,getEnumConstants方法将返回null
最后,getConstructor与getdeclaredConstructor方法返回一个Constructor对象。Constructor
类也已经变成泛型,从而使newInstance方法有一个正确的返回类型

2.4 maven

Maven 是一个基于 Java 技术的项目管理和构建工具,可以帮助开发者自动化构建、管理和部署项目。
Maven 是一个强大的工具,能够管理项目的依赖关系、构建过程、文档生成等,可大大提高开发效率
和工程质量。使用 Maven ,可以通过简单的命令轻松地构建您的 Java 项目,而不必担心复杂的依赖
关系管理或构建脚本等问题。此外,Maven 适用于现代持续集成和持续交付环境,可以帮助您更快地
部署和测试应用程序。以下是 Maven 的几个重要概念和作用:

项目对象模型(Project Object Model,POM):Maven 的核心是一个基于 XML 的 POM 文件,它描述了项目的依赖关系、构建过程、打包方式、插件配置等信息。Maven 根据 POM 文件管理项目,并根据其定义构建项目。
仓库(Repository):Maven 仓库是一个用于存储构件(即项目的二进制文件)和依赖项的库,用于管理和发布 Maven 构件。
依赖管理(Dependency Management):Maven 可以自动管理项目依赖项,从而可以使用远程仓库中已经存在的开源库或者自己的库,减少项目的维护成本。
构建生命周期(Build Lifecycle):Maven 基于构建生命周期提供了一种标准的方式来声明、执行和管理构建过程中的各种活动。
插件(Plugin):Maven 插件是使开发者能够管理和构建项目的核心组成部分。它们提供了很多功能,如复制文件、调用 Shell 或批处理脚本、编译源代码、生成 Javadoc 文档等。

3.有关Spring

Spring Boot 是一个基于 Spring 框架的微服务框架,它提供了一种简单快捷的方式来创建应用程序和微服务。
Spring Boot 通过自动配置,减少了开发者的大量配置和样板代码,能够快速构建生产级别的应用程序。

以下是 Spring Boot 通过几个重要概念和特点使得开发人员可以更加专注于业务逻辑实现,而不必担心配置等问题。此外,Spring Boot 提供了很多功能,如 Web 应用程序开发、数据访问、缓存支持、安全性等,使得 Spring Boot 成为创建 Web 应用程序和微服务的首选框架。

自动配置(Auto-configuration):Spring Boot 提供了大量的自动配置模块,即可执行的 Java 代码块,用
于自动配置应用程序的行为。这些模块会根据应用程序的需求自动配置必需的组件和功能。
起步依赖(Starter Dependencies):Spring Boot 起步依赖是一组 Maven 依赖,用于有效地提供应用程序
所需的所有库和框架。例如,要创建一个 Web 应用程序,只需添加 "spring-boot-starter-web" 依赖项,
Spring Boot 会自动配置所有必要的组件。
松散耦合(Loose Coupling):Spring Boot 支持松散耦合,即应用程序的所有组件相互独立,每个组件都
是自治的,可以轻松地替换和升级。
微服务架构(Microservices Architecture):Spring Boot 是一种微服务架构,它通过将应用程序分解成小型
、自治的服务,提高应用程序的可拓展性和可维护性。

3.1 自动配置

假设我们要创建一个 Spring Boot Web 应用程序,并对其进行自动配置,我们可以直接引入以下
的 Maven 依赖项:

	<dependency> 
   		<groupId>org.springframework.boot</groupId> 
   		<artifactId>spring-boot-starter-web</artifactId> 
	</dependency>
Spring Boot 会自动根据这个依赖项进行配置,包括但不限于以下方面:
Servlet 容器(Tomcat 或 Jetty 等)
Spring MVC 框架,并通过 @Controller 注解启用 Web 控制器功能。
静态资源处理器,例如 js、css、images 等。
错误页面实现及其映射。
HTTP 消息转换器 (HttpMessageConverters)。
控制器的视图解析器等。

3.2 起步依赖

Spring Boot 的起步依赖是一组已定义好的依赖关系集合,可以通过一项依赖管理来一次性解决所有需要使用
的依赖项,而不用手动添加每个依赖项。这样可以极大地简化项目的构建和依赖项管理。

在spring-boot-starter-web 依赖中,SpringBoot会自动引入一下相关依赖:

spring-boot-starter
spring-boot-starter-tomcat
spring-boot-starter-validation
spring-boot-starter-json
spring-boot-starter-security
spring-boot-starter-test

这样就避免了手动添加每个依赖项的繁琐工作,简化了项目的管理。如果需要更改某个版本,也只需在 pom.xml 中修改对应的版本号即可。

3.3 松散耦合

Spring 提倡面向接口编程,通过接口来定义组件之间的合约,而不是与具体的实现代码绑定在一起。
这种方式可以使得应用程序更加灵活,易于扩展和维护。

例如,当需要更换底层实现时,只需要实现新接口,而无需对程序其他部分进行修改。
在 Spring 框架中,我们通常使用接口来定义应用程序中的组件对象(Bean),从而实现对这些对象的解耦。比如,定义一个接口 UserService,包含了 User 记录的增删改查方法:

	public interface UserService {
    public User createUser(User user);
    public User updateUser(User user);
    public User countUser();
    public User printUserInfo();
    public User deleteUser(Long userId);
    public User getUserById(Long userId);
    public List&lt;User&gt; getAll();
}

然后,我们可以定义一个 UserServiceImpl 类来实现 UserService 接口中定义的功能:

	@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public User createUser(User user) {
        // 添加业务逻辑
    }

    @Override
    public User updateUser(User user) {
        // 添加业务逻辑
    }
    
	@Override
    public User countUser() {
        // 添加业务逻辑
    }
    
	@Override
    public User printUserInfo() {
        // 添加业务逻辑
    }
    @Override
    public User deleteUser(Long userId) {
        // 添加业务逻辑
    }

    @Override
    public User getUserById(Long userId) {
        // 添加业务逻辑
    }

    @Override
    public List&lt;User&gt; getAll() {
        // 添加业务逻辑
    }
}

通过面向接口编程,我们可以更容易地实现以下两个方面的解耦:

1.业务逻辑代码和数据访问代码的解耦
UserServiceImpl 类中使用了 UserRepository 对象来实现数据访问的功能,而 UserRepository 的实现类是由 Spring 容器注入的。这样,我们就将业务逻辑和数据访问代码分离了开来,从而更加清晰地组织代码,易于维护和修改。

2.服务提供者和服务消费者的解耦
通过接口来定义服务,服务提供者只需实现服务接口并向 Spring 容器注册其实现,此时服务消费者就能通过容器中的服务接口来获取所需服务,而无需关心服务实现的具体细节。这样,服务提供者和服务消费者就解耦了,从而方便了代码的 testability 和 maintenance。

总结

有关后端的知识是一个很庞大的知识体系,在这里我仅对学校训练营课上朋辈分享的知识稍作总结与拓展练习,这只是后端学习的开始,值得我们探索的还有许多。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值