【Spring】简单的登录案例和配套知识

news2024/11/19 14:45:42

本篇文章接着介绍 Spring 的相关知识,主要通过一个非常非常简单用户登录案例来介绍,各位大佬们路过记得赏小的一颗赞🤩


文章目录

  • 1. 演示一下 Spring 管理类的模式
  • 2. 用户登录案例
    • 2.1 准备的对象和其功能
      • 2.1.1 User
      • 2.1.2 UserController
      • 2.1.3 UserService
      • 2.1.4 UserDao
      • 2.1.5 AppConfig
      • 2.1.6 DemoApplication
    • 2.2 各对象之间的依赖关系
    • 2.3 IOC 带来的一个好处
  • 3. Spring 中的日志打印
    • 3.1 Spring 官方提供的方式
    • 3.2 lombok 提供的方法
    • 3.2 日志打印级别
    • 3.3 修改当前日志级别

1. 演示一下 Spring 管理类的模式

下面代码在第一次打印 Person 对象的时候,pid = 0,name = null,

第二次打印的时候,pid 有值,name 依旧是 null

第三次打印的时候,pid 和 name 都有值

而 pid 和 name 是由不同的两个类赋值的,说明这两个类被注入了同一个 Bean,由此可知 Spring 管理对象采用单例模式

一般在 Java 中,表过程的对象总是以单例的方式出现,表数据的对象无法使用单例管理,所以,一般让 Spring 管理的对象大多是表过程的对象(不是绝对的)

@Component
public class Person {
    int pid;
    String name;

    @Override
    public String toString() {
        return "Person{" +
                "pid=" + pid +
                ", name='" + name + '\'' +
                '}';
    }
}
@Component
public class Person1 {

    @Autowired
    public void usePerson1(Person person) {
        System.out.println("usePerson1(), person = " + person);
        person.pid = 20221024;
    }
}
@Component
public class Person2 {

    @Autowired
    public void usePerson2(Person person) {
        System.out.println("usePerson2(), person = " + person);
        person.name = "hsq";
    }
}
@SpringBootApplication
public class DemoApplication {

   public static void main(String[] args) throws Exception {
      ApplicationContext context = SpringApplication.run(DemoApplication.class, args);

      Person bean = context.getBean(Person.class);
      System.out.println(bean);
   }

}

请添加图片描述

2. 用户登录案例

没有用到 Web 的形式,仅仅只是从控制台输入输出,然后将数据存入数据库

2.1 准备的对象和其功能

在 IOC 之外的场景下,Bean 注入的注释标签就要有一些区分了

2.1.1 User

表示用户本身(属性,构造方法,toString)

public class User {
    public Integer uid;
    public String username;
    public String password;

    public User() {}

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(Integer uid, String username, String password) {
        this.uid = uid;
        this.username = username;
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(uid, user.uid);
    }

    @Override
    public int hashCode() {
        return Objects.hash(uid);
    }
}

2.1.2 UserController

进行用户输入、输出的操作(不同于 Web 的模式,这里的输入输出通过 Scanner(System.in) 和 System.out 控制)

@Controller
public class UserController {
    // 依赖输入、输出,我们自己不强调一定是标准输入输出
    private final Scanner scanner;
    private final PrintWriter writer;
    private final UserService userService;

    // 全部让 Spring 帮我们注入
    @Autowired
    public UserController(Scanner scanner, PrintWriter writer, UserService userService) {
        this.scanner = scanner;
        this.writer = writer;
        this.userService = userService;
    }

    public void run() throws Exception {
        while (true) {
            writer.print("请选择是注册还是登录:");
            writer.flush();
            String func = scanner.nextLine();
            if (func.equals("注册")) {
                writer.println("您选择了【注册】功能,接下来请输入用户名和密码");
                writer.print("请输入用户: ");
                writer.flush();
                String username = scanner.nextLine();
                writer.print("请输入密码: ");
                writer.flush();
                String password = scanner.nextLine();

                User user = userService.register(username, password);

                writer.println("注册完成,您的用户信息是: " + user);
            } else if (func.equals("登录")) {
                writer.println("您选择了【登录】功能,接下来请输入用户名和密码");
                writer.print("请输入用户: ");
                writer.flush();
                String username = scanner.nextLine();
                writer.print("请输入密码: ");
                writer.flush();
                String password = scanner.nextLine();

                User user = userService.login(username, password);
                if (user == null) {
                    writer.println("登录失败");
                } else {
                    writer.println("登录成功,您的用户信息是: " + user);
                }
            }
        }
    }
}

