SSM整合——Springboot

1.0 概述

1.1 持久层:

DAO层(mapper)

  • DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此

    • DAO层的设计首先是设计DAO的接口,

    • 然后在spring-mapper.xml的配置文件中定义此接口的实现类,

    • 然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰,

    • DAO层的数据源配置,以及有关数据库连接的参数都在spring-mapper的配置文件中进行配置。

1.2 业务层:

Service层

  • Service层:Service层主要负责业务模块的逻辑应用设计。

    • 首先设计接口,再设计其实现的类

    • 接着再在Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理

    • Service层的业务实现,具体要调用到已定义的DAO层的接口

    • 数据库的事务配置在service.xml中配置

    • 封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。

1.3 表现层:

Controller层(Handler层)

  • Controller层:Controller层负责具体的业务模块流程的控制,

    • 在此层里面要调用Service层的接口来控制业务流程,

    • 控制的配置也同样是在springmvc.xml的配置文件里面进行,针对具体的业务流程,会有不同的控制器,

    • 我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,

      这样不仅使程序结构变得清晰,也大大减少了代码量

1.4 View层
  • View层 此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示.

1.5 各层联系
  • DAO层,Service层这两个层次都可以单独开发,互相的耦合度很低,完全可以独立进行,这样的一种模式在开发大项目的过程中尤其有优势

  • Controller,View层因为耦合度比较高,因而要结合在一起开发,但是也可以看作一个整体独立于前两个层进行开发。这样,在层与层之前我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切显得非常清晰简单。

  • Service逻辑层设计

    • Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的业务处理方法。

2.0 SSM整合

2.1 创建SpringBoot项目

image-20230309210725476

2.2 引入依赖
<properties><java.version>11</java.version><mybatis.version>2.2.2</mybatis.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency>
​<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
注意:引入 spring-boot-devtools 依赖后,每次我们只需要重新编译源代码即可,不要需要重启springboot项目
2.3 工程搭建
#启动端口
server.port=8088
#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///220706a
spring.datasource.username=root
spring.datasource.password=123456
# 日志登记
logging.level.com.whitecamellia.mybatis_demo = debug
#xml配置
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
#驼峰映射
mybatis.configuration.map-underscore-to-camel-case=true
#配置别名
mybatis.type-aliases-package = com.whitecamellia.mybatis_demo.entity 
#主键返回
mybatis.configuration.use-generated-keys=true
# 延迟加载
mybatis.configuration.lazy-loading-enabled=true
#二级缓存
mybatis.configuration.cache-enabled=true
2.4 封装Result工具类
package com.whitecamellia.ssm_test.util;
import lombok.Getter;
@Getter
public class Result {private int code;private String message;private Object data;
​private Result() {}
​public static Result ok () {Result result = new Result();result.code = 200;result.message = "success";return result;}
​public static Result ok (Object data) {Result result = new Result();result.code = 200;result.message = "success";result.data = data;return  result;}
​public static Result error (int code,String message) {Result result = new Result();result.code = code;result.message = message;return  result;}
}
​
​
// 测试
@RestController
public class PersonController {@Autowiredprivate PersonService personService;
​@GetMapping("/findList")public Result findList () {List<Person> list = personService.findList();return  list.size()!= 0 ?Result.ok(list) :Result.error(201,"无数据");}
}
2.5 优化工具类
@Getter
public class Result<T> {private int code;private String message;private T data;
​private static final int DEFAULT_SUCCESS_CODE = 200;private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
​private Result() {}
​public static Result<Void> ok () {Result<Void> result = new Result<>();result.code = DEFAULT_SUCCESS_CODE;result.message = DEFAULT_SUCCESS_MESSAGE;return result;}
​public static  T> Result<T> ok (T data) {Result<T> result = new Result<>();result.code = DEFAULT_SUCCESS_CODE;result.message = DEFAULT_SUCCESS_MESSAGE;result.data = data;return result;}
​public static Result<Void> error (int code,String message) {Result<Void> result = new Result<>();result.code = code;result.message = message;return result;}
​
}
2.6 测试
 @GetMapping("/findList")public Result<List<Person>> findList () {return  Result.ok(personService.findList());}

3.0 分页

