Java——springboot web案例

一、spring boot初始化

这些文件是借助 Spring Initializr 初始化项目时,官方自动生成的脚手架配套内容,用于适配 Maven、Git 版本管理等通用开发场景;其中一部分是刚需文件,一部分属于可选文件。

一、文件夹类

  1. .mvn
  • 作用:存放 Maven Wrapper 的配套配置。Maven Wrapper(也就是下文的mvnw)可以让项目自带一套 Maven 版本,即便你的电脑本地没有安装 Maven、或者本地 Maven 版本不一致,其他人拿到项目也能依靠项目内置的 Maven 完成构建,规避本地环境差异引发的报错。
  • 删除建议:可选删除。如果你本机已经配置好了适配的 Maven 环境,日常只会使用本地 Maven 进行构建,这个文件夹就可以删掉;团队成员本地 Maven 环境参差不齐的话,建议保留。
  1. src
  • 作用:项目代码主目录,是绝对不能删除 的核心目录
    • src/main/java:存放 Java 业务代码、Controller、实体类等;
    • src/main/resources:存放配置文件、静态资源;
    • src/test/java:单元测试代码。

二、Git 相关文件

  1. .gitattributes
  • 作用:Git 的配置文件,用来规范不同操作系统的换行符格式(Windows、Mac 换行标准不一样),避免跨系统提交代码出现大量无意义的换行改动,也可以设置不同文件的差异化处理规则。
  • 删除建议:可选删除。如果你的项目压根不打算使用 Git 做版本控制,可以删掉;后续要用 Git 管理代码就建议保留。
  1. .gitignore
  • 作用:告诉 Git 哪些文件、文件夹不需要提交到代码仓库,典型过滤对象:.idea(IDEA 专属配置)、编译产出 target 文件夹、本地配置、系统缓存文件等,避免 IDE 个性化配置、编译垃圾文件上传远程仓库。
  • 删除建议:推荐保留,只有彻底不用 Git 的时候才删。

三、文档文件

  1. HELP.md
  • 作用:初始化自动生成的说明文档,里面记录 Spring Boot 入门帮助、常用参考链接,仅起到新手引导作用,运行项目完全不会读取这个文件。
  • 删除建议:可以放心删除,绝大多数开发者建好项目之后就会删掉它,日常开发不会用到。

四、Maven Wrapper 脚本

  1. mvnw(Linux/Mac 系统执行脚本)、mvnw.cmd(Windows 系统执行脚本)
  • 作用:二者是 Maven Wrapper 的启动脚本:
    • mvnw适配 macOS、Linux;
    • mvnw.cmd适配 Windows; 运行这两个脚本就会调用.mvn目录内置的 Maven 来打包、编译项目。
  • 删除建议:跟随.mvn一同取舍,本地自备 Maven 就可以一起删掉。

五、最核心不可删文件

  1. pom.xml
  • 作用:Maven 的核心配置文件,所有 Maven 依赖、插件、项目构建规则全部写在这里,之前配置的 web、lombok 等依赖都存放于此。
  • 删除建议:严禁删除,删掉之后 Maven 就失去了项目依赖管理的能力,项目无法正常构建。

二、代码讲解

java 复制代码
private Integer id;

选用Integer而非int的原因

1.先理清二者基础区别

(1)int是 Java 的基本数据类型,属于原生类型,默认初始值固定是0;

(2)Integer是int对应的包装类,属于引用类型,它可以赋值为null。

2.业务场景下选择 Integer 的核心理由(后端开发主流习惯):可以表达「字段不存在 / 数据库值为空」的情况(最关键)

数据库表里面的 id 字段允许设置NULL。

如果使用int id:数据库 id 为空时,Java 强制把初始值填充成0,你无法区分两种截然不同的业务情况:

① 用户真实 id 就是 0;② 数据库压根没有填入 id(空缺),会产生数据歧义;

如果使用Integer id:数据库为空时实体的 id 就接收null,可以精准识别出字段是空的状态,不会出现歧义。