2.1.3 UserService

进行必要的数据操作,进行密码的加密和解密

@Service
public class UserService {
    // UserService 对象依赖 UserDao 对象
    // 直接使用注入的方式
    private final UserDao userDao;

    // 构造方法注入
    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public User register(String username, String password) throws Exception {
        // 1. 密码的 hash 加密
        String salt = BCrypt.gensalt();
        password = BCrypt.hashpw(password, salt);

        // 2. 进行插入
        User user = new User(username, password);
        userDao.insert(user);

        // 3. 返回构造完成的用户对象
        return user;
    }

    public User login(String username, String password) throws Exception {
        // 1. 先查询用户
        User user = userDao.selectOneByUsername(username);
        if (user == null) {
            return null;
        }

        // 2. 进行密码的比较
        if (!BCrypt.checkpw(password, user.password)) {
            return null;
        }

        // 3. 返回构造完成的用户对象
        return user;
    }
}

上面代码中用到的 BCrypt 算法是一种密码加密算法,代码篇幅过长,有需要的大佬可以去自行下载 —— BCrypt 加密算法下载

2.1.4 UserDao

对数据库进行操作

@Repository
public class UserDao {
    private static final Logger log = LoggerFactory.getLogger(UserDao.class);

    // 依赖 DataSource 对象才能完成
    // 需要 Spring 帮我们注入 DataSource 对象
    private final DataSource dataSource;

    // 使用构造方法注入(依赖注入)
    @Autowired
    public UserDao(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void insert(User user) throws Exception {
        try (Connection c = dataSource.getConnection()) {
            String sql = "insert into users (username, password) values (?, ?)";
            try (PreparedStatement ps = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
                ps.setString(1, user.username);
                ps.setString(2, user.password);

                log.info("执行的 SQL = {} ", ps);
                ps.executeUpdate();

                try (ResultSet rs = ps.getGeneratedKeys()) {
                    rs.next();
                    user.uid = rs.getInt(1);
                }
            }
        }
    }

    public User selectOneByUsername(String username) throws Exception {
        try (Connection c = dataSource.getConnection()) {
            String sql = "select uid, username, password from users where username = ?";
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setString(1, username);

                log.info("执行的 SQL = {} ", ps);

                try (ResultSet rs = ps.executeQuery()) {
                    if (!rs.next()) {
                        return null;
                    }

                    return new User(
                            rs.getInt("uid"),
                            rs.getString("username"),
                            rs.getString("password")
                    );
                }
            }
        }
    }
}

2.1.5 AppConfig

因为案例只是我自己写的,所以前面代码中所注入的 Bean,我需要自行注册进 Spring,这里采用方法注册。并且在这里配置数据库

@Configuration
public class AppConfig {
    @Bean
    public Scanner scanner() {
        return new Scanner(System.in);
    }

    @Bean
    public PrintWriter writer() {
        // PrintStream -> PrintWriter
        PrintStream printStream = System.out;

        return new PrintWriter(printStream, true);
    }

    @Bean
    public DataSource dataSource() {
        MysqlDataSource dataSource = new MysqlDataSource();
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai");
        dataSource.setUser(" ");	// 数据库用户名
        dataSource.setPassword(" ");	// 数据库密码
        return dataSource;
    }
}

2.1.6 DemoApplication

主类,程序的入口,调用 UserController 中的 run() 方法开始程序

@SpringBootApplication
public class DemoApplication {

   public static void main(String[] args) throws Exception {
      ApplicationContext context = SpringApplication.run(DemoApplication.class, args);

      UserController userController = context.getBean(UserController.class);
      userController.run();
   }

}

2.2 各对象之间的依赖关系

请添加图片描述

2.3 IOC 带来的一个好处

我们去依赖抽象的概念,不需要具体的实现

好处是,我们可以很方便的替换背后的依赖对象。比如:刚才我们依赖的 Scanner 对象是从标准输入读取的,我们可以很方便的替换成读取文件的方式

只需修改 AppConfig 对象中的 Scanner 方法为以下即可