3.1 基本使用
@RestController
public class SpAttributeController {@Autowiredprivate SpAttributeService spAttributeService;
​@GetMapping("/find")public Result<List<SpAttribute>> findByPage() {return Result.ok(spAttributeService.findByPage());}
}
public interface SpAttributeService {List<SpAttribute> findByPage();
}
@Service
public class SpAttributeServiceImpl implements SpAttributeService {
​@Autowiredprivate SpAttributeMapper spAttributeMapper;
​@Overridepublic List<SpAttribute> findByPage() {return spAttributeMapper.findByPage();}
}
@Mapper
public interface SpAttributeMapper {@Select(" select * from sp_attribute")List<SpAttribute> findByPage();
}
@Data
public class SpAttribute {private Integer attrId;private String attrName;private Integer catId;private String attrSel;private String attrWrite;private String attrVals;// getter&&setter
}
3.2 导入依赖
<pagehelper-version>1.4.1</pagehelper-version>
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pagehelper-version}</version>
</dependency>
3.3 分页助手
 Page<SpAttribute> page1 = PageHelper.offsetPage(pageNum, pageSize);Page<SpAttribute> page2 = PageHelper.startPage(pageNum, pageSize);
3.4 测试:
//  http://localhost:8088/findByPage1?pageNum=1&pageSize=10@GetMapping("/findByPage1")public Result<List<SpAttribute>> findByPage1(Integer pageNum, Integer pageSize) {
//      PageHelper.offsetPage(pageNum, pageSize);PageHelper.startPage(pageNum, pageSize);return Result.ok(spAttributeService.findByPage());}
3.5 封装PageData
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageData<T> {private List<T> data;private long total;
}
3.6 测试
 @GetMapping("/findByPage2")public Result<PageData<SpAttribute>> findByPage2(Integer pageNum, Integer pageSize) {Page<SpAttribute> result = PageHelper.startPage(pageNum, pageSize);spAttributeService.findByPage();PageData<SpAttribute> pageData = new PageData<>(result.getResult(), result.getTotal());return Result.ok(pageData);}
3.7 分页演示
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>table 模块快速使用</title><!-- 引入 layui.css --><link rel="stylesheet" href="//unpkg.com/layui@2.6.8/dist/css/layui.css">
​<!-- 引入 layui.js --><script src="//unpkg.com/layui@2.6.8/dist/layui.js"></script>
</head>
<body>
<table id="demo" lay-filter="test"></table>
​
<script>layui.use('table', function () {var table = layui.table;
​//第一个实例table.render({elem: '#demo', height: 312, url: '/findByPage3' //数据接口, page: true //开启分页, cols: [[ //表头{field: 'attrId', title: '主键id', width: 180, sort: true, fixed: 'left'}, {field: 'attrName', title: '属性名称', width: 180}, {field: 'catId', title: '类型id', width: 180, sort: true}, {field: 'attrSel', title: '动态参数', width: 180}, {field: 'attrWrite', title: '静态属性', width: 180}]],parseData: function(d){return {code: d.code,msg: d.message,count: d.data.total,data: d.data.data,};}});
​});
</script>
</body>
</html>
 
 @GetMapping("/findByPage3")public Result<PageData<SpAttribute>> findByPage3(@RequestParam(name = "page")Integer pageNum,@RequestParam(name = "limit")Integer pageSize) {Page<SpAttribute> result = PageHelper.startPage(pageNum, pageSize);spAttributeService.findByPage();PageData<SpAttribute> pageData = new PageData<>(result.getResult(), result.getTotal());return Result.ok(pageData);}
3.8 增加排序功能
 Page<SpAttribute> result = PageHelper.startPage(pageNum, pageSize, "attr_id DESC");
3.9 注意事项:
  • 在使用排序时,我们发现pagehelper采用的是字符串拼接的形式,这样会有潜在的sql注入问题,这就要求我们在排序时必须严格校验排序的参数。必须与表或者实体类字段做好对应。

前端传参  
  @GetMapping("/findByPage")public Result<PageData<SpAttribute>> findByPage(@RequestParam(defaultValue = "1") Integer pageNum,    @RequestParam(defaultValue = "10") Integer pageSize) {pageSize = pageSize >= 50 ? 50 : pageSize;return ...}
注意事项:
  • pageNum,pageSize指定默认值

  • pageNum 可以不做限制但是pageSize必做,防止前端恶意传参

pageHelper注意事项
  • 分页插件是当调用startPage或者offsetPage之后开始拦截select语句,拦截之后,在select语句后拼接limit参数,拦截以后,分页功能关闭,再准备拦截下一次select语句。也就是说如果我们连续发了2个select语句请求只会拦截第一次操作。

  • 不要在拦截select语句与请求的select语句之间使用page的任意方法,只有select语句请求以后,page里面才有数据。

4.0 事务

事务:transaction

4.1 基本使用
public class Account {private Integer id;private String name;private double balance;//getter&&setter
}
​@RestController
public class AccountController {@Autowiredprivate AccountService accountService;
​@PostMapping("/balance")public void update() {boolean update = accountService.update();System.out.println(update);}
}
​
public interface AccountService {boolean update();
}

