《JavaEE进阶》----20.<基于Spring图书管理系统①(登录+添加图书)>

news2024/11/23 15:35:07

PS:关于接口定义

接口定义,通常由服务器提供方来定义。

1.路径:自己定义

2.参数:根据需求考虑,我们这个接口功能完成需要哪些信息。

3.返回结果:考虑我们能为对方提供什么。站在对方角度考虑。

我们使用到的技术:

前端:”是自己在网上找的代码

后端

  • IDEA
  • Maven
  • MySQL+Mybatis
  • SSM 

实现的功能:

  1. 用户登录
  2. 添加图书
  3. 显示图书列表
  4. 更新图书
  5. 删除图书
  6. 批量删除图书
  7. 强制登录
  8. 引入统一功能

做这个管理系统,首先我们需要考虑到什么呢?

第一步建立数据库

比如登录、用户要输入 用户名 和 密码。

因此对于数据库。我们需要一张用户表。用来存储用户名和密码。

还需要配置数据库 & 日志文件

搞完数据库相关的。就要写代码了。

第二步创建实体类

我们需要根据数据库字段创建一些实体类。


第三步实现用户登录功能

第四步实现添加图书功能

第五步实现显示图书列表功能

第六步实现更新图书功能

第七步实现删除图书功能

第八步实现批量删除图书

第九步实现强制登录

第十步加上统一功能

预览整体项目

首页

登录进去 

 

可以进行翻页 

添加图书 

 

批量删除 

修改图书 

删除图书 

一、建立数据库

1.1配置数据库 & 日志

server:  #端口号配置
  port: 1208