public Scanner scanner() throws FileNotFoundException {
//        return new Scanner(System.in);
        File file = new File("input.txt");
        return new Scanner(file, "UTF-8");
}

3. Spring 中的日志打印

3.1 Spring 官方提供的方式

先得到 log 对象,再调用其中方法打印日志即可

private static final Logger log = LoggerFactory.getLogger(UserDao.class);


log.info("执行的 SQL = {} ", ps);

3.2 lombok 提供的方法

使用 @Slf4j 注释修饰此类,然后使用 log 调用方法打印即可,前提是必须要有 lombok 插件

3.2 日志打印级别

比当前日志级别低的打印方式不会有结果

如:当前日志级别为 info 时,那么用 debug 打印不会有结果

请添加图片描述

3.3 修改当前日志级别

默认日志级别是 info ,我们可以在配置文件中修改当前日志级别

在配置文件中写入如下代码,即可将 com.hsq.demo 包下的日志文件修改为 debug

logging.level.com.hsq.demo=debug

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

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

相关文章

05、JavaWeb启程——JDBC详解

1、JDBC概述 1、持久化概述 【简介】: 持久化指的是把内存中的数据存储到可掉电存储设备中以供之后使用。 2、JDBC概述 【简介】: JDBC是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一的访问。 【JDBC本质】&#xff1…

【Java】泛型

当你觉得这条路很难走的时候,一定是上坡路 目录 1.初识泛型 1.1 什么是泛型 1.2泛型类语法 1.2.1泛型类定义 1.2.2泛型类使用语法 1.2.3泛型类的使用 1.2.4裸类型 2.泛型如何编译 2.1擦除机制 3.泛型的上界 3.1语法 3.2示范 4.泛型方法 4.1 语法 …

i.MX 6ULL 驱动开发 十九:RGBLCD

一、RGBLCD 硬件原理 【正点原子MP157连载】第十八章 RGB LCD彩条显示实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7_正点原子的博客-CSDN博客 ATK7016 时序参数: 二、eLCDIF 接口 eLCDIF 是 I.MX6U 自带的液晶屏幕接口,用于连接 RGB …

【Linux】没有GDB,何谈Linux C

一、简单的开始 1、有C代码如下 #include <stdio.h>void main() {printf("Hello World!"); }2、通过gcc编译 生成带有调试信息的可运行程序&#xff0c;编译参数-g gcc -g hello.c -o hello3、运行GDB -q表示不打印gdb版本信息&#xff0c;界面较为干净 …

linux内核调试工具之kprobe

目录 一、内核调试的痛点 二、kprobe的优点 三、kprobe探测点的要点 四、探测点的开销与优化 五、内核配置 六、API 七、程序架构 八、实例 一、内核调试的痛点 内核调试&#xff0c;添加打印信息。在运行过程中想看某个函数的变量&#xff0c;需要重新编译内核。这样破…

【C语言】指针(进阶)

目录一、字符指针二、数组指针2.1、数组指针的定义2.2、&数组名和数组名2.3、数组指针的使用三、数组传参、指针传参3.1、一维数组传参3.2、二维数组传参3.3、一级指针传参3.4、二级指针传参四、函数指针五、函数指针数组六、指向函数指针数组的指针七、回调函数一、字符指…

【C语言小游戏】详解三子棋,深刻掌握二维数组

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#xff0c;今天带领大家实现一个C语言小游戏&#xff0c;主要运用的知识点为二维数组&#xff0c;希望这篇文章让大家对二维数组有更深刻的认识。 &#x1f49e;看似不起波澜的日复一日&#xff0c;会突然在某一天让人看到坚持…

【day14】【洛谷算法题】-P5711闰年判断-刷题反思集[入门2分支结构]

&#x1f338;大家好&#xff0c;我是花无缺&#xff0c;一枚热爱生活的新时代青年&#xff0c;感谢你的阅读&#x1f970;~ &#x1f468;‍&#x1f4bb;个人主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专…

PC - 史上最简单的远程访问群晖 NAS 方法

文章目录1、下载安装cpolar群晖套件1.1 注册cpolar账号1.2 下载cpolar群晖套件1.3 安装cpolar群晖套件2、创建隧道映射5000端口2.1 打开cpolar群晖套件2.2 创建远程访问隧道2.3 获取公网URL地址3、公网远程群晖NAS教大家一个新手小白都可以轻松掌握的远程群晖NAS方法&#xff0…