在你认为可能出现问题的方法上加上注解@Transactional

​@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountMapper accountMapper;
​@Transactional@Overridepublic boolean update() {int sub = accountMapper.sub();int i = 1 / 0;int add = accountMapper.add();return sub == add ? true : false;}
}
@Mapper
public interface AccountMapper {int sub();int add();
}
<?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.whitecamellia.mapper.AccountMapper"><update id="add">UPDATE accountset balance = balance + 500WHERE id = 2</update>
​<update id="sub">UPDATE accountset balance = balance - 500WHERE id = 1</update>
​
</mapper>
 
4.2 rollbackFor
@Service
​
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountMapper accountMapper;
​@Transactional  //  默认 只有运行时异常  会自动回滚@Overridepublic boolean update() throws FileNotFoundException {int sub = accountMapper.sub();// IOException 非运行时异常FileInputStream fileInputStream = new FileInputStream("C:\\WINDOWS\\1.txt"); int add = accountMapper.add();return sub == add ? true : false;}
​
}
 
  • 程序报错!尽管我们添加了事务注解,但是我们发现数据还是可以在数据库中进行修改

  • 实际上spring框架在封装 @Transactional注解默认只会处理runtimeException,对于编译异常,默认交给用户处理。

  • 我们希望编译异常也交给spring框架来管理,具体配置如下

@Transactional(rollbackFor = RuntimeException.class)//默认
@Transactional(rollbackFor = Exception.class) // 所有 遇见运行时异常 或者 非运行时异常。都会回滚,前提是该方法内的异常抛出而非捕获
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountMapper accountMapper;
​@Transactional(rollbackFor = Exception.class)@Overridepublic boolean update() throws FileNotFoundException {int sub = accountMapper.sub();
//      int i = 1 / 0;FileInputStream fileInputStream = new FileInputStream("C:\\WINDOWS\\1.txt");int add = accountMapper.add();return sub == add ? true : false;}
​
}
4.3 事务的传播机制
  • REQUIRED (默认)

    • 支持当前事务,如果当前没有事务,则新建事务

    • 如果当前存在事务,则加入当前事务,合并成一个事务

  • REQUIRES_NEW

    • 新建事务,如果当前存在事务,则把当前事务挂起(无论当前环境是否有事物)

    • 这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交

  • NESTED

    • 如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交

    • 如果当前没有事务,则新建事务

    • 如果它异常,父级可以捕获它的异常而不进行回滚,正常提交

    • 但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别

  • SUPPORTS

    • 如果当前存在事务,则加入事务

    • 如果当前不存在事务,则以非事务方式运行,这个和不写没区别

  • NOT_SUPPORTED

    • 以非事务方式运行

    • 如果当前存在事务,则把当前事务挂起

  • MANDATORY

    • 如果当前存在事务,则运行在当前事务中

    • 如果当前无事务,则抛出异常,也即父级方法必须有事务

  • NEVER

    • 以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务

一般用得比较多的是 REQUIREDREQUIRES_NEW

REQUIRES_NEW 一般用在子方法需要单独事务。

@Transactional(propagation = Propagation.REQUIRED)

代码演示:

testService

public interface TestService {void TestInsert ();
}

testServiceImpl