spring:
  datasource: # 数据库连接配置
    url: jdbc:mysql://127.0.0.1:3306/book_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 12345678
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 配置打印 MyBatis⽇志
    map-underscore-to-camel-case: true #配置驼峰⾃动转换
  mapper-locations: classpath:mapper/**Mapper.xml # 配置mybatis xml的⽂件路径,在resources/mapper创建所有表的xml⽂件
  # classpath对应resources这个目录,接下来说明在mapper这个文件夹下面,以Mapper.xml结束的都可以被加载

# 设置⽇志⽂件的⽂件名
logging:
  file:
    name: spring-book.log

 我们新建一个book_test数据库。

DROP DATABASE IF EXISTS book_test;
CREATE DATABASE book_test DEFAULT CHARACTER SET utf8mb4;

①新建一个用户表

DROP TABLE IF EXISTS user_info;
CREATE TABLE user_info (
    `id` INT NOT NULL AUTO_INCREMENT,
    `user_name` VARCHAR ( 128 ) NOT NULL,
    `password` VARCHAR ( 128 ) NOT NULL,
    `delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,
    `create_time` DATETIME DEFAULT now(),
    `update_time` DATETIME DEFAULT now() ON UPDATE now(),
    PRIMARY KEY ( `id` ), --将 id 列设置为主键,保证每条记录唯一
    UNIQUE INDEX `user_name_UNIQUE` ( `user_name` ASC )
--指定了索引的列以及排序方式。在此例中,user_name 列按照升序(ASC)排序。
--默认是升序,因此这里 ASC 是可选的。
) 
    ENGINE = INNODB --设置存储引擎为 InnoDB,支持事务和外键
    DEFAULT CHARACTER SET = utf8mb4 COMMENT = '⽤⼾表';

②新建图书表

DROP TABLE IF EXISTS book_info;
CREATE TABLE `book_info` (
    `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
    `book_name` VARCHAR ( 127 ) NOT NULL,
    `author` VARCHAR ( 127 ) NOT NULL,
    `count` INT ( 11 ) NOT NULL,
    `price` DECIMAL (7,2 ) NOT NULL,
    `publish` VARCHAR ( 256 ) NOT NULL,
    `status` TINYINT ( 4 ) DEFAULT 1 COMMENT '0-⽆效, 1-正常, 2-不允许借阅',
    `create_time` DATETIME DEFAULT now(),
    `update_time` DATETIME DEFAULT now() ON UPDATE now(),
    PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

初始化数据

-- 初始化数据 
INSERT INTO user_info ( user_name, PASSWORD ) VALUES ( "admin", "admin" );
INSERT INTO user_info ( user_name, PASSWORD ) VALUES ( "zhangsan", "123456" );
-- 初始化图书数据 
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES
 ('活着', '余华', 29, 22.00, '北京⽂艺出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES
 ('平凡的世界', '路遥', 5, 98.56, '北京⼗⽉⽂艺出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES
 ('三体', '刘慈欣', 9, 102.67, '重庆出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES
 ('⾦字塔原理', '⻨肯锡', 16, 178.00, '⺠主与建设出版社');

下面是我们建好后的用户表

图书表

二、创建实体类

2.1 用户实体类UserInfo实体类

package com.qiyangyang.springbook.demos.model;

import lombok.Data;
import java.util.Date;
@Data
public class UserInfo {
    private Integer id;
    private String userName;
    private String password;
    private Integer delete_flag;
    private Date createTime;
    private Date updateTime;
}

2.2 图书实体类 BookInfo实体类

package com.qiyangyang.springbook.demos.model;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class BookInfo {
    private Integer id;
    private String bookName;
    private String author;
    private Integer count;
    private BigDecimal price;
    private String publish;
    private Integer status;//1-可借阅   2-不可借阅  0-已删除
    private String stateCN;//根据book状态设置描述
    private Date createTime;
    private Date updateTime;
}

 三、实现用户登录接口

 3.1约定前后端交互接口

[请求]
/user/login
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

[参数]
name=zhangsan&password=123456

[响应]
true //账号密码验证正确, 否则返回false

浏览器给服务器发送 /user/login 这样的 HTTP 请求, 服务器给浏览器返回了一个Boolean类型 的数据.返回true,表示账号密码验证正确 

3.2实现(后端)服务器代码

3.2.1控制层

从数据库查询用户名和密码,如果可以查到并且密码一致,就认为登录成功。

创建UserController

package com.qiyangyang.springbook.demos.controller;

import com.qiyangyang.springbook.demos.model.UserInfo;
import com.qiyangyang.springbook.demos.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;

@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("/login")
    public boolean login(String userName, String password, HttpSession session){
        /**
         * 校验参数
         */
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
        }
        //判断用户输入的密码和用户输入的密码是否一致
        //我们需要查询数据库,得到数据库的密码
        UserInfo userInfo = userService.queryByName(userName);
        if(userInfo == null){
            //用户不存在
            return false;
        }
        if(password.equals(userInfo.getPassword())){
            //将密码置为空,不置为空也可以,因为Session是在服务器上的数据,客户端也看不到
            //session也是占内存的因此,不需要的不存。
            /**
             * 如果密码正确
             * 存Session
             */
            //由于密码信息是没用的,用不到。我们设置成空。不设置成空也行,因为存在服务器。客户端是看不到的
            userInfo.setPassword("");
            session.setAttribute("user_session",userInfo);
            return true;
        }
        return false;
    }
}
/**
package com.qiyangyang.springbook.demos.controller;

import com.qiyangyang.springbook.demos.model.UserInfo;
import com.qiyangyang.springbook.demos.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;

@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("/login")
    public boolean login(String userName, String password, HttpSession session){
        /**
         * 校验参数
         */
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
        }
        //判断用户输入的密码和用户输入的密码是否一致
        //我们需要查询数据库,得到数据库的密码
        UserInfo userInfo = userService.queryByName(userName);
        if(userInfo == null){
            //用户不存在
            return false;
        }
        if(password.equals(userInfo.getPassword())){
            //将密码置为空,不置为空也可以,因为Session是在服务器上的数据,客户端也看不到
            //session也是占内存的因此,不需要的不存。
            /**
             * 如果密码正确
             * 存Session
             */
            //由于密码信息是没用的,用不到。我们设置成空。不设置成空也行,因为存在服务器。客户端是看不到的
            userInfo.setPassword("");
            session.setAttribute("user_session",userInfo);
            return true;
        }
        return false;
    }
}
/**
 * HttpSession session
 * 存的是根据SessionId获取的Session对象,每一个sessionId对应一个session对象。
 * 会根据客户端等等判断是新用户还是老用户。服务器里面存了很多session。
 * SessionId在后端通过服务器生成并通过 Cookie 发送给客户端。
 *
 */
 *
 */

问题1:每次我们存的Session都一样。后面用户。存的Session会覆盖前面用户的Session吗?