算法的时间复杂度和空间复杂度

文章目录算法的时间复杂度和空间复杂度算法效率算法的复杂度时间复杂度时间复杂度的概念大O的渐进表示法常见的时间复杂度计算举例空间复杂度常见复杂度对比复杂度的oj练习算法的时间复杂度和空间复杂度 算法效率时间复杂度空间复杂度常见的时间复杂度以及复杂度的oj练习 算法…

【题解】方格取数

&#x1f60a;博主目前也在学习&#xff0c;有错误欢迎指正&#x1f60a; &#x1f308;保持热爱 奔赴星海&#x1f308; 文章目录一、题目1、题目描述3、原题链接二、解题报告1、思路分析2、代码详解三、本题知识一、题目 1、题目描述 输入格式&#xff1a; 输入的第一行为一…

Java并发编程实战之互斥锁

文章目录Java并发编程实战之互斥锁如何解决原子性问题&#xff1f;锁模型Java synchronized 关键字Java synchronized 关键字 只能解决原子性问题&#xff1f;如何正确使用Java synchronized 关键字&#xff1f;锁和受保护资源的合理关联关系死锁预防死锁破坏占有且等待条件破坏…

字节一面:TCP 三次握手,问的好细!

大家好&#xff0c;我是小林。 有位读者在面试字节时&#xff0c;被问到这么个问题&#xff1a; 概括起来&#xff0c;是这两个问题&#xff1a; TCP 三次握手中&#xff0c;客户端收到的第二次握手中 ack 确认号不是自己期望的&#xff0c;会发生什么&#xff1f;是直接丢弃…

1024程序员节:从关注自身健康开始

今天是1024程序员节&#xff0c;我们已经历经了尽三年的疫情&#xff0c;健康是我们最应该关注的事情&#xff0c;在这个特别的日子里&#xff0c;希望程序员们都能更加爱惜自己的身体&#xff0c;少加班&#xff0c;多锻炼。 健身不仅是保持健康体魄的关键要素之一&#xff0c…

基于ssm高校科研管理系统-计算机毕业设计源码+LW文档

【摘 要】高校科研管理是一项重要而又繁琐的工作&#xff0c;有效的信息管理平台可以大大缓解科研管理压力&#xff0c;减少工作量。本文以石河子大学信息科学与技术学院为应用背景&#xff0c;开发教师教学信息与论文信息交流平台。该系统能对科研成果和课题进行较为全面的管理…

第十三届蓝桥杯C++B组国赛I题——齿轮 (AC)

目录1.齿轮1.题目描述2.输入格式3.输出格式4.样例输入5.样例输出6.样例说明6.数据范围7.原题链接2.解题思路3.Ac_code1.齿轮 1.题目描述 这天, 小明在组装齿轮。 他一共有 nnn 个齿轮, 第 iii 个齿轮的半径为 rir_{i}ri​, 他需要把这 nnn 个齿轮按一定 顺序从左到右组装起来…

[附源码]Java计算机毕业设计SSM公司办公自动化系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

10个实用的CSS样式之悬浮卡片

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位喜欢写作&#xff0c;计科专业大三菜鸟 &#x1f3e1;个人主页&#xff1a;starry陆离 &#x1f4da;订阅专栏&#xff1a;『10个实用的CSS样式』 10个实用的CSS样式之悬浮卡片1.简介2.布局设计3.样式美化3.1body美化3.2c…

隔离技术之端口隔离

端口隔离技术 端口隔离主要应用在同一个vlan内&#xff0c;不同的用户之间不可互相访问 好处&#xff1a; 可以避免广播风暴&#xff0c;节约了vlan的资源&#xff0c;提高了用户之间的安全性 比如一个用户的电脑中病毒了&#xff0c;不会影响到其他用户 端口隔离是基于端口&…

网络原理——No.2 传输层_TCP的连接管理(画图理解三次握手与四次挥手)

JavaEE传送门JavaEE 网络原理——传输层_UDP 网络原理——No.1 传输层_TCP的确认应答机制与超时重传 目录TCP的连接管理三次握手(建立连接)四次挥手(断开连接)TCP的连接管理 描述的就是 TCP 建立链接和断开链接的过程 TCP 的链接, 只是一个 “逻辑上的” “虚拟的连接” (只要…