java 复制代码
private LocalDateTime time;
1. LocalDate

只保存年月日 ,例如 2025-11-20,不包含小时、分钟、秒这些时分秒细节。 适用场景:生日、入职日期、下单日期(只需要记录哪一天即可)。

2. LocalTime

只保存时分秒 ,例如 14:32:50,没有年、月、日信息。 适用场景:门店早晚上下班时刻、每日固定打卡时点。

3. LocalDateTime(正是代码要选用的)

二者进行组合,同时拥有年月日 + 时分秒,形如 2024-07-16 11:03:28,和你 txt 文件里2024-07-16 11:03:28这种完整时间格式完美匹配。

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor

1. @Data(综合型注解,日常最常用)

它相当于批量一次性整合了好几类常用代码:

  1. 自动生成所有成员字段的gettersetter方法;
  2. 重写toString(),打印实体对象时能够输出所有字段的取值,调试查看数据很便捷;
  3. 重写equals()hashCode(),方便完成两个实体对象之间的相等判断;
  4. 还会生成字段对应的 canGet/canSet 布尔方法适配部分框架。

适用场景:绝大多数普通实体类(比如你正在编写的 User 实体),打上这一个注解就省去手写一大堆 get、set、toString 代码的工作量。

2. @NoArgsConstructor:生成无参构造方法

  • 作用:自动创建没有任何入参的构造函数:public User(){}
  • 刚需原因:大量框架强制实体配备无参构造: ① MyBatis 从数据库查询封装实体、Spring 做反射实例化对象时,底层默认调用无参构造; ② JSON 序列化 / 反序列化(Jackson 等工具)解析前端 JSON 数据转为 Java 实体,同样离不开无参构造; 如果只写了全参构造,默认的无参构造会被 Java 自动抹除,运行阶段就容易抛出实例化报错。

3. @AllArgsConstructor:生成全参构造方法

  • 作用:自动创建包含实体全部成员属性 的构造方法,可以一次性传入所有字段完成对象初始化 示例:你的 User 实体拥有 id、username、password、name、age、updateTime 一共 6 个字段,注解就自动生成接收这 6 个参数的构造器,写代码时可以直接new User(参数1,参数2......)快速完成对象创建,适配你之前读取 txt、批量 new User 封装数据的写法。
java 复制代码
@RestController

@RestController详细讲解

1. 本质来源

@RestController是 Spring MVC 提供的复合注解,等价于 @Controller + @ResponseBody 两个注解合并的效果,后端 Web 开发日常高频使用。

2. 拆分两层理解作用
(1)具备@Controller的能力:把类注册成控制器

Spring 扫描该注解之后,会将这个类纳入 Spring 容器进行管理,专门用来接收前端发来的 HTTP 请求,类内部可以编写各类接口方法(也就是 Controller 层),承接浏览器、前端页面、Postman 发出的请求。

(2)具备@ResponseBody的能力:返回 JSON 格式数据

这是它和普通@Controller最关键的区别:

  • 单用@Controller的时候,方法返回字符串会被 Spring 当成网页视图名称,会尝试跳转对应的 html 页面;
  • 叠加了@ResponseBody之后,方法返回的对象、集合会自动借助 Jackson 序列化为JSON 字符串,直接把 JSON 响应给到前端,不会进行页面跳转,前后端分离开发基本都需要这种效果。
java 复制代码
@RestController
public class UserController {
    @RequestMapping("/list")
    public List<user> list() throws Exception{
        //1.加载并读取user.txt文件,获取用户数据
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
        ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8,new ArrayList<>());
        //2.遍历lines集合,解析用户信息,封装为user对象 -> list集合
        List<user> userList = lines.stream().map(line -> {
            String[] parts = line.split(",");
            Integer id = Integer.parseInt(parts[0]);
            String username = parts[1];
            String password = parts[2];
            String name = parts[3];
            Integer age = Integer.parseInt(parts[4]);
            LocalDateTime updataTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            return new user(id,username,password,name,age,updataTime);
        }).toList();
        //3.返回json格式数据
        return userList;
    }

}

