Java进阶13讲__补充1/2

news2024/11/25 13:29:37

单元测试、反射、注解、Lombok

1.  单元测试

1.1  Junit单元测试框架

1.2  Junit框架入门

package com.itheima.a_单元测试;

import org.junit.Test;

public class SpringUtilTest {
    @Test
    public void testPrintNumber() {
        StringUtil.printNumber("Jack");
        StringUtil.printNumber("张三");
        StringUtil.printNumber("");
        StringUtil.printNumber(null);
    }
}

1.3  Junit框架的常见注解

package com.itheima.a_单元测试;

import org.junit.*;

public class SpringUtilTest {
    @Before
    public void init() {
        System.out.println("===init===");
    }

    @After
    public void destroy() {
        System.out.println("===destroy===");
    }

    @BeforeClass
    public static void initClass() {
        System.out.println("===initClass===");
    }

    @AfterClass
    public static void destroyClass() {
        System.out.println("===destroyClass===");
    }

    @Test
    public void testPrintNumber() {
        StringUtil.printNumber("Jack");
        StringUtil.printNumber("张三");
        StringUtil.printNumber("");
    }

    @Test
    public void testGetMaxIndex() {
        StringUtil su = new StringUtil();
        int i = su.getMaxIndex("我是孙庆的爹");
        System.out.println("i:" + i);
    }
}

1.4  Junit框架断言

package com.itheima.a_单元测试;

import org.junit.Assert;
import org.junit.Test;

public class SpringUtilTest {

    @Test
    public void testGetMaxIndex() {
        StringUtil su = new StringUtil();
        int i0 = su.getMaxIndex("我是孙庆的爹");
        Assert.assertEquals("NotEquals", 5, i0);
    }
}

2.  反射

2.1  认识反射、获取类 

package com.itheima.b_反射;

/*
反射的第一步是什么
    获取Class类对象,如此才可以解析类的全部成分

获取Class对象的三种方式
    1. 直接使用类名.class获取:Class c1 = 类名.class
    2. 调用Class提供的方法:Class c2 = Class.forName("全类名")
    3. 调用Object提供的方法:Class c3 = 对象.getClass()
*/
public class Demo1 {
    public static void main(String[] args) throws Exception {
        Class c1 = Cat.class;
        System.out.println(c1.getName());
        Class c2 = Class.forName("com.itheima.b_反射.Cat");
        System.out.println(c2.getName());
        Class c3 = new Cat().getClass();
        System.out.println(c3.getName());
    }
}

2.2  获取类的构造器

有Declared的方法是拿所有的,没有Declared修饰的是拿公共的(public)

package com.itheima.b_反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;

/*
获取构造器[下面是Class的方法]
    Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
    Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
    Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)

使用构造器(创建对象)[下面是Constructor的方法]
    T newInstance(Object... initArgs)	调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)
*/
public class Demo2 {
    public static void main(String[] args) throws Exception {
        Class myClass = new Cat().getClass();
//        Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
        Constructor[] constructors = myClass.getConstructors();
//        Arrays.stream(constructors).forEach(System.out::println);
//        System.out.println();

//        Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
        Constructor[] declaredConstructors = myClass.getDeclaredConstructors();
//        Arrays.stream(declaredConstructors).forEach(System.out::println);
//        System.out.println();

//        Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
        Constructor<Cat> constructor = myClass.getConstructor();
        Constructor<Cat> constructor1 = myClass.getConstructor(String.class);
//        Constructor<Cat> constructor2 = myClass.getConstructor(String.class, int.class);
//        System.out.println(constructor);
//        System.out.println(constructor1);
//        System.out.println(constructor2);
//        System.out.println();

//        Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)
        Constructor<Cat> declaredConstructor = myClass.getDeclaredConstructor(String.class, int.class);
//        System.out.println(declaredConstructor);

//          使用公告构造器创建对象
        Cat cat = constructor.newInstance();
        System.out.println(cat);
//          使用私有构造器创建对象
        declaredConstructor.setAccessible(true);//暴力反射
        Cat cat1 = declaredConstructor.newInstance("招财猫", 21);
        System.out.println(cat1);
    }

}

2.3  获取类的成员变量

package com.itheima.b_反射;

import java.lang.reflect.Field;
import java.util.Arrays;

