邪修实战系列(3)
1、第一阶段邪修实战总览(9.1-9.30)
把第一阶段(基础夯实期)的学习计划拆解成极具操作性的每日行动方案。这个计划充分利用我“在职学习”的特殊优势,强调“用输出倒逼输入”,确保每一分钟的学习都直接服务于面试和实战。
- 核心目标:构建起Java后端开发的知识树主干,并能通过一个小型项目串联起所有知识点。
- 核心策略:每天3小时雷打不动的高效学习(工作日可分散,周末集中攻坚)。
2、周目标(9.1-9.14)
Java核心+Sprig Boot破冰,能独立使用Spring搭建Web后端并提供RESTful接口。
3、分日目标与邪修技巧
3.1、Day 9-10: Spring Boot开发RESTful API
- 行动:设计/api/ads相关的接口(GET、POST),用@PostMapping接收前端传过来的JSON数据并解析。
- 邪修技巧:使用Postman软件测试自己写的接口,确保能通。这个过程和前端联调一模一样,这就是经验。
3.1.1、学习分享
接下来我会讲解一下我在学习这部分知识的时候编写与测试GET接口的详细步骤:
第一步:设计我们的数据模型
在编写接收数据的API之前,需要先定义数据长什么样。我们可以直接在我们7-8天测试的那个demo中进行修改。
- 创建实体类:在scr/main/java/com/adcampaign下新建一个entity包,并在该包下创建一个新的Java类,名为AdAdvertisement
- 编写类代码:
package com.adcampaign.entity;/*** 广告活动数据模型类* 用于存储广告活动的核心数据,并提供数据计算和分析功能* 每个实例代表一天的广告活动数据*/
public class AdAdvertisement {// 日期(例如:"2023-10-01")private String date;// 广告花费(单位:元)private double cost;// 线索提交个数(用户提交的潜在客户信息数量)private int leadCount;// 私信消息数(收到的用户私信数量)private int messageCount;/*** 构造方法:创建广告活动数据对象* @param date 日期字符串* @param cost 广告花费金额* @param leadCount 线索数量* @param messageCount 私信消息数量*/public AdAdvertisement(String date, double cost, int leadCount, int messageCount) {this.date = date;this.cost = cost;this.leadCount = leadCount;this.messageCount = messageCount;}// Getter方法:获取私有属性的值public String getDate() { return date; }public double getCost() { return cost; }public int getLeadCount() { return leadCount; }public int getMessageCount() { return messageCount; }// Setter方法:修改私有属性的值public void setDate(String date) { this.date = date; }public void setCost(double cost) { this.cost = cost; }public void setLeadCount(int leadCount) { this.leadCount = leadCount; }public void setMessageCount(int messageCount) { this.messageCount = messageCount; }/*** 计算单个线索成本* 公式:单个线索成本 = 广告花费 ÷ 线索数量* @return 单个线索成本(元/个),如果线索数量为0则返回0*/public double calculateCostPerLead() {// 防止除以零错误:如果线索数为0,返回0return (leadCount > 0) ? cost / leadCount : 0;}/*** 计算私信消息转化成本* 公式:私信转化成本 = 广告花费 ÷ 私信消息数* @return 私信转化成本(元/条),如果私信数为0则返回0*/public double calculateCostPerMessage() {// 防止除以零错误:如果私信数为0,返回0return (messageCount > 0) ? cost / messageCount : 0;}/*** 分析广告花费随日期的变动情况* @param previousCampaign 上一个日期的广告活动数据(用于比较)* @return 变动情况描述,包含变动金额和百分比*/public String analyzeCostChange(AdAdvertisement previousCampaign) {// 检查是否有历史数据可供比较if (previousCampaign == null) return "无历史数据可供比较";// 计算变动金额:当前花费 - 上一期花费double changeAmount = this.cost - previousCampaign.getCost();// 计算变动百分比:(变动金额 ÷ 上一期花费) × 100%double changeRate = (changeAmount / previousCampaign.getCost()) * 100;// 格式化输出:保留两位小数,显示变动金额和百分比return String.format("花费变动: %.2f元 (%.2f%%)", changeAmount, changeRate);}/*** 分析单个线索成本随日期的变动情况* @param previousCampaign 上一个日期的广告活动数据(用于比较)* @return 变动情况描述,包含变动金额和百分比*/public String analyzeCostPerLeadChange(AdAdvertisement previousCampaign) {if (previousCampaign == null) return "无历史数据可供比较";// 获取当前和上一期的单个线索成本(调用已有的计算方法)double currentCpl = this.calculateCostPerLead();double previousCpl = previousCampaign.calculateCostPerLead();// 防止除以零错误if (previousCpl <= 0) return "历史单个线索成本为0,无法计算变动率";double changeAmount = currentCpl - previousCpl;double changeRate = (changeAmount / previousCpl) * 100;return String.format("单个线索成本变动: %.2f元 (%.2f%%)", changeAmount, changeRate);}/*** 分析私信消息转化成本随日期的变动情况* @param previousCampaign 上一个日期的广告活动数据(用于比较)* @return 变动情况描述,包含变动金额和百分比*/public String analyzeMessageCostChange(AdAdvertisement previousCampaign) {if (previousCampaign == null) return "无历史数据可供比较";// 获取当前和上一期的私信转化成本(调用已有的计算方法)double currentCpm = this.calculateCostPerMessage();double previousCpm = previousCampaign.calculateCostPerMessage();// 防止除以零错误if (previousCpm <= 0) return "历史私信转化成本为0,无法计算变动率";double changeAmount = currentCpm - previousCpm;double changeRate = (changeAmount / previousCpm) * 100;return String.format("私信转化成本变动: %.2f元 (%.2f%%)", changeAmount, changeRate);}
}
(其实要是大家仔细研究过这个系列的前面,并且看了Data_Board-README文档的话,不难发现,其实这个类是直接复制的,仅仅只是改了名字而已)
第二步:升级控制器
现在我们需要改造我们Day7-8创建的控制器或者来创建一个更专业的控制器,我们这里直接来创建吧
- 创建控制器:在controller包下,创建AdController.java
- 编写Get接口(返回数据列表):
package com.adcampaign.controller;import com.adcampaign.entity.AdAdvertisement; // 导入刚刚创建的实体类
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;
import java.util.List;@RestController
@RequestMapping("/api/ads") // 所有这个控制器下的接口路径都以 /api/ads 开头
public class AdController {// 模拟一些静态数据private List<AdAdvertisement> adList = Arrays.asList(new AdAdvertisement("2025-9-28",5000,10,50),new AdAdvertisement("2025-9-29",6000,15,60));@GetMapping // 等价于 @GetMapping(""),访问路径是 /api/adspublic List<AdAdvertisement> getAllAds() {return adList; // Spring Boot会自动将这个List序列化为JSON返回}
}
第三步:编写启动类
启动类通常位于项目最顶级的包下,之前7-8天的测试自动生成了一个启动类,我们这里直接删除即可,接下来在src/main/java/com/adcampaign包下新建一个启动类叫Data_Board_Application.java
- 编写启动类代码:
package com.adcampaign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;// 核心注解:标记这是一个Spring Boot应用的主配置类
@SpringBootApplication
@RestController
public class Data_Board_Appliction {public static void main(String[] args) {SpringApplication.run(Data_Board_Appliction.class, args);}
}
- 测试GET接口
-
- 启动项目,运行启动类
Data_Board_Application.java
,然后在在终端窗口如果出现下面的样式则代表运行成功:
- 启动项目,运行启动类
-
- 打开浏览器,访问网址
http://localhost:8080/api/ads
,如果在浏览器中显示如图所示的两条包含广告数据的JSON数组,就证明成功了。
- 打开浏览器,访问网址
第四步:编写POST接口(接收数据)
这是最关键的一步,可以学会如何接收前端发送的JOSN数据。
- 在AdController中添加POST接口:
// 新增POST接口@PostMappingpublic String createAd(@RequestBody AdAdvertisement newAd) {// @RequestBody 注解告诉Spring:“请把请求体里的JSON数据,转换成一个AdAdvertisement对象”// 模拟处理:打印接收到数据System.out.println("接收到新的广告数据:");System.out.println("日期: " + newAd.getDate());System.out.println("广告花费: " + newAd.getCost());System.out.println("线索提交个数: " + newAd.getLeadCount());System.out.println("私信消息数: " + newAd.getMessageCount());// 这里暂时不做实际存储,只是返回成功消息return "广告数据创建成功! " + newAd.getDate();}
- AdController控制器的完整代码如下:
package com.adcampaign.controller;import com.adcampaign.entity.AdAdvertisement; // 导入刚刚创建的实体类
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;import java.util.Arrays;
import java.util.List;@RestController
@RequestMapping("/api/ads") // 所有这个控制器下的接口路径都以 /api/ads 开头
public class AdController {// 模拟一些静态数据private List<AdAdvertisement> adList = Arrays.asList(new AdAdvertisement("2025-9-28",5000,10,50),new AdAdvertisement("2025-9-29",6000,15,60));@GetMapping // 等价于 @GetMapping(""),访问路径是 /api/adspublic List<AdAdvertisement> getAllAds() {return adList; // Spring Boot会自动将这个List序列化为JSON返回}// 新增POST接口@PostMappingpublic String createAd(@RequestBody AdAdvertisement newAd) {// @RequestBody 注解告诉Spring:“请把请求体里的JSON数据,转换成一个AdAdvertisement对象”// 模拟处理:打印接收到数据System.out.println("接收到新的广告数据:");System.out.println("日期: " + newAd.getDate());System.out.println("广告花费: " + newAd.getCost());System.out.println("线索提交个数: " + newAd.getLeadCount());System.out.println("私信消息数: " + newAd.getMessageCount());// 这里暂时不做实际存储,只是返回成功消息return "广告数据创建成功! " + newAd.getDate();}
}
第五步:测试POST接口(使用Postman)
由于我们不能用浏览器地址栏测试POST请求,必须使用Postman或类似的API测试工具,所以需要我们来下载并安装一个Postman来进行测试。
- 大家可以跟着这篇文章来初步了解一下Postman,postman接口测试工具详解【全】,这篇文章中详细介绍了如何下载、安装与一些简单的使用。
- 创建一个新请求:
-
- 方法选择:POST
-
- URL输入:localhost:8080/api/ads
- 设置请求头:
-
- 点击Headers标签
-
- 添加一个Key:Content-Type,Value:application/json
- 设置请求体:
-
- 点击Body标签
-
- 选择raw和JOSN
-
- 在下方文本框中输入一段JOSN数据:
{"date": "2025-09-30","cost": 100.5,"leadCount": 5,"messageCount": 7
}
-
点击Send:
-
- 成功标志:下方响应去会看到
广告数据创建成功2025-9-30
- 成功标志:下方响应去会看到
-
- 同时,回头看我们的IDE控制台(运行Spring Boot)的窗口,应该能看到打印出的接收到的数据信息。
- 同时,回头看我们的IDE控制台(运行Spring Boot)的窗口,应该能看到打印出的接收到的数据信息。
-
这个项目的源码我放到了我的GitHub里,点击Data_Board_Spring_Boot链接直接学习和使用即可~
总结
@RequestBody是灵魂:
- 它完成了
HTTP请求体 -> Java对象
的魔法转换。这个过程叫“反序列化”,由Spring内置的Jackson库自动完成。只需要定义一个Java类,字段名能和JSON的key对上就行。
为什么要有无参构造器和Getter/Setter?
- Jackson库在创建对象和读取/设置属性时需要使用它们。没有他们,转换就会失败。这也是之前为什么要强调生成这些方法的原因。
Web开发经验
- 使用Spring Boot的@RestController开发过RESTful接口,包括处理GET和POST请求。并且我知道如何使用@RequestBody注解来接收前端发送的JSON格式参数,完成反序列化。
@SpringBootApplication
是一个组合注解,它包含了三个核心功能:
@SpringBootConfiguration
:标记该类为配置类@EnableAutoConfiguration
:开启自动配置,这是Spring Boot的魔法所在,它根据您引入的jar包依赖(如Spring-Web,MySQL Driver),自动配置应用程序锁需的组件(如Tomcat服务器、SpringMVC)。@ComponentScan
:自动扫描当前包及其子包下的组件(如@Controller,@Service,@RestController,@Component等),并注册为Spring Bean。
包路径的重要性
AdControlle控制器类
必须放在启动类
的同级或者子包下!例如,如果启动类在com.example.demo
包下,那么您的控制器最好放在com.example.demo.controller
包下。如果放在一个毫不相干的包路径下,@ComponentScan
将无法发现它,导致404错误。