答:同一个用户会覆盖,不同用户,不同客户端不会覆盖。

Session表示的是会话,对话。是有来有回的,而且是多个回合。

 * HttpSession session
 * 存的是根据SessionId获取的Session对象,每一个sessionId对应一个session对象。
 * 会根据客户端等等判断是新用户还是老用户。服务器里面存了很多session。
 * SessionId在后端通过服务器生成并通过 Cookie 发送给客户端。


问题2:如果多个客户端同时访问,需不需要加多线程?

答:不需要,因为我们没有使用多线程。

请求的隔离框架已经帮我们做了。因此不考虑多线程。

什么时候才去做多线程呢,比如程序里面用到了线程池。才考虑多线程。每个用户进来login函数。信息存放在栈里面,栈是线程私有的。堆是线程公有的。这些成员变量存储在栈里面,因此每个用户的信息之间没有关系。分别对应不同的对象。

在我们需要进行优化的时候考虑多线程。比如要查询两次数据。第一次得到了密码,可以因为业务需要还要查询一次。这时候串行查询觉得太慢了。这时候考虑多线程。就可以进行并行查询。加了多线程我们就要考虑线程安全的情况。代码里用到多线程,才考虑多线程。

校验密码我们推荐在业务逻辑层来写,由于这里比较简单。我们就写在Controller中

3.2.2 业务层

创建UserService

package com.qiyangyang.springbook.demos.service;

import com.qiyangyang.springbook.demos.mapper.UserInfoMapper;
import com.qiyangyang.springbook.demos.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;

    /**
     * 从数据库中查询用户信息
     * @param userName
     * @return
     */
    public UserInfo queryByName(String userName){
        return userInfoMapper.queryByName(userName);
    }
}

3.2.3数据层

创建UserInfoMapper

package com.qiyangyang.springbook.demos.mapper;

import com.qiyangyang.springbook.demos.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserInfoMapper {
    @Select("select * from user_info where delete_flag = 0 and user_name=#{userName}")
    UserInfo queryByName(String userName);


}

 3.3后端校验

使用Postman校验。多次实验发现,校验成功。然后我们再去写前端的代码。

3.4实现前端代码

3.4.1 ajax 部分

    <script src="js/jquery.min.js"></script>
    <script>
        function login() {
            $.ajax({
               type:"post",
                url:"/user/login",
                data:{
                   userName:$("#userName").val(),
                    password:$("#password").val()
                },
                success:function (result) {
                    if(result===true){
                        //验证成功
                        location.href = "book_list.html";
                    }else {
                        alert("登录失败,用户名不存在或密码错误!");
                    }
                }
            });
        }
    </script>

3.4.2完整前端登录代码 

<!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="350px">
        </div>
        <div class="login-dialog">
            <h3>登陆</h3>
            <div class="row">
                <span>用户名</span>
                <input type="text" name="userName" id="userName" class="form-control">
            </div>
            <div class="row">
                <span>密码</span>
                <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:{
                   userName:$("#userName").val(),
                    password:$("#password").val()
                },
                success:function (result) {
                    if(result===true){
                        //验证成功
                        location.href = "book_list.html";
                    }else {
                        alert("登录失败,用户名不存在或密码错误!");
                    }
                }
            });
        }
    </script>
</body>

</html>

3.5完整校验前后端交互 

输入正确用户名和密码

成功登录,并且跳转到图书目录页面。 

输入错误用户名和密码。登录失败。弹框显示用户名不存在或密码错误。 

四、实现添加图书接口

4.1约定前后端交互

[请求]

/book/addBook

Content-Type: application/x-www-form-urlencoded; charset=UTF-8

[参数]

bookName=图书1&author=作者1&count=23&price=36&publish=出版社1&status=1

[响应]

"成功添加图书"  //失败信息, 成功时返回空字符串

我们约定浏览器给服务器发送/book/addBook 这样的HTTP请求。

form表单的形式来提交数据。服务器返回处理结果。返回“”表示图书添加成功。否则,返回失败信息。

4.2实现(后端)服务器代码

4.2.1控制层

创建BookController类

@Slf4j
@RestController
@RequestMapping("book")
public class BookController {