/*
获取成员变量[Class提供]
    public Field[] getFields()	获取类的所有公共成员变量(只能获取public修饰的)
    public Field[] getDeclaredFields()	获取类的全部成员变量(只要存在就能拿到)
    public Field getField(String name)	获取类的某个公共成员变量(只能获取public修饰的)
    public Field getDeclaredField(String name)	获取类的某个成员变量(只要存在就能拿到)

使用成员变量(赋值和取值) [Field提供]
    public void set(Object obj, Object value): 赋值
    public Object get(Object obj):	取值
    public void  setAccessible(boolean flag):	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的变量,需要暴力反射
*/
public class Demo3 {
    public static void main(String[] args) throws Exception {
        Cat cat = new Cat();
        Class<? extends Cat> catClass = cat.getClass();
//    public Field getDeclaredField(String name)	获取类的某个成员变量(只要存在就能拿到)
        Field name = catClass.getDeclaredField("name");
        Field country = catClass.getDeclaredField("COUNTRY");
        Field age = catClass.getDeclaredField("age");
        //获取成员变量[Class提供]
        //    public Field[] getFields()	获取类的所有公共成员变量(只能获取public修饰的)
//        Field[] fields = catClass.getFields();
//        Arrays.stream(fields).forEach(System.out::println);
//        System.out.println();

        //    public Field[] getDeclaredFields()	获取类的全部成员变量(只要存在就能拿到)
//        Field[] declaredFields = catClass.getDeclaredFields();
//        Arrays.stream(declaredFields).forEach(item-> System.out.println(item.getName()+"类型:"+item.getType()));
        //    public Field getField(String name)	获取类的某个公共成员变量(只能获取public修饰的)
//        Field name = catClass.getField("name");
//        System.out.println(name);

        //使用成员变量(赋值和取值) [Field提供]
        System.out.println("======");
        System.out.println(name.getName());
        System.out.println(age.getName());
        System.out.println("======");
        System.out.println(cat);
        //    public void set(Object obj, Object value): 赋值
        String countryStr = (String) country.get(country);
        System.out.println(countryStr);
        //    public void  setAccessible(boolean flag):	设置为true,表示禁止检查访问控制(暴力反射)
        name.setAccessible(true);
        age.setAccessible(true);

        name.set(cat, "孙庆");
        age.set(cat, 21);
        System.out.println(cat);
        //    public Object get(Object obj):	取值
        String catName = (String) name.get(cat);
        System.out.println(catName);
        int catAge = (int) age.get(cat);
        System.out.println(catAge);
        System.out.println("======");
    }

}

2.4  获取类的成员方法

package com.itheima.b_反射;

import java.lang.reflect.Method;
import java.util.Arrays;

/*
获取成员方法[Class提供]
    Method[] getMethods()	获取类的全部公共成员方法(只能获取public修饰的)
    Method[] getDeclaredMethods()	获取类的全部成员方法(只要存在就能拿到)
    Method getMethod(String name, Class<?>... parameterTypes) 	获取类的某个公共成员方法(只能获取public修饰的)
    Method getDeclaredMethod(String name, Class<?>... parameterTypes)	获取类的某个成员方法(只要存在就能拿到)

使用成员方法(执行方法)[Method提供]
    public Object invoke(Object obj, Object... args)	触发某个对象的该方法执行。
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的成员方法,需要暴力反射
*/
public class Demo4 {
    public static void main(String[] args) throws Exception {
        Cat cat = new Cat();
        Class<? extends Cat> catClass = cat.getClass();
        //获取成员方法[Class提供]
        //Method[] getMethods()	获取类的全部公共成员方法(只能获取public修饰的)
//        Method[] methods = catClass.getMethods();
        //Method[] getDeclaredMethods()	获取类的全部成员方法(只要存在就能拿到)
        System.out.println("================");
        Method[] methodsArr = catClass.getDeclaredMethods();
        //        Arrays.stream(methods).forEach(item -> {
//            System.out.println("方法名字:" + item.getName() + ",返回值类型:" + item.getReturnType() + ",参数个数:" + item.getParameterCount());
//        });
        //Method getMethod(String name, Class<?>... parameterTypes) 	获取类的某个公共成员方法(只能获取public修饰的)
//        Method method = catClass.getMethod(cat.getName());
//        System.out.println(method);
        //Method getDeclaredMethod(String name, Class<?>... parameterTypes)	获取类的某个成员方法(只要存在就能拿到)
        Method eat = catClass.getDeclaredMethod("eat", String.class);
        System.out.println(eat.getReturnType());
        System.out.println(Arrays.toString(eat.getParameterTypes()));
        //使用成员方法(执行方法)[Method提供]
        //public Object invoke(Object obj, Object... args)	触发某个对象的该方法执行。
        //public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)
        eat.setAccessible(true);
        System.out.println(eat.invoke(cat, "鱼"));

    }
}