@Service
public class TestServiceImpl implements TestService {@Autowiredprivate PersonMapper personMapper;@Transactional@Overridepublic void TestInsert() {Person person = new Person();person.setName("测试");person.setAge(20);// int i = 1 / 0;personMapper.insert(person);}
}
 

PersonServiceImpl

@Service
public class PersonServiceImpl implements PersonService {@Autowiredprivate PersonMapper personMapper;
​@Autowiredprivate TestService testService;@Override@Transactional(rollbackFor = Exception.class)public int insert(Person person) throws FileNotFoundException {int insert = personMapper.insert(person);
​testService.TestInsert();
//        int i = 1 / 0;
//        new FileInputStream("c:/1.txt");return insert;}
}
 

@Transactional(propagation = Propagation.REQUIRES_NEW)

@Service
public class TestServiceImpl implements TestService {@Autowiredprivate PersonMapper personMapper;// 默认
//  @Transactional(propagation = Propagation.REQUIRED)@Transactional(propagation = Propagation.REQUIRES_NEW)@Overridepublic void TestInsert() {Person person = new Person();person.setName("测试");person.setAge(20);personMapper.insert(person);}
}

4.4 事务的失效场景

5.0 Lombok

5.1 常用注解
@Getter
@Setter
@ToString
@EqualsAndHashCode
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
//    @Getterprivate Integer id;
//    @Setterprivate String name;private Integer age;
}
5.2 @Slf4j (日志框架)
编译前
@Slf4j
class Demo {public static void main(String[] args) {
​}
}
编译后
class Demo {private static final Logger log = LoggerFactory.getLogger(Demo.class);
​Demo() {}
​public static void main(String[] args) {// 日志输出级别:debug、info、warn、errorlog.debug();}
}
 
5.3 级别演示
@Slf4j
@Service
public class PersonServiceImpl implements PersonService {@Autowiredprivate PersonMapper personMapper;@Overridepublic List<Person> findList() {log.debug("开始打印数据");return personMapper.findList();}
}

注意:我们项目配置文件中配置日志的打印级别是debug,故会将所有的日志全部打印

#开发环境日志级别
logging.level.com.whitecamellia.ssm_test=debug
#生产环境日志级别
#logging.level.com.whitecamellia.ssm_test=info
#再次精简打印信息
logging.level.root=warn
5.4 调试打印
@Slf4j
@Service
public class PersonServiceImpl implements PersonService {@Autowiredprivate PersonMapper personMapper;@Overridepublic List<Person> findList() {List<Person> list = personMapper.findList();log.debug("开始打印{}集合数据",list);return  list;}
}
5.5 写入日志
#生产环境,将打印信息写到文件中
logging.file.name = logger.log

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/215477.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

混合预编码(Hybrid Precoding)的全连接结构与子连接结构

A Survey on Hybrid Beamforming Techniques in 5G: Architecture and System Model Perspectives 全连接结构的混合预编码 子连接结构的混合预编码 Alternating Minimization Algorithms for HybridPrecoding in Millimeter Wave MIMO Systems

深度学习——第4.3章 深度学习的数学基础

第4章 深度学习的数学基础 目录 4.7 指数函数和对数函数 4.7 指数函数和对数函数 深度学习经常会用到Sigmoid函数和Softmax函数&#xff0c;这些函数是通过包含exp(x)的指数函数创建的。后面我们需要求解这些函数的导数。 4.7.1 指数 指数是一个基于“乘以某个数多少次”&a…

关于个人职业选择

职业选择&#xff0c;一直是个老生常谈的话题。这并不是一个容易做的决定。 让我们来看看AI怎么说。 首先是方向性的回答&#xff1a; 然后是一些具体的回答 我个人比较倾向于深耕网络安全。这是一个很有趣也是一个持续发展着的领域。 不知道关于这个事情你怎么看&#xff0…

创建vue项目:vue脚手架安装、vue-cli安装,vue ui界面创建vue工程(vue2/vue3),安装vue、搭建vue项目开发环境(保姆级教程二)

今天讲解 Windows 如何利用脚手架创建 vue 工程&#xff0c;以及 vue ui 图形化界面搭建 vue 开发环境&#xff0c;这是这个系列的第二章&#xff0c;有什么问题请留言&#xff0c;请点赞收藏&#xff01;&#xff01;&#xff01; 文章目录 1、安装vue-cli脚手架2、vue ui创建…

智能优化算法应用:基于斑马算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于斑马算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于斑马算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.斑马算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

R语言,table()函数实现统计每个元素出现的频数+并将最终统计频数结果转换成dataframe数据框形式

在 R中&#xff0c;要统计dataframe数据框中每个元素出现的频数&#xff0c;可以使用table()函数。以下是一个示例&#xff1a; 目录 一、创建数据 二、统计第一列每个元素出现的频数 三、统计第二列每个元素出现的频数 四、将频数结果转换为数据框&#xff0c;并改列名 一…

ambari hive on Tez引擎一直卡住

hive on tez使用./bin/hive启动后一直卡住&#xff0c;无法进入命令行 使用TEZ作为Hive默认执行引擎时&#xff0c;需要在调用Hive CLI的时候启动YARN应用&#xff0c;预分配资源&#xff0c;这需要花一些时间&#xff0c;而使用MapReduce作为执行引擎时是在执行语句的时候才会…

人工智能_机器学习063_SVR支持向量机_回归拟合天猫双十一销量方程---人工智能工作笔记0103

之前我们用线性回归做过天猫双十一销量预测的数据,现在我们再来用SVR支持向量机来做一下 首先上面是给出了销量,对应2009年到2019年的,销售额 可以看到: X=np.arange(2009,2020)-2008 统一减去2008的话看起来数据比较简单了 y=np.array([0.5,9.36,52,191,350,571,912,1207,1…

题目:快速幂(蓝桥OJ 1514)

题目描述&#xff1a; 解题思路&#xff1a; 使用快速幂模板&#xff08;倍增思想&#xff09;。 题解&#xff1a; #include<bits/stdc.h> using namespace std; using ll long long;ll ksm(ll a, ll b, ll c)//注意&#xff1a;需要取模的地方都取模c&#xff0c;且…

使用 Kubernetes 为 CI/CD 流水线打造高效可靠的临时环境

介绍 在不断发展的科技世界中&#xff0c;快速构建高质量的软件至关重要。在真实环境中测试应用程序是及早发现和修复错误的关键。但是&#xff0c;在真实环境中设置 CI/CD 流水线进行测试可能既棘手又昂贵。 Kubernetes 是一个流行的容器编排平台&#xff0c;提供临时环境解决…

【STM32】蓝牙氛围灯

Docs 一、项目搭建和开发流程 一、项目需求和产品定义 1.需求梳理和产品定义 一般由甲方公司提出&#xff0c;或由本公司市场部提出 需求的重点是&#xff1a;这个产品究竟应该做成什么样&#xff1f;有哪些功能&#xff1f;具体要求和参数怎样&#xff1f;此外还要考虑售价…

【postgresql】ERROR: INSERT has more expressions than target columns

执行下面sql insert into apply_account_cancellation3 select * from pply_account_cancellation; 返回下面错误信息 insert into apply_account_cancellation3 select * from apply_account_cancellation > ERROR: INSERT has more expressions than target colu…

如何将 MySQL 数据库转换为 SQL Server

本文解释了为什么组织希望将其 MySQL 数据库转换为 Microsoft SQL 数据库。本文接着详细介绍了尝试转换之前需要记住的事项以及所涉及的方法。专业的数据库转换器工具将帮助您快速将 MySQL 数据库记录转换为 MS SQL Server。 在继续之前&#xff0c;我们先讨论一下 MySQL 到 M…

新能源汽车生产污废水需要哪些工艺及设备

新能源汽车的快速发展带来了许多环境问题&#xff0c;其中之一就是生产过程中产生的污废水。由于新能源汽车的生产过程与传统汽车有所不同&#xff0c;因此需要采用特定的工艺和设备来处理和处理这些废水。 首先&#xff0c;新能源汽车生产过程中产生的污废水主要来自洗涤和冷却…

游戏中小地图的制作__unity基础开发教程

小地图的制作 Icon标识制作制作摄像机映射创建地图UI效果“不一样的效果” 在游戏中经常可以看到地图视角的存在&#xff0c;那么地图视角是如何让实现的呢&#xff1f; 这一期教大家制作一个简易的小地图。 &#x1f496;点关注&#xff0c;不迷路。 老样子&#xff0c;我们还…

C++ Qt开发:LineEdit单行输入组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍LineEdit单行输入框组件的常用方法及灵活运用…

【NR技术】NR NG-RAN整体架构 -功能划分(三)

1 概述 NG-RAN节点包括: gNB&#xff0c;向终端提供NR用户平面和控制平面协议终端;ng-eNB&#xff0c;向终端提供E-UTRA用户平面和控制平面的协议终端。gNB和ng- eNB通过Xn接口相互连接。gnb和NG- eNB也通过NG接口连接到5GC&#xff0c;更具体地说&#xff0c;通过NG-C接口连…

深入浅出:HTTPS单向与双向认证及证书解析20231208

介绍: 网络安全的核心之一是了解和实施HTTPS认证。本文将探讨HTTPS单向认证和双向认证的区别&#xff0c;以及SSL证书和CA证书在这些过程中的作用&#xff0c;并通过Nginx配置实例具体说明。 第一部分&#xff1a;HTTPS单向认证 定义及工作原理&#xff1a;HTTPS单向认证是一…

网络游戏APP备案|游戏

网络游戏APP备案|游戏 网络游戏备案分析需要备案原因&#xff08;个人看法&#xff09;对小公司对大公司 总结 网络游戏备案分析 相信做网络游戏的伙伴们在23年都收到了各个平台的公告&#xff0c;网络游戏需要进行APP的备案。也就是说网路游戏现在安卓平台也不是你想上架测试…

2024年甘肃省职业院校技能大赛信息安全管理与评估赛项一阶段样题一

2024年甘肃省职业院校技能大赛高职学生组电子与信息大类信息安全管理与评估赛项样题一 竞赛需要完成三个阶段的任务&#xff0c;分别完成三个模块&#xff0c;总分共计 1000分。三个模块内容和分值分别是&#xff1a; 1.第一阶段&#xff1a;模块一 网络平台搭建与设备安全防…