浏览器访问 http://localhost:8080/list,程序读取 resources/user.txt 文本文件,把文件里每一行用户文字,转成 user 实体对象,打包成列表返回给前端网页展示。

第 1 行:@RestController

  1. 这是 SpringBoot 的注解,相当于给这个类贴标签。
  2. 作用:
    • 告诉 Spring:这个类是接口控制器,专门用来接收浏览器的网络请求;
    • Rest 代表:方法返回集合 / 对象时,自动转换成 JSON 字符串给前端,不用我们手动转字符串。
  3. 对比基础语法:注解是框架专属标记,没有对应的基础 Java 语法,记住固定作用即可。

第 2 行:public class UserController {

  1. public:公共访问权限,Spring 框架能随便调用这个类;
  2. class UserController:我们新建的类,专门放用户相关接口代码;
  3. {}:类的代码范围,所有写接口的代码都放这里面。

第 3 行:@RequestMapping("/list")

  1. 又是注解,绑定网址 /list 和下面这个 list() 方法;
  2. 大白话:只要浏览器地址末尾是 /list,Spring 就自动执行下面的 list 函数。

第 4 行:public List<user> list() throws Exception{

拆成 5 小块,全是你学过的基础语法:

  1. public:公共方法,Spring 能调用;
  2. List<user>:方法返回值类型,代表最后要返回一个装着 user 对象的动态数组集合(就是你学的 ArrayList 父接口,长度自动变长);
  3. list():方法名字,空括号 = 调用这个方法不用传任何参数;
  4. throws Exception:抛出所有异常
    • 读取文件、转数字、解析日期都可能出错(文件找不到、文字转数字失败、日期格式不对);
    • 初学简化写法:告诉系统 "所有出错我暂时不写 if 判断捕获,出错直接交给服务器处理",不用写一堆 try-catch;
  5. {}:方法内部代码全部写在大括号里。

第 5 行:InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");

分步拆开,比喻讲解

  1. InputStream in
    • InputStream:Java 自带字节读取管道,相当于一根吸管,用来吸文件里的文字;
    • in:自定义变量名,后面代码用in代表这根吸管。
  2. this:代表当前 UserController 这个类运行出来的对象;
  3. .getClass():拿到当前类的底层信息(类对象);
  4. .getClassLoader():类加载器,专门负责找到项目里resources文件夹下的文件;
  5. .getResourceAsStream("user.txt")
    • 参数是文件名,加载器找到这个 txt 文件,打开 "吸管" 读取文件,返回 InputStream 吸管对象;
  6. = 赋值:把打开文件后的吸管,存到变量 in 里,后面读文件全靠这个变量。

第 6 行:ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8,new ArrayList<>());

逐段拆解,用基础循环类比

  1. ArrayList<String> lines
    • ArrayList:你学过的动态数组集合;<String>约束集合里只能存字符串;
    • lines:变量名,用来存 txt 里每一行文字,一行就是一个 String。
  2. IoUtil.readLines(参数1,参数2,参数3)
    • IoUtil 是 Hutool 工具类,别人提前写好的工具方法,底层本质就是你熟悉的while循环一行一行读文件,帮你省去几十行重复代码; 参数 1 in:我们刚才打开的文件吸管,告诉工具读哪个文件; 参数 2 StandardCharsets.UTF_8:读取编码,防止中文乱码; 参数 3 new ArrayList<>():新建一个空集合,工具读完所有行后,自动把每行文字放进这个集合;
  3. =赋值:装满所有行文字的集合,存入变量lines

第 7 行:List<user> userList = lines.stream().map(line -> { ... }).toList();

逐段拆解原代码每一部分

  1. List<user> userList:定义集合,专门存放组装好的 user 对象;
  2. lines.stream():把集合 lines 转换成 "流",只是 Java 简化循环的写法,作用 = 开启循环遍历 lines 里每一个字符串;
  3. .map(参数):翻译:遍历循环里,对每一行 line 做统一转换(把字符串一行,转换成 user 对象);
  4. line -> { ... }:Lambda 表达式,相当于 for 循环里的循环体;
    • line:循环里临时变量,代表当前遍历到的单行文字,和 for (String line : lines) 里的 line 完全一样;
    • {}:转换逻辑,里面全是你能看懂的数组、类型转换语法;
  5. .toList():循环全部结束后,把所有转换好的 user 收集成一个新 List 集合,赋值给左边userList

大括号内部循环体逐行讲解

String[] parts = line.split(",");

String username = parts[1];

直接取出数组下标 1 的字符串,存用户名,基础数组取值。

String password = parts[2];

数组下标 2,取密码字符串。

String name = parts[3];

数组下标 3,取真实姓名。

Integer age = Integer.parseInt(parts[4]);

数组下标 4 的文字是 "20",转成数字年龄。

  • split(","):字符串分割方法,按逗号,把一行文字切成字符串数组;

  • 举例:一行文字1,zhangsan,123,张三,20,2024-07-15 15:05:45,分割后数组parts

    java 复制代码
    parts[0] = "1"
    parts[1] = "zhangsan"
    parts[2] = "123"
    parts[3] = "张三"
    parts[4] = "20"
    parts[5] = "2024-07-15 15:05:45"
  • String[] parts:字符串数组,你基础语法学过的数组。

Integer id = Integer.parseInt(parts[0]);

  • parts[0]是字符串 "1",不能直接存进数字变量;
  • Integer.parseInt():把数字字符串转换成整数,基础类型转换语法;
  • Integer id:数字变量,存用户编号。

LocalDateTime updataTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

parts[5]:数组最后一位,是日期字符串2024-07-15 15:05:45DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"):定义日期格式模板,告诉程序文字的年月日时分秒怎么排列;

  • yyyy4 位年份、MM两位月份、dd日期、HH24 小时制小时、mm分钟、ss秒;

LocalDateTime.parse(文字,模板):按照模板,把日期字符串转成 Java 日期对象,专门存时间; LocalDateTime updataTime:日期变量,存放解析完成的时间。

return new user(id,username,password,name,age,updataTime);

  1. new user(参数):创建 user 实体类对象,把刚才拆分好的 id、用户名、密码、姓名、年龄、时间全部传入;
  2. return:把新建好的 user 对象返回给 map 流,存入最终集合 userList; 对应 for 循环里 userList.add(u); 这一步。

倒数第二行:return userList;

方法结束,把装满 user 对象的集合返回出去;因为类上加了@RestController,Spring 自动把这个集合转换成 JSON 文本,浏览器就能拿到表格数据渲染页面。

相关推荐
从此以后自律1 小时前
Java Object 类常用方法全讲解
java·开发语言
XH华1 小时前
C++语言第二章类和对象(下)
开发语言·c++
你有我备注吗2 小时前
SQL学习之查询
java·sql·学习
从零开始的代码生活_2 小时前
C++ stack、queue 与 priority_queue:容器适配器原理与实战
开发语言·c++·后端·学习·算法
techdashen2 小时前
Go 1.25 新增 `reflect.TypeAssert`:更直接、更高效地从 `reflect.Value` 取出类型值
开发语言·后端·golang
2zcode2 小时前
项目文档:基于MATLAB低采样率ISAR成像的快速稀疏重建算法研究
开发语言·算法·matlab
xixi09242 小时前
JMeter5.6.3基础使用教程1
java·开发语言
带刺的坐椅2 小时前
用 Solon ReActAgent 落地发票识别与智能报销
java·llm·solon·react-agent
এ慕ོ冬℘゜2 小时前
原生 JS 实现自定义单选日历组件(无 UI 库、纯手写、禁用过去日期)
开发语言·javascript·ui