2.5  作用、应用场景

2.6  案例

package com.itheima.b_反射;

import java.lang.reflect.Field;
import java.util.Arrays;

/*
反射案例
    对于任意一个对象,该框架都可以把对象的字段名和对应的值,然后打印在控制台

*/
public class Demo5 {
    public static void main(String[] args) {
        //1. 准备两个对象
        Student student = new Student("柳岩", 40, '女', 167.5, "女星");
        Teacher teacher = new Teacher("播妞", 6000);
        //2.调用方法
        printInfo(student);
        printInfo(teacher);
    }

    public static void printInfo(Object o) {
        Class<?> obj = o.getClass();
        Field[] list = obj.getDeclaredFields();
        System.out.println("======" + obj.getSimpleName() + "======");
        Arrays.stream(list).forEach(item -> {
            try {
                item.setAccessible(true);
                System.out.println(item.getName() + "=" + item.get(o));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}

class Student {
    public Student(String name, int age, char sex, double height, String hobby) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.hobby = hobby;
    }

    private String name;
    private int age;
    private char sex;
    private double height;
    private String hobby;
}

class Teacher {
    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    private String name;
    private double salary;
}

3.  注解

3.1  快速入门

package com.itheima.c_annotation.example;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassNameCheck {
    public String[] author() default "佚名";

    public String value();
}

3.2  注解解析

3.3  注解属性

package com.itheima.c_annotation.example;

import com.itheima.c_annotation.ClassUtil;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class checkClassName {
    public static void isRight() throws Exception {
        StringBuilder sb = new StringBuilder();
        //拿集合
        Set<Class> classSet = ClassUtil.getClasses("com.itheima.c_annotation.example");
        //遍历
        System.out.println("------------");
        List<Class> list = classSet.stream()
                .filter(e -> e.isAnnotationPresent(ClassNameCheck.class))
                .filter(e -> !e.getSimpleName().startsWith("Heima"))
                .collect(Collectors.toList());
        if (list.size() != 0) {
            list.stream().forEach(e -> {
                ClassNameCheck annotation = (ClassNameCheck) e.getDeclaredAnnotation(ClassNameCheck.class);
                System.out.print(e.getSimpleName() + "作者:");
                Arrays.stream(annotation.author()).forEach(System.out::print);
                System.out.println(",作用:" + annotation.value());
            });
            throw new Exception("类名不规范");
        }
        System.out.println("------------");
    }
}

获取某个包下所有的类 

package com.itheima.c_annotation;


import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileFilter;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import static cn.hutool.core.util.ClassUtil.getClassLoader;
public class ClassUtil {
    private ClassUtil() {
    }


    /**
     * 获取某个包下的所有类
     */
    public static Set<Class> getClasses(String packageName) {
        try {
            Set<Class> classSet = new HashSet<>();
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replace(".", "/"));
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (url != null) {
                    String protocol = url.getProtocol();
                    if (protocol.equals("file")) {
                        String packagePath = url.getPath().replaceAll("%20", " ");
                        addClass(classSet, packagePath, packageName);
                    } else if (protocol.equals("jar")) {
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        if (jarURLConnection != null) {
                            JarFile jarFile = jarURLConnection.getJarFile();
                            if (jarFile != null) {
                                Enumeration<JarEntry> jarEntries = jarFile.entries();
                                while (jarEntries.hasMoreElements()) {
                                    JarEntry jarEntry = jarEntries.nextElement();
                                    String jarEntryName = jarEntry.getName();
                                    if (jarEntryName.endsWith(".class")) {
                                        String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
                                        doAddClass(classSet, className);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return classSet;
        } catch (Exception e) {
            throw new RuntimeException("包名错误");
        }


    }

    private static void addClass(Set<Class> classSet, String packagePath, String packageName) {
        File[] files = new File(packagePath).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
            }
        });
        for (File file : files) {
            String fileName = file.getName();
            if (file.isFile()) {
                String className = fileName.substring(0, fileName.lastIndexOf("."));
                if (StringUtils.isNotEmpty(packageName)) {
                    className = packageName + "." + className;
                }
                doAddClass(classSet, className);
            } else {
                String subPackagePath = fileName;
                if (StringUtils.isNotEmpty(packagePath)) {
                    subPackagePath = packagePath + "/" + subPackagePath;
                }
                String subPackageName = fileName;
                if (StringUtils.isNotEmpty(packageName)) {
                    subPackageName = packageName + "." + subPackageName;
                }
                addClass(classSet, subPackagePath, subPackageName);
            }
        }
    }

    /**
     * 加载类
     */
    private static Class loadClass(String className, boolean isInitialized) {
        Class cls;
        try {
            cls = Class.forName(className, isInitialized, getClassLoader());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return cls;
    }

    /**
     * 加载类(默认将初始化类)
     */
    private static Class loadClass(String className) {
        return loadClass(className, true);
    }

    private static void doAddClass(Set<Class> classSet, String className) {
        Class cls = loadClass(className, false);
        classSet.add(cls);
    }
}

4.  Lombok

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

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

相关文章

go 笔记

数据结构与 方法&#xff08;增删改查&#xff09; 安装goland,注意版本是2024.1.1&#xff0c;不是2024.2.1&#xff0c;软件下载地址也在链接中提供了 ‘go’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 在 Windows 搜索栏中输入“环境变量”&#…

Windows上安装RabbitMQ

rabbitmq是干嘛的我就不介绍了&#xff0c;直接开始安装教程。 搭建成功演示图 下载安装包 https://pan.baidu.com/s/1ZlCFxh9Q00ynSU3ZCpTC9Q?pwdry51​pan.baidu.com/s/1ZlCFxh9Q00ynSU3ZCpTC9Q?pwdry51 下载完后有两个包(erlang和rabbitmq) 先安装otp_win64_24.1.7.exe…

【Python系列】理解 Python 中的时间和日期处理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

测试开发基础——测试分类

四、测试分类 1. 按照测试目标分类 1.1. 界面测试 肉眼看到的任何元素都需要进行测试 界面测试&#xff08;简称U测试&#xff09;&#xff0c;指按照界面的需求&#xff08;一般是U设计稿&#xff09;和界面的设计规则&#xff0c;对我们软件界面所展示的全部内容进行测试…

【计算机网络】UDP 协议详解及其网络编程应用

文章目录 一、引言二、UDP1、UDP的协议格式2、UDP 报文的解包和分用3、UDP面向数据报的特点 三、UDP输入输出四、UDP网络编程 一、引言 UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;是一种网络通信协议&#xff0c;它属于传输层的协议。是一…

火语言RPA流程组件介绍--鼠标拖拽元素

&#x1f6a9;【组件功能】&#xff1a;在开始位置上按下鼠标&#xff0c;拖动到结束坐标或指定元素上放下鼠标&#xff0c;实现目标元素的拖拽 配置预览 配置说明 丨拖动元素 支持T或# 默认FLOW输入项 开始拖动的元素,并从当前元素开始按下鼠标 丨拖动到 目标元素/目标位…

vue3 el-message组件封装

背景 在封装请求拦截器时,使用ElMessage进行弹窗提示成功或失败,但是如果页面用到多个接口,这时就会导致页面出现很多弹窗,导致用户体验不好,有可能出现卡顿现象。 这时就需要进行一些判断,如果前面的ElMessage还没关闭并且类型是一致的就return,不再弹窗提示,类型不…

项目日志——日志器模块一部缓冲区的设计、实现、测试

文章目录 异步缓冲区模块模块设计缓冲区设计单个缓冲区 实现测试 异步缓冲区模块 模块设计 异步日志器的思想是为了避免业务线程因为写日志的过程时间较长而长时间阻塞 异步日志器的工作就是把业务输出的日志内容放入内存缓冲区中&#xff0c;使用专门的线程进行日志写入 这…

一款高效、简洁的帧动画生成工具

在现代网页设计和移动应用开发中&#xff0c;帧动画是一种常见的动画实现方式&#xff0c;它通过连续显示一系列静态图片来模拟动画效果。然而&#xff0c;手动创建和管理这些帧动画图片不仅耗时费力&#xff0c;而且效率低下。为此&#xff0c;gka 应运而生&#xff0c;它是一…

翻车率这么高!今年11月软考论文应该如何备考?

随着最近2024年5月软考成绩的出炉&#xff0c;大家发现论文及格绝大多数都是45分&#xff0c;有许多高级考生三科中只有论文不合格&#xff0c;与软考证书失之交臂。而下半年除高项&#xff0c;其他4个高级科目都将开考&#xff0c;那么高级中至关重要的论文科目该如何备考呢&a…

AI应用开发平台Dify本地Ubuntu环境部署结合内网穿透远程管理大模型

文章目录 前言1. Docker部署Dify2. 本地访问Dify3. Ubuntu安装Cpolar4. 配置公网地址5. 远程访问6. 固定Cpolar公网地址7. 固定地址访问 前言 本文主要介绍如何在Linux Ubuntu系统使用Docker快速部署大语言模型应用开发平台Dify,并结合cpolar内网穿透工具实现公网环境远程访问…

微信小程序:wx.login或调用uni.login时报错the code is a mock one

微信小程序&#xff0c;调用wx.login或调用uni.login方法&#xff0c;返回the code is a mock one 原因与解决 原因:没有关联真实的 appid&#xff0c;解决办法&#xff1a;绑定真实的微信小程序的appid

OpenCV结构分析与形状描述符(9)检测轮廓相对于其凸包的凹陷缺陷函数convexityDefects()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 查找一个轮廓的凸性缺陷。 下图显示了一个手部轮廓的凸性缺陷&#xff1a; convexityDefects 是 OpenCV 库中的一个函数&#xff0c;用于检测轮…

文件压缩项目(基于Huffman编码)

目录 文件压缩压缩本质huffman树huffman树的构建Huffman编码的压缩过程获取Huffman编码构建压缩信息 Huffman编码的解压缩过程解压压缩的数据 写压缩函数的注意事项文件指针移动到头 测试过程对文本文件进行压缩纯英文文本测试中文文本测试中英文文本测试 对图片进行压缩解压缩…

第 1 课 编程是一门技术 ——认识Dev-C++

1.什么是编程&#xff1f; 软件由程序和文档组成&#xff0c;每个程序都是由一条条计算机能够识别和执行的指令组成的&#xff0c;每一天指令指挥计算机完成指定的操作。编写程序又称编程&#xff0c;他是一门技术。通俗地讲&#xff0c;编程就是告诉计算机&#xff0c;你要帮我…

合成控制法SCM

研究D的处理效应&#xff0c;找一个相似的样本&#xff0c;他们的差异就是处理效应。但&#xff1a;难点就在如何找到相似的样本。那么就通过合成法来合成一个虚拟的重庆。 案例&#xff1a;美国加州香烟法案出台 依靠权重来合成一个新的y 假设我们不用SCM&#xff0c;直接靠着…

文心快码前端工程师观点分享:人机协同关系总结与展望

&#x1f381;&#x1f449;点击进入文心快码 Baidu Comate 官网&#xff0c;体验智能编码之旅&#xff0c;还有超多福利&#xff01;&#x1f381; 本系列视频来自百度工程效能部的前端研发经理杨经纬&#xff0c;她在由开源中国主办的“AI编程革新研发效能”OSC源创会杭州站1…

CloudberryDB 内核分享:Directory Table 底层逻辑与实现原理讲解

在之前的直播中&#xff0c;我们向大家介绍了&#x1f517;&#xff0c;为企业AI应用创新提供更高质量的非结构化数据语料输入和知识库支持&#xff0c;感兴趣的朋友可以点击链接阅读。 随着我们的开源数据仓库产品Cloudberry Database&#xff08;简称“CloudberryDB”&#…

杂七杂八-系统环境安装

杂七杂八-系统&环境安装 1. 系统安装2.环境安装 仅个人笔记使用&#xff0c;感谢点赞关注 1. 系统安装 Windows安装linux子系统WSL2&#xff1a;使用windows系统跑linux程序(大模型) 2.环境安装 目前仅专注于 NLP 大模型 机器学习和前后端的技术学习和分享 感谢大家的关注…

基于spring的博客系统(总)

通过前⾯课程的学习, 我们掌握了Spring框架和MyBatis的基本使⽤, 并完成了图书管理系统的常规功能 开发, 接下来我们系统的从0到1完成⼀个项⽬的开发&#xff1b; 1. 项⽬介绍 使⽤SSM框架实现⼀个简单的博客系统 共5个⻚⾯ 1. 用户登录 2. 博客发表⻚ 3. 博客编辑⻚ 4. 博客…