    @Autowired
    private BookService bookService;
    @RequestMapping("/addBook")
    public String addBook(BookInfo bookInfo){
        log.info("添加图书,bookInfo:{}",bookInfo);
        /**
         * 参数校验
         */
        if(!StringUtils.hasLength(bookInfo.getBookName())
                || !StringUtils.hasLength(bookInfo.getAuthor())
                || !StringUtils.hasLength(bookInfo.getPublish())
                || bookInfo.getCount() <=0
                || bookInfo.getPrice()==null){
            return "参数错误";
        }
        /**
         * 添加图书
         */
        /**
         * 出现错误比如参数错误。添加过程出现异常,因为MySQL会出现一些异常
         * 我们使用try/catch来捕获。
         */
        try {
            bookService.insertBook(bookInfo);
        }catch (Exception a){
            return "内部发生错误,请联系管理员";
        }
        /**
         * 返回成功添加吐过表示图书插入成功。
         */
        return "成功添加图书";
    }
}

4.2.2 业务层

创建BookService类

@Service
public class BookService {
    @Autowired
    private BookInfoMapper bookInfoMapper;

    public Integer insertBook(BookInfo bookInfo){
        return bookInfoMapper.insertBook(bookInfo);
    }
}

4.2.3 数据层

创建BookInfoMapper

@Mapper
public interface BookInfoMapper {
    @Insert("insert into book_info(book_name,author,count,price,publish) " +
            "values (#{bookName},#{author},#{count},#{price},#{publish})")
    Integer insertBook(BookInfo bookInfo);
}

4.3后端测试

填写正确数据,返回成功添加图书

填写错误数据,返回参数错误 

 

小bug (后端服务器问题)

count 和 price为字符串时,会报400错误。请求参数类型不匹配。

日志显示在绑定 bookInfo 对象时出现了类型转换错误:

  • count 字段:后端定义 count 应为 Integer,但接收到的值是 "五大"(字符串)。
  • price 字段:后端定义 price 应为 BigDecimal,但接收到的值是 "带娃"(字符串)。

因为这些值无法转换成期望的数值类型,所以 Spring 在尝试绑定请求参数时抛出了 BindException,并返回 HTTP 400 错误,表示请求的格式或内容无效。

 

4..4实现前端代码 

4.4.1 form表单 和 ajax 部分

form表单

我们可以把提交的数据写成一个form表单。

form表单 Id 在前端显示页面并没有什么作用。主要是搭配后端来进行前后端交互。 

整个表单内容需要提交的话,我们可以借助form标签来提交整个表单

         

data: $("#addBook").serialize(), //序列化

 //这个函数会把整个表单的所有的input框..等等输入的项目都会提交

提交的结构是以key : value 键值对的形式提交

key就是name

value就是输入的值。

      <form id="addBook">
        <div class="form-group">
          <label for="bookName">图书名称:</label>
          <input
            type="text"
            class="form-control"
            placeholder="请输入图书名称"
            id="bookName"
            name="bookName"
          />
        </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="javascript:history.back()">返回</button>
            </div>
        </form>

ajax部分 

    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script>
        function add() {
            $.ajax({
                type:"post",
                url:"/book/addBook",
//整个表单内容需要提交的话,我们可以借助form标签来提交整个表单,搭配后端做一些交互来使用的。
                data: $("#addBook").serialize(),//序列化
//这个函数会把整个表单的所有的input框..等等输入的项目都会提交
                success:function (result) {
                    if(result === "成功添加图书"){
                        alert("添加成功");
                        location.href = "book_list.html";
                    }else {
                        alert(result);
                    }
                }
            });

        }
    </script>

4.4.2完整前端添加图书代码

<!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"
          >
            <path
              d="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="javascript:history.back()"
          >
            返回
          </button>
        </div>
      </form>
    </div>
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script>
      function add() {
        $.ajax({
          type: "post",
          url: "/book/addBook",
          //整个表单内容需要提交的话,我们可以借助form标签来提交整个表单,搭配后端做一些交互来使用的。
          data: $("#addBook").serialize(), //序列化
          //这个函数会把整个表单的所有的input框..等等输入的项目都会提交
          success: function (result) {
            if (result === "成功添加图书") {
              alert("添加成功");
              location.href = "book_list.html";
            } else {
              alert(result);
            }
          },
        });
      }
    </script>
  </body>
