当前位置: 首页 > news >正文

JAVA极简图书管理系统,初识springboot后端项目

前提条件:

具备基础的springboot 知识

Java基础

废话不多说!

创建项目

配置所需环境

将application.properties==>application.yml   配置以下环境

数据库连接MySQL

自己创建的数据库名称为book_test


server:port: 8080
spring:datasource:url: jdbc:mysql://localhost:3306/book_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivermvc:hiddenmethod:filter:enabled: truemybatis:mapper-locations: classpath:mapper/*.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl#一直出现的问题:引入依赖包的问题

 追加两个依赖使得可以使用mapper-locations

数据库准备

图书以及简单的用户信息

CREATE TABLE `book_info` (`id` INT(10) NOT NULL AUTO_INCREMENT,`book_name` VARCHAR(127) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',`author` VARCHAR(127) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',`count` INT(10) NULL DEFAULT NULL,`price` DECIMAL(7,2) NOT NULL,`publish` VARCHAR(256) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',`status` TINYINT(3) NULL DEFAULT '1' COMMENT '0-⽆效, 1-正常, 2-不允许借阅',`create_time` DATETIME NULL DEFAULT 'CURRENT_TIMESTAMP',`update_time` DATETIME NULL DEFAULT 'CURRENT_TIMESTAMP' ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8mb4_0900_ai_ci'
ENGINE=InnoDB
AUTO_INCREMENT=25
;

CREATE TABLE `user_info` (`id` INT(10) NOT NULL AUTO_INCREMENT,`user_name` VARCHAR(128) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',`password` VARCHAR(128) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',`delete_flag` TINYINT(3) NULL DEFAULT '0',`create_time` DATETIME NULL DEFAULT 'CURRENT_TIMESTAMP',`update_time` DATETIME NULL DEFAULT 'CURRENT_TIMESTAMP' ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `user_name_UNIQUE` (`user_name`) USING BTREE
)
COMMENT='用户表'
COLLATE='utf8mb4_0900_ai_ci'
ENGINE=InnoDB
AUTO_INCREMENT=3
;

 

spring MVC 运行逻辑

Mapper ==> Service ==> Controller

mapper接口层代码:

@Insert("INSERT INTO book_info (book_name, author, count, price, publish, status, create_time, update_time) VALUES " +"(#{bookName}, #{author}, #{count}, #{price}, #{publish}, #{status}, #{createTime}, #{updateTime})")@Options(useGeneratedKeys = true, keyProperty = "id")int insertBook(BookInfo book);@Select("SELECT id, book_name AS bookName, author, count, price, publish, status, " +"CASE status WHEN 0 THEN '无效' WHEN 1 THEN '允许借阅' ELSE '不允许借阅' END AS statusCN, " +"create_time, update_time FROM book_info WHERE id = #{id}")@Results(id = "bookResultMap", value = {@Result(property = "id", column = "id"),@Result(property = "bookName", column = "bookName"),@Result(property = "author", column = "author"),@Result(property = "count", column = "count"),@Result(property = "price", column = "price"),@Result(property = "publish", column = "publish"),@Result(property = "status", column = "status"),@Result(property = "statusCN", column = "statusCN"),@Result(property = "createTime", column = "create_time"),@Result(property = "updateTime", column = "update_time")})BookInfo selectBookById(Integer id);@Update("UPDATE book_info SET book_name = #{bookName}, author = #{author}, count = #{count}, price = #{price}, " +"publish = #{publish}, status = #{status}, update_time = #{updateTime} WHERE id = #{id}")int updateBook(BookInfo book);@Delete("DELETE FROM book_info WHERE id = #{id}")int deleteBook(Integer id);@Select("SELECT * FROM book_info")List<BookInfo> selectAllBooks();List<BookInfo> mockData();

创建用户bookinfo


@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public boolean login(String name, String password, HttpSession session){//账号或密码为空if (!StringUtils.hasLength(name) || !StringUtils.hasLength(password)){return false;}//模拟验证数据, 账号密码正确if("admin".equals(name) && "admin".equals(password)){session.setAttribute("userName",name);return true;}//账号密码错误return false;}

@Data
public class BookInfo {//图书IDprivate Integer id;//书名private String bookName;//作者private String author;//数量private Integer count;//定价private BigDecimal price;//出版社private String publish;//状态 0-⽆效 1-允许借阅 2-不允许借阅private Integer status;private String statusCN;//创建时间private Date createTime;//更新时间private Date updateTime;
}

service层面:

  /*** 添加图书* @param book 图书信息* @return 操作结果,成功返回true,失败返回false*/boolean addBook(BookInfo book);/*** 根据ID查询图书* @param id 图书ID* @return 图书信息*/BookInfo getBookById(Integer id);/*** 更新图书信息* @param book 图书信息* @return 操作结果,成功返回true,失败返回false*/boolean updateBook(BookInfo book);/*** 删除图书* @param id 图书ID* @return 操作结果,成功返回true,失败返回false*/boolean deleteBook(Integer id);/*** 获取所有图书列表* @return 图书列表*/List<BookInfo> getAllBooks();

接口层的实现

 private BookInfoMapper bookMapper;@Overridepublic boolean addBook(BookInfo book) {// 可以在这里添加业务逻辑校验,例如检查图书信息是否完整int rowsAffected = bookMapper.insertBook(book);return rowsAffected > 0;}@Overridepublic BookInfo getBookById(Integer id) {return bookMapper.selectBookById(id);}@Overridepublic boolean updateBook(BookInfo book) {// 业务逻辑校验,例如确保ID不为空且存在对应的图书记录int rowsAffected = bookMapper.updateBook(book);return rowsAffected > 0;}@Overridepublic boolean deleteBook(Integer id) {// 可以添加逻辑判断,比如检查图书是否已被借阅不能删除int rowsAffected = bookMapper.deleteBook(id);return rowsAffected > 0;}@Overridepublic List<BookInfo> getAllBooks() {return bookMapper.selectAllBooks();}

控制层面:

@Autowiredprivate BookService bookService;// 添加图书@PostMapping("/add")public ResponseEntity<ResponseMessage> addBook(@RequestBody BookInfo book) {
//        boolean isAdded = bookService.addBook(book);
//        if (isAdded) {
//            return ResponseEntity.status(200).body(book);
//        } else {
//            return ResponseEntity.badRequest().build();
//        }try {boolean isAdded = bookService.addBook(book);if (isAdded) {// 创建ResponseMessage实例,表示成功ResponseMessage response = new ResponseMessage(200, "图书添加成功", book);return ResponseEntity.ok(response); // 注意这里返回的是ResponseEntity<ResponseMessage>} else {// 创建ResponseMessage实例,表示失败ResponseMessage response = new ResponseMessage(400, "图书添加失败,请检查输入信息", null);return ResponseEntity.badRequest().body(response); // 同样返回ResponseEntity<ResponseMessage>}} catch (Exception e) {// 异常处理,返回错误信息ResponseMessage response = new ResponseMessage(500, "添加图书时发生系统错误: " + e.getMessage(), null);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);}}// 根据ID获取图书信息@GetMapping("/{id}")public ResponseEntity<BookInfo> getBookById(@PathVariable Integer id) {BookInfo book = bookService.getBookById(id);if (book != null) {return ResponseEntity.ok(book);} else {return ResponseEntity.notFound().build();}}// 更新图书信息@PutMapping("/{id}")public ResponseEntity<Void> updateBook(@PathVariable Integer id, @RequestBody BookInfo book) {book.setId(id); // 确保请求体中的ID与路径变量ID一致boolean isUpdated = bookService.updateBook(book);if (isUpdated) {return ResponseEntity.noContent().build();} else {return ResponseEntity.notFound().build();}}// 删除图书@DeleteMapping("/{id}")public ResponseEntity<Void> deleteBook(@PathVariable Integer id) {boolean isDeleted = bookService.deleteBook(id);if (isDeleted) {return ResponseEntity.noContent().build();} else {return ResponseEntity.notFound().build();}}// 获取所有图书列表@GetMappingpublic ResponseEntity<List<BookInfo>> getAllBooks() {List<BookInfo> books = bookService.getAllBooks();return ResponseEntity.ok(books);}
public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public ResponseMessage(int code, String message, Object data) {this.code = code;this.message = message;this.data = data;}private int code; // 状态码,200表示成功,非200表示各种错误private String message; // 描述信息private Object data; // 可选,成功时返回的数据或错误时的额外信息

后端结束

前台交互

增加图书:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>添加图书</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/add.css"></head><body><div class="container"><div class="form-inline"><h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16"><pathd="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" /></svg><span>添加图书</span></h2></div><form id="addBook"><div class="form-group"><label for="bookName">图书名称:</label><input type="text" class="form-control" placeholder="请输入图书名称" id="bookName" name="bookName"></div><div class="form-group"><label for="bookAuthor">图书作者</label><input type="text" class="form-control" placeholder="请输入图书作者" id="bookAuthor" name="author" /></div><div class="form-group"><label for="bookStock">图书库存</label><input type="text" class="form-control" placeholder="请输入图书库存" id="bookStock" name="count"/></div><div class="form-group"><label for="bookPrice">图书定价:</label><input type="number" class="form-control" placeholder="请输入价格" id="bookPrice" name="price"></div><div class="form-group"><label for="bookPublisher">出版社</label><input type="text" id="bookPublisher" class="form-control" placeholder="请输入图书出版社" name="publish" /></div><div class="form-group"><label for="bookStatus">图书状态</label><select class="custom-select" id="bookStatus" name="status"><option value="1" selected>可借阅</option><option value="2">不可借阅</option></select></div><div class="form-group" style="text-align: right"><button type="button" class="btn btn-info btn-lg" onclick="add()">确定</button><button type="button" class="btn btn-secondary btn-lg" onclick="history.back()">返回</button></div></form></div><script type="text/javascript" src="js/jquery.min.js"></script><script>function add() {// 收集表单数据const formData = {bookName: $("#bookName").val(),author: $("#bookAuthor").val(),count: $("#bookStock").val(),price: $("#bookPrice").val(),publish: $("#bookPublisher").val(),status: $("#bookStatus").val()};// 使用Ajax发送数据到后端$.ajax({type: "POST",url: "/book/add", //请替换为您的后端接口地址contentType: "application/json; charset=utf-8",data: JSON.stringify(formData),success: function(response) {if(response.code === 200 || response.code === 201) { // 假设200或201都表示成功// alert(response.code);alert("添加成功");location.href = "book_list.html"; // 添加成功后跳转到列表页} else {alert("添加失败:" + response.message);}},error: function(xhr, status, error) {alert("添加图书时发生错误: " + error);}});}</script>
</body></html>

图书列表:展示所有图书

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>图书列表展示</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/list.css"><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/bootstrap.min.js"></script><script src="js/jq-paginator.js"></script>
</head><body>
<div class="bookContainer"><h2>图书列表展示</h2><div class="navbar-justify-between"><div><button class="btn btn-outline-info" type="button" onclick="location.href='book_add.html'">添加图书</button><button class="btn btn-outline-info" type="button" onclick="batchDelete()">批量删除</button></div></div><table class="table"><thead><tr><th><label for="selectAllBooks"></label><input type="checkbox" id="selectAllBooks"></th><th>ID</th><th>书名</th><th>作者</th><th>数量</th><th>定价</th><th>出版社</th><th>状态</th><th>操作</th></tr></thead><tbody></tbody></table><div class="demo"><ul id="pageContainer" class="pagination justify-content-center"></ul></div><script>$(document).ready(function() {getBookList();$("#selectAllBooks").click(function() {$("input[name='selectBook']").prop('checked', this.checked);});});function getBookList() {$.ajax({type: "get",url: "/book"+location.search,success: function (result) {console.log(result);if (result != null) {let finalHtml = "";for (const book of result) {finalHtml += '<tr>';finalHtml += '<td><input type="checkbox" name="selectBook" value="' + book.id + '"></td>'; // 修正了value属性的遗漏finalHtml += '<td>' + book.id + '</td>';finalHtml += '<td>' + book.bookName + '</td>';finalHtml += '<td>' + book.author + '</td>';finalHtml += '<td>' + book.count + '</td>';finalHtml += '<td>' + book.price + '</td>';finalHtml += '<td>' + book.publish + '</td>';finalHtml += '<td>' + book.statusCN + '</td>';finalHtml += '<td><div class="op">';finalHtml += '<a href="book_update.html?bookId=' + book.id + '" class="btn btn-sm btn-primary">编辑</a>'; // 修正了链接的闭合finalHtml += '<button class="btn btn-sm btn-danger" onclick="deleteBook(' + book.id + ')">删除</button>';finalHtml += '</div></td>';finalHtml += '</tr>';}$("tbody").html(finalHtml);}}});}function deleteBook(id) {const isDelete = confirm("确认删除?");if (isDelete) {$.ajax({type: "DELETE",url: "/book/" + id,success: function() {alert("删除成功");// 刷新页面以反映删除后的数据变化getBookList();location.reload();},error: function(xhr, status, error) {if (xhr.status === 404) {alert("图书不存在");} else {alert("删除失败: " + error);}}});}}function batchDelete() {const isDelete = confirm("确认批量删除?");if (isDelete) {//获取复选框的idconst ids = [];$("input:checkbox[name='selectBook']:checked").each(function () {ids.push($(this).val());});console.log(ids);alert("批量删除成功");}}</script>
</div>
</body></html>

修改图书

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>修改图书</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/add.css">
</head><body><div class="container"><div class="form-inline"><h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16"><pathd="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" /></svg><span>修改图书</span></h2></div><form id="updateBook"><input type="hidden" class="form-control" id="bookId" name="id"><div class="form-group"><label for="bookName">图书名称:</label><input type="text" class="form-control" id="bookName" name="bookName"></div><div class="form-group"><label for="bookAuthor">图书作者</label><input type="text" class="form-control" id="bookAuthor" name="author"/></div><div class="form-group"><label for="bookStock">图书库存</label><input type="text" class="form-control" id="bookStock" name="count"/></div><div class="form-group"><label for="bookPrice">图书定价:</label><input type="number" class="form-control" id="bookPrice" name="price"></div><div class="form-group"><label for="bookPublisher">出版社</label><input type="text" id="bookPublisher" class="form-control" name="publish"/></div><div class="form-group"><label for="bookStatus">图书状态</label><select class="custom-select" id="bookStatus" name="status"><option value="1" selected>可借阅</option><option value="2">不可借阅</option></select></div><div class="form-group" style="text-align: right"><button type="button" class="btn btn-info btn-lg" onclick="update()">确定</button><button type="button" class="btn btn-secondary btn-lg" onclick="history.back()">返回</button></div></form></div><script type="text/javascript" src="js/jquery.min.js"></script><!-- HTML 表单保持不变 --><script>function update() {// 收集表单数据const formData = {id: location.search.split("=")[1], // 确保隐藏字段包含图书IDbookName: $("#bookName").val(),author: $("#bookAuthor").val(),count: $("#bookStock").val(),price: $("#bookPrice").val(),publish: $("#bookPublisher").val(),status: $("#bookStatus").val()};// 对id进行Base64编码// 使用Ajax发送PUT请求到Spring Boot后端更新图书,URL中包含Base64编码的id// 构建正确的URL,使用模板字符串动态插入IDconsole.log("--------------"+formData)const urls = `/book/${formData.id}`;// 使用Ajax发送PUT请求到Spring Boot后端更新图书$.ajax({type: "PUT",url: urls, // 使用上面构建的正确URLcontentType: "application/json; charset=utf-8",data: JSON.stringify(formData),success: function(response, textStatus, jqXHR) {if(jqXHR.status === 204) {alert("更新成功");location.href = "book_list.html";} else if(response.status === 'SUCCESS') {alert("更新成功");location.href = "book_list.html";} else {alert("更新失败:" + response.message);}},error: function(xhr, status, error) {alert("更新图书时发生错误: " + xhr.responseText || error);}});}</script>
</body></html>

用户登录页面:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/login.css"><script type="text/javascript" src="js/jquery.min.js"></script>
</head><body><div class="container-login"><div class="container-pic"><img src="pic/computer.png" width="713" alt=""></div><div class="login-dialog"><h3>登陆</h3><div class="row"><span>用户名</span><label for="userName"></label><input type="text" name="userName" id="userName" class="form-control"></div><div class="row"><span>密码</span><label for="password"></label><input type="password" name="password" id="password" class="form-control"></div><div class="row"><button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button></div></div></div><script src="js/jquery.min.js"></script><script>function login() {$.ajax({type: "post",url: "/user/login",data: {name: $("#userName").val(),password: $("#password").val()},success: function (result) {if (result) {location.href = "book_list.html";} else {alert("账号或密码不正确!");}}});}</script>
</body></html>

总结:

  1. src/main/java/bao/book_again 目录下的 BookAgainApplication.java 是项目的启动类,它继承了Spring Boot的SpringBootApplication,并使用@SpringBootApplication注解开启自动配置和扫描。

  2. Controller 目录下有多个控制器类,如 BasicController.javaPathVariableController.java,它们使用Spring MVC的@RestController@Controller注解,处理来自客户端的HTTP请求,并返回相应的响应。

  3. Domain 目录下有领域模型类,如 User.javaBookInfo.java,它们代表了应用中的实体对象。

  4. Exception 目录下有异常处理类,如 ResponseMessage.java,可能是用于封装错误信息和响应状态的类。

  5. Mapper 目录下有MyBatis的相关接口,如 BookService.java,它们定义了数据库操作的接口。

  6. Service 目录下有服务层实现,如 BookServiceImpl.java,实现了业务逻辑。

  7. resources/static 目录下有静态资源,如HTML文件和图片。

  8. application.yml 是项目的配置文件,用于配置Spring Boot应用的各种属性。

  9. test 目录下可能有单元测试或集成测试代码。

这个项目使用了Spring Boot和Spring MVC,结合MyBatis作为持久层框架,实现了基本的CRUD操作。用户界面使用HTML模板,通过RESTful API与后端交互。整体来看,这是一个典型的MVC架构的Web应用,其中Controller负责处理HTTP请求,Service层处理业务逻辑,Mapper层处理数据库操作,Domain层定义了领域模型,Exception层处理异常,static目录下存放了前端资源

相关文章:

JAVA极简图书管理系统,初识springboot后端项目

前提条件&#xff1a; 具备基础的springboot 知识 Java基础 废话不多说&#xff01; 创建项目 配置所需环境 将application.properties>application.yml 配置以下环境 数据库连接MySQL 自己创建的数据库名称为book_test server:port: 8080 spring:datasource:url:…...

MySQL 重新初始化实例

1、关闭mysql服务 service mysqld stop 2、清理datadir(本例中指定的是/var/lib/mysql)指定的目录下的文件&#xff0c;将该目录下的所有文件删除或移动至其他位置 cd /var/lib/mysql mv * /opt/mysql_back/ 3、初始化实例 /usr/local/mysql/bin/mysqld --initialize --u…...

VCS编译bug汇总

‘typedef’ is not expected to be used in this contex 注册前少了分号。 Scope resolution error resolution : 声明指针时 不能与类名同名&#xff0c;即 不能声明为adapter. cannot find member "type_id" 忘记注册了 拼接运算符使用 关键要加上1b&#xff0…...

【2024LLM应用-数据预处理】之如何从PDF,PPT等非结构化数据提取有效信息(结构化数据JSON)?

&#x1f970;大家知道吗,之前在给AI大模型"喂数据"的时候,我们往往需要把非结构化数据(比如PDF、PPT、Excel等)自己手动转成结构化的格式,这可真是太累人儿了。&#x1f975; 幸好现在有了Unstructured这个神级库,它内置的数据提取函数可以帮我们快速高效地完成这个…...

冯雷老师:618大退货事件分析

近日冯雷老师受邀为某头部电商36名高管进行培训&#xff0c;其中聊到了今年618退货潮的问题。以下内容整理自冯雷老师的部分授课内容。 一、引言 随着电子商务的蓬勃发展&#xff0c;每年的618大促已成为消费者和商家共同关注的焦点。然而&#xff0c;在销售额不断攀升的同时…...

JAVA基础教程DAY0-基础知识

JAVA语言的特点 简单性、面向对象、安全性、跨平台性、支持多线程、分布性 面向对象编程&#xff08;Object-Oriented Programming&#xff0c;简称OOP&#xff09;是一种编程范式&#xff0c;它通过将数据和操作这些数据的方法封装在一起&#xff0c;以创建对象的形式来组织代…...

鸿蒙开发Ability Kit(程序访问控制):【安全控件概述】

安全控件概述 安全控件是系统提供的一组系统实现的ArkUI组件&#xff0c;应用集成这类组件就可以实现在用户点击后自动授权&#xff0c;而无需弹窗授权。它们可以作为一种“特殊的按钮”融入应用页面&#xff0c;实现用户点击即许可的设计思路。 相较于动态申请权限的方式&am…...

【信息系统项目管理师】18年~23年案例概念型知识

文章目录 18上18下19上19下20上20下21上21下22年上22年下23年上 18上 请简述 ISO 9000 质量管理的原则 领导作用、 过程方法、 管理的系统方法、 与供方互利的关系、 基于事实的决策方法、 持续改进、 全员参与、 以顾客为关注焦点 概念 国家标准(GB/T 1 9000 2008)对质量的定…...

什么是字符串常量池?如何利用它来节省内存?

字符串常量池是Java中一个非常重要的概念&#xff0c;尤其对于理解内存管理和性能优化至关重要。想象一下&#xff0c;你正在管理一家大型图书馆&#xff0c;每天都有无数读者来借阅书籍。 如果每本书每次借阅都需要重新印刷一本&#xff0c;那么图书馆很快就会陷入混乱&#…...

Selenium自动化测试20条常见异常+处理方案

常见的Selenium异常 以下是所有Selenium WebDriver代码中可能发生的一些常见Selenium异常。 1、ElementClickInterceptedException 由于以某种方式隐藏了接收到click命令的元素&#xff0c;因此无法正确执行Element Click命令。 2、ElementNotInteractableException 即使目…...

verilog将信号和常数拼接起来

正确的拼接 1 s_axis_data_tdata {32b0000_0000_0000_0000_0000_0000_0000_0000,32b0011_1111_1000_0000_0000_0000_0000_0000}; 2 注意&#xff0c;信号的两部分都要用{}花括号括起来 s_axis_data_tdata {{32{1b1}},{32b0100_0000_0000_0000_0000_0000_0000_0000}}; 3…...

OpenSSH远程代码执行漏洞 (CVE-2024-6387)

1. 前言 OpenSSH是一套基于安全外壳&#xff08;SSH&#xff09;协议的安全网络实用程序&#xff0c;它提供强大的加密功能以确保隐私和安全的文件传输&#xff0c;使其成为远程服务器管理和安全数据通信的必备工具。 OpenSSH 自 1995 年问世近 20 年来&#xff0c;首次出现了…...

高薪程序员必修课-java并发编程的bug源头

前言 Java并发编程虽然强大&#xff0c;但也容易引发复杂的bug。并发编程的bug主要源自以下几个方面&#xff1a;竞态条件、死锁、内存可见性问题和线程饥饿。了解这些bug的源头及其原理&#xff0c;可以帮助开发者避免和解决这些问题。以下是详细的讲解和相应的示例。 1. 竞态…...

c++:#include 某文件.h底层如何寻找其.cpp实现

在C中&#xff0c;当你编写了一个头文件&#xff08;如MyLibrary.h&#xff09;和对应的实现文件&#xff08;如MyLibrary.cpp&#xff09;时&#xff0c;其他源文件&#xff08;如main.cpp&#xff09;只需要包含头文件&#xff08;#include "MyLibrary.h"&#xff…...

uniapp中如何进行微信小程序的分包

思路&#xff1a;在uniapp中对微信小程序进行分包&#xff0c;和原生微信小程序进行分包的操作基本上没区别&#xff0c;主要就是在pages.json中进行配置。 如图&#xff0c;我新增了一个包diver-page 此时需要在pages.json中的subPackages数组中新增一项 root代表这个包的根…...

win10下安装PLSQL14连接Oracle数据库

问题背景 在使用Oracle开发过程中&#xff0c;经常会使用工具来连接数据库&#xff0c;方便查询、处理数据。其中有很多工具可以使用&#xff0c;比如dbeaver、plsql等。本文主要介绍在win10环境下&#xff0c;plsql14的安装步骤以及安装过程中遇到的一些问题。 安装步骤及问题…...

高考失利咨询复读,银河补习班客服开挂回复

补习班的客服在高考成绩出来后&#xff0c;需要用专业的知识和足够的耐心来回复各种咨询&#xff0c;聊天宝快捷回复软件&#xff0c;帮助客服开挂回复。 ​ 前言 高考成绩出来&#xff0c;几家欢喜几家愁&#xff0c;对于高考失利的学生和家长&#xff0c;找一个靠谱的复读补…...

java 代码块

Java中的代码块主要有三种类型&#xff1a;普通代码块、静态代码块、构造代码块。它们的用途和执行时机各不相同。 普通代码块&#xff1a;在方法内部定义&#xff0c;使用一对大括号{}包围的代码片段。它的作用域限定在大括号内&#xff0c;每当程序执行到该代码块时就会执行其…...

vue中避免多次请求字典接口

vuex缓存所有字典项 背景vuex管理所有字典项调用字典接口处理字典项数据的filter页面中使用字典 背景 每次用到字典都需要通过对应的字典type调用一次字典接口&#xff0c;当一个页面用到字典项很多时&#xff0c;接口请求炒鸡多&#xff0c;会导致接口响应超时。 本篇文章改为…...

Snappy使用

Snappy使用 Snappy是谷歌开源的压缩和解压的开发包&#xff0c;目标在于实现高速的压缩而不是最大的压缩 项目地址&#xff1a;GitHub - google/snappy&#xff1a;快速压缩器/解压缩器 Cmake版本升级 该项目需要比较新的cmake&#xff0c;CMake 3.16.3 or higher is requi…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践

01技术背景与业务挑战 某短视频点播企业深耕国内用户市场&#xff0c;但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大&#xff0c;传统架构已较难满足当前企业发展的需求&#xff0c;企业面临着三重挑战&#xff1a; ① 业务&#xff1a;国内用户访问海外服…...