</html>

4.5完整校验前后端交互

输入正确数据

成功添加到我们的数据库中。 

输入错误数据。

弹框提示输入参数错误! 

本篇内容已经很多。

后续内容在下一篇文章中!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaEE】文件io

目录 文件类型 File概述 属性 构造方法 常用方法 Reader Writer InputStream OutputStream 字节流转字符流 通过Scanner读取InputStream 通过PrintWriter转换outputstream 示例 文件类型 从编程的角度看&#xff0c;文件类型主要就是两大类 文本&#xff08;文…

D3入门:概念、主要特点、基本功能、常见应用场景

D3.js&#xff08;Data-Driven Documents&#xff09;是一个JavaScript库&#xff0c;用于基于数据操作文档。它利用了HTML、SVG和CSS等Web标准技术&#xff0c;使得开发者可以创建丰富的交互式图表和数据可视化。D3.js的强大之处在于其灵活的数据绑定机制和对DOM元素的高效操作…

go函数传值是值传递?还是引用传递?slice案例加图解

先说下结论 Go语言中所有的传参都是值传递&#xff08;传值&#xff09;&#xff0c;都是一个副本&#xff0c;一个拷贝。 值语义类型&#xff1a;参数传递的时候&#xff0c;就是值拷贝&#xff0c;这样就在函数中就无法修改原内容数据。 基本类型&#xff1a;byte、int、bool…

tensorflow案例5--基于改进VGG16模型的马铃薯识别,准确率提升0.6%,计算量降低78.07%

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 本次采用VGG16模型进行预测&#xff0c;准确率达到了98.875&#xff0c;但是修改VGG16网络结构&#xff0c; 准确率达到了0.9969&#xff0c;并且计算量…

攻防世界38-FlatScience-CTFWeb

攻防世界38-FlatScience-Web 点开这个here看到一堆pdf,感觉没用&#xff0c;扫描一下 试试弱口令先 源码里有&#xff1a; 好吧0.0 试试存不存在sql注入 根本没回显&#xff0c;转战login.php先 输入1’,发现sql注入 看到提示 访问后得源码 <?php ob_start(); ?>…

数据分析-44-时间序列预测之深度学习方法TCN

文章目录 1 TCN简介1.1 网络示意图1.2 TCN优点2 模拟应用2.1 模拟数据2.2 预处理创建滞后特征2.3 划分训练集和测试集2.4 创建TCN模型2.5 模型训练2.6 模型预测3 自定义my_TCN模型3.1 my_TCN()函数3.2 训练模型3.3 模型预测3.4 改进4 参考附录1 TCN简介 时间卷积网络(TCN)是…

C++【STL容器系列(二)】vector的模拟实现

文章目录 1. vector的结构2. vector的默认成员函数2.1构造函数2.1.1 默认构造2.1.2 迭代器构造2.1.3 用n个val初始化构造 2.2 拷贝构造2.3 析构函数2.4 operator 3. vector iterator函数3.1 begin 和 cbegin函数3.2 end() 和 cend()函数 4. vector的小函数4.1 size函数4.2 capa…

【linux】网络基础 ---- 应用层

1. 再谈 "协议" 协议是一种 "约定"&#xff0c;在读写数据时, 都是按 "字符串" 的方式来发送接收的. 但是这里我们会遇到一些问题&#xff1a; 如何确保从网上读取的数据是否是完整的&#xff0c;区分缓冲区中的由不同客户端发来的数据 2. 网…

C语言PythonBash:空白(空格、水平制表符、换行符)与转义字符

C语言 空白 C语言中的空白&#xff08;空格、水平制表符、换行符&#xff09;被用于分隔Token&#xff0c;因此Token间可以有任意多个空白。 // 例1 printf("Hello, World!"); 例1中存在5个Token&#xff0c;分别是&#xff1a; printf("Hello, World! \n&qu…

Linux基础(十四)——BASH

BASH 1.BASH定义2.shell的种类3.bash的功能3.1 命令记录功能3.2 命令补全功能3.3 命令别名设置3.4 工作控制、 前景背景控制3.5 程序化脚本&#xff1a; &#xff08; shell scripts&#xff09;3.6 万用字符 4.bash的内置命令5.shell的变量功能5.1 变量的取用5.2 新建变量5.3 …

【重学 MySQL】八十二、深入探索 CASE 语句的应用

【重学 MySQL】八十二、深入探索 CASE 语句的应用 CASE语句的两种形式CASE语句的应用场景数据分类动态排序条件计算在 SELECT 子句中使用在 WHERE子句中使用在 ORDER BY 子句中使用 注意事项 在MySQL中&#xff0c;CASE 语句提供了一种强大的方式来实现条件分支逻辑&#xff0c…

由播客转向个人定制的音频频道(1)平台搭建

项目的背景 最近开始听喜马拉雅播客的内容&#xff0c;但是发现许多不方便的地方。 休息的时候收听喜马拉雅&#xff0c;但是还需要不断地选择喜马拉雅的内容&#xff0c;比较麻烦&#xff0c;而且黑灯操作反而伤眼睛。 喜马拉雅为代表的播客平台都是VOD 形式的&#xff0…

7+纯生信,单细胞识别细胞marker+100种机器学习组合建模,机器学习组合建模取代单独lasso回归势在必行!

影响因子&#xff1a;7.3 研究概述&#xff1a; 皮肤黑色素瘤&#xff08;SKCM&#xff09;是所有皮肤恶性肿瘤中最具侵袭性的类型。本研究从GEO数据库下载单细胞RNA测序&#xff08;scRNA-seq&#xff09;数据集&#xff0c;根据原始研究中定义的细胞标记重新注释各种免疫细胞…

uniapp解析蓝牙设备响应数据bug

本文章为了解决《uniapp 与蓝牙设备收发指令详细步骤(完整项目版)》中第十步的Array 解析成 number函数bug 1、原代码说明 function array16_to_number(arrayValue) {const newArray arrayValue.filter(item > String(item) ! 00 || String(item) ! 0)const _number16 ne…

【递归回溯与搜索算法篇】算法的镜花水月:在无尽的自我倒影中,递归步步生花

文章目录 递归回溯搜索专题&#xff08;一&#xff09;&#xff1a;递归前言第一章&#xff1a;递归基础及应用1.1 汉诺塔问题&#xff08;easy&#xff09;解法&#xff08;递归&#xff09;C 代码实现时间复杂度和空间复杂度易错点提示 1.2 合并两个有序链表&#xff08;easy…

大数据开发面试宝典

312个问题&#xff0c;问题涵盖广、从自我介绍到大厂实战、19大主题&#xff0c;一网打尽、真正提高面试成功率 一、Linux 1. 说⼀下linux的常⽤命令&#xff1f; 说一些高级命令即可 systemctl 设置系统参数 如&#xff1a;systemctl stop firewalld关闭防火墙 tail / hea…

链表归并与并集相关算法题|两递增归并为递减到原位|b表归并到a表|两递减归并到新链表(C)

两递增归并为递减到原位 假设有两个按元素递增次序排列的线性表&#xff0c;均以单链表形式存储。将这两个单链表归并为一个按元素递减次序排列的单链表&#xff0c;并要求利用原来两个单链表的节点存放归并后的单链表 算法思想 因为两链表已按元素值递增次序排列&#xff0…

【RabbitMQ】06-消费者的可靠性

1. 消费者确认机制 没有ack&#xff0c;mq就会一直保留消息。 spring:rabbitmq:listener:simple:acknowledge-mode: auto # 自动ack2. 失败重试机制 当消费者出现异常后&#xff0c;消息会不断requeue&#xff08;重入队&#xff09;到队列&#xff0c;再重新发送给消费者。…

【陕西】《陕西省省级政务信息化项目投资编制指南(建设类)(试行)》-省市费用标准解读系列07

《陕西省省级政务信息化项目投资编制指南&#xff08;建设类&#xff09;&#xff08;试行&#xff09;》规定了建设类项目的费用投资测算方法与计价标准&#xff0c;明确指出建设类项目费用包括项目建设费和项目建设其他费&#xff08;了解更多可直接关注咨询我们&#xff09;…

VB6.0桌面小程序(桌面音乐播放器)

干货源码 Imports System.IO Imports System.Security.Cryptography Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Button1.Text “上一曲” Button4.Text “播放” Button3.Text “下一曲” Button2.Text “顺序播…