Spring Boot项目快速创建-开发流程(笔记)

news2025/4/2 3:07:16

主要流程:

前端发送网络请求->controller->调用service->操纵mapper->操作数据库->对entity数据对象赋值->返回前端

前期准备:

maven、mysql下载好 

跟学视频,感谢老师: https://www.bilibili.com/video/BV1gm411m7i6/?share_source=copy_web&vd_source=92d754038ee61d01dacfbb2bacae8320

打点:

00:00 - 42:53 GET接口

42:54 - 51:24 POST接口

51:25 - 54:20 DELETE接口

54:21 - 1:02:11 UPDATE接口

1:02:17 - 1:04:22 打包 

一、项目创建 

初始化Spring boot应用:Spring Initializr

配置好以下内容(根据实际情况选择java版本) ,点GENERATE生成项目。

解压项目之后,idea打开open,导入项目的pom.xml文件。

 

项目结构,源代码全部放在JAVA文件夹下

因为还没有数据库,所以先把pom.xml里数据库的部分注释掉(不然会报错)

然后刷新一下maven,手动reload一下

接下来尝试运行,打开java文件,点击三角,运行main方法

 

可以看见运行起来

右键创建一个测试的controller,编写代码然后运行。

 

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @GetMapping ("/hello")
    public String hello() {
        return "Hello World";
    }
}

运行后,浏览器访问localhost:8080/hello

基本概念

  • **@Controller**:标记类为 Spring MVC 控制器,处理 HTTP 请求并返回视图(如 HTML)。
  • ​**@ResponseBody**:将方法的返回值直接写入 HTTP 响体中,而非渲染视图。
  • ​**@RestController** = @Controller + @ResponseBody,​专用于 RESTful API,自动将返回对象转为 JSON/XML 格式。

核心功能

  • 通过 @RequestMapping@GetMapping@PostMapping 等注解绑定 URL 路径。

改为List: 

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class TestController {
    @GetMapping ("/hello")
    public List<String> hello() {
        return List.of("Hello","World");
    }
}

显示JSON格式 :

 

 二、rest api规范

8个HTTP方法:

GET
POST
PUT
DELETE

OPTIONS
HEAD
TRACE
CONNECT

1.创建数据库 

启动数据库:net start mysql

登录数据库:mysql -uroot -p1234(-u和-p后写自己的用户名和密码)

//创建数据库
create database test
	character set utf8mb4
	collate utf8mb4_general_ci

//选中该数据库
use test;

//创建数据表
create table student(
	id int auto_increment primary key,
	name varchar(50) not null,
	phone char(11) not null,
	age int
);


//插入一条数据
insert into student (name,phone,age)
values('TOM','12345678910',30);

2.写实际代码

①GET接口

恢复上面注释的依赖

新建对应的package,在package里新建接口StudentRepository:

 

再建一个学生类: 

//Student.java
package com.example.demo.dao;

import jakarta.persistence.*;

@Entity
@Table(name="student")
public class Student {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "name")
    private String name;

    @Column(name = "phone")
    private String phone;

    @Column(name = "age")
    private int age;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

//StudentRepository.java
package com.example.demo.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student,Long> {

}

然后再创建一个package,写service层,同样新建一个接口文件StudentService,以及对应的一个实现StudentServiceImpl

现在目录是这个格式:

//StudentServiceImpl.java
package com.example.demo.service;

import com.example.demo.dao.Student;
import com.example.demo.dao.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl implements StudentService {
    
    @Autowired
    private StudentRepository studentRepository;
    
    @Override
    public Student getStudentById(long id) {
        return studentRepository.findById(id).orElseThrow(RuntimeException::new);
    }
}
//StudentService.java
package com.example.demo.service;

import com.example.demo.dao.Student;

public interface StudentService {
    public Student getStudentById(long id);

}

接下来写对应的api层controller的代码,新建package名为controller,包里建StudentController类。

package com.example.demo.controller;

import com.example.demo.dao.Student;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping("/student/{id}")
    public Student getStudent(@PathVariable long id) {
        return studentService.getStudentById(id);
    }
}

配置数据库url(用户名和密码写自己的):

spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=1234

在浏览器中输入  localhost:8080/student/1

返回信息: 

 


因为controller直接返回了这些值不够规范,有些加密字段是不想展示给前端的,比如这里将年龄保密,不显示。

所以新建一个dto的package以及StudentDTO对象,用来展示可以给前端的数据。

package com.example.demo.dto;

public class StudentDTO {
    private long id;
    private String name;
    private String phone;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

修改controller层和service层 :

package com.example.demo.controller;

import com.example.demo.Response;
import com.example.demo.dao.Student;
import com.example.demo.dto.StudentDTO;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping("/student/{id}")
    public Response<StudentDTO> getStudent(@PathVariable long id) {
        return Response.newSuccess(studentService.getStudentById(id));
    }
}
package com.example.demo.service;

import com.example.demo.dao.Student;
import com.example.demo.dto.StudentDTO;

public interface StudentService { 
    StudentDTO getStudentById(long id);
}
package com.example.demo.service;

import com.example.demo.converter.StudentConverter;
import com.example.demo.dao.Student;
import com.example.demo.dao.StudentRepository;
import com.example.demo.dto.StudentDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentRepository studentRepository;

    @Override
    public StudentDTO getStudentById(long id) {
        Student student= studentRepository.findById(id).orElseThrow(RuntimeException::new);
         return StudentConverter.convertStudent(student);
    }
}

新建package和类:

package com.example.demo.converter;

import com.example.demo.dao.Student;
import com.example.demo.dto.StudentDTO;

public class StudentConverter {
    public static StudentDTO convertStudent(Student student) {
        StudentDTO studentDTO = new StudentDTO();
        studentDTO.setId(student.getId());
        studentDTO.setName(student.getName());
        studentDTO.setPhone(student.getPhone());
        return studentDTO;
    }
}

新建一个Response类,统一一些后端访问的格式:

package com.example.demo;

public class Response <T>{
    private T data;
    private boolean success;
    private String errorMsg;

    public static <K> Response<K> newSuccess(K data) {
        Response<K> response = new Response<>();
        response.setData(data);
        response.setSuccess(true);
        return response;
    }

    public static Response<Void> newFail(String errorMsg) {
        Response<Void> response = new Response<>();
        response.setErrorMsg(errorMsg);
        response.setSuccess(false);
        return response;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}

 把代码都修改完之后启动,可以看见age隐藏了没有显示。返回成功。

 

以上是完整的GET查询接口的实现,用来查询id=1的学生信息。


②POST接口

接下来新增一个POST接口,用来新增学生信息。

目的:将前端传来的json文件转为Java对象存储至数据库。因为传过来的DTO,所以需要converter,之所以返回getbyid,因为这个方法返回是Long。

编写代码,在原有文件上新增就行,以下复制完整的:

package com.example.demo.controller;

import com.example.demo.Response;
import com.example.demo.dao.Student;
import com.example.demo.dto.StudentDTO;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping("/student/{id}")
    public Response<StudentDTO> getStudent(@PathVariable long id) {
        return Response.newSuccess(studentService.getStudentById(id));
    }

    @RequestMapping("/student")
    @PostMapping("/student")
    public Response<Long> addNewStudent(@RequestParam StudentDTO studentDTO) {
        return Response.newSuccess(studentService.addNewStudent(studentDTO));

    }
}
package com.example.demo.service;

import com.example.demo.dao.Student;
import com.example.demo.dto.StudentDTO;

public interface StudentService {
    StudentDTO getStudentById(long id);
    
    Long addNewStudent(StudentDTO studentDTO);
}
package com.example.demo.service;

import com.example.demo.converter.StudentConverter;
import com.example.demo.dao.Student;
import com.example.demo.dao.StudentRepository;
import com.example.demo.dto.StudentDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentRepository studentRepository;

    @Override
    public StudentDTO getStudentById(long id) {
        Student student= studentRepository.findById(id).orElseThrow(RuntimeException::new);
        return StudentConverter.convertStudent(student);
    }

    @Override
    public Long addNewStudent(StudentDTO studentDTO) {
        List<Student> studentList=studentRepository.findByPhone(studentDTO.getPhone());
        if (!CollectionUtils.isEmpty(studentList)){
            throw new IllegalStateException("phone:"+studentDTO.getPhone()+" has been taken");
        }
        Student student=studentRepository.save(StudentConverter.convertStudent(studentDTO));
        return student.getId();
    }
}
package com.example.demo.converter;

import com.example.demo.dao.Student;
import com.example.demo.dto.StudentDTO;

public class StudentConverter {
    public static StudentDTO convertStudent(Student student) {
        StudentDTO studentDTO = new StudentDTO();
        studentDTO.setId(student.getId());
        studentDTO.setName(student.getName());
        studentDTO.setPhone(student.getPhone());
        return studentDTO;
    }

    public static Student convertStudent(StudentDTO studentDTO) {
        Student student = new Student();
        student.setName(studentDTO.getName());
        student.setPhone(studentDTO.getPhone());
        return student;
    }
}
package com.example.demo.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface StudentRepository extends JpaRepository<Student,Long> {

    List<Student> findByPhone(String phone);
}

 修改完代码就可以使用Postman工具新增学生信息(没有下载所以跳过这步了)


③DELETE接口

接下来实现DELETE删除接口。

在原有文件新增就行,新增代码如下:

//StudentController
    @DeleteMapping("/student/{id}")
    public void deleteStudentById(@PathVariable long id) {
        studentService.deleteStudentById(id);
    }


//StudentService
void deleteStudentById(long id);


//StudentServiceImpl
 @Override
    public void deleteStudentById(long id) {
        studentRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("id:"+ id +"doesn't exist!"));
        studentRepository.deleteById(id);
    }

接下来也是使用postman来删除和查询。(没下载所以又跳过这步,之后如果下载了再来补) 


④UPDATE接口

接下来实现UPDATE接口。

在原有文件新增代码如下:

//StudentController
     @PutMapping("/student/{id}")
    public Response<StudentDTO> updateStudentById(@PathVariable long id, @RequestParam (required = false)String name,
                                              @RequestParam(required = false)String phone) {
        return Response.newSuccess(studentService.updataStudentById(id,name,phone));
    }


//StudentService
StudentDTO updataStudentById(long id, String name, String phone);


//StudentServiceImpl
 @Override
    @Transactional
    public StudentDTO updataStudentById(long id, String name, String phone) {
        Student studentInDB=studentRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("id:"+ id +"doesn't exist!"));
        if(StringUtils.hasLength(name) && !studentInDB.getName().equals(name)){
            studentInDB.setName(name);
        }
        if(StringUtils.hasLength(phone) && !studentInDB.getPhone().equals(phone)){
            studentInDB.setPhone(phone);
        }
        Student student=studentRepository.save(studentInDB);
        return StudentConverter.convertStudent(student);
    }

接下来也是使用postman来更新和查询。

三、打包项目 

使用命令:mvn clean install 

 

但是出现错误:

错误信息:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:3.4.1:clean (default-clean) on project demo: The plugin org.apache.maven.plugins:maven-clean-plugin:3.4.1 requires Maven version 3.6.3 -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginIncompatibleException

原因是当前maven版本为3.6.1,但项目依赖 Spring Boot 3.4.4,官方要求 ​Maven 3.8.8+ 或 ​Java 21+。

重新下载更高级的maven版本:Welcome to Apache Maven – Maven

下载教程:Maven下载以及项目创建(笔记)_maven 依赖 如何下载 com.github-CSDN博客

需要注意!重新配置maven环境变量时,最好删除原来的MAVEN_HOME,重新添加,不然不会更新。 

IDEA重新配置maven路径,重启:

可以看到已经将版本更新了 

使用命令:mvn clean install ,成功啦!!

复制一下jar包路径

 

可以用java -jar demo-0.0.1-SNAPSHOT.jar来启动项目:  


以上,总结:


完结撒花,零基础,耗时7小时。

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

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

相关文章

车架号查询车牌号接口如何用Java对接

一、什么是车架号查询车牌号接口&#xff1f; 车架号查询车牌号接口&#xff0c;即传入车架号&#xff0c;返回车牌号、车型编码、初次登记日期信息。车架号又称车辆VIN码&#xff0c;车辆识别码。 二、如何用Java对接该接口&#xff1f; 下面我们以阿里云接口为例&#xff0…

npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本的处理方法

1、安装了node.js后&#xff0c;windows powershell中直接输入npm&#xff0c;然后就报错 2、出现原因&#xff1a;权限不够 系统禁用了脚本的执行&#xff0c;所以我们在windows powershell输入npm -v的时候&#xff0c;就会报上面的错误。 3、解决 Set-ExecutionPolicy Un…

数仓开发那些事(11)

某神州优秀员工&#xff1a;一闪&#xff0c;领导说要给我涨米。 一闪&#xff1a;。。。。&#xff08;着急的团团转&#xff09; 老运维&#xff1a;Oi&#xff0c;两个吊毛&#xff0c;看看你们的hadoop集群&#xff0c;健康度30分&#xff0c;怎么还在抽思谋克&#xff1f…

从零开始完成冒泡排序(0基础)——C语言版

文章目录 前言一、冒泡排序的基本思想二、冒泡排序的执行过程&#xff08;一&#xff09;第一轮排序&#xff08;二&#xff09;第二轮排序&#xff08;三&#xff09;第三轮排序&#xff08;四&#xff09;第四轮排序 三、冒泡排序的代码实现&#xff08;C语言&#xff09;&am…

工业级POE交换机:助力智能化与自动化发展

随着工业互联网、物联网&#xff08;IoT&#xff09;和自动化技术的快速发展&#xff0c;网络设备在工业领域的应用日益广泛。然而&#xff0c;在严苛环境下&#xff0c;传统网络设备往往难以应对复杂的温湿度变化、电磁干扰和供电不稳定等挑战。为同时满足数据传输与供电一体化…

使用ZYNQ芯片和LVGL框架实现用户高刷新UI设计系列教程(第五讲)

在上一讲我们讲解了按键回调函数的自定义函数的用法&#xff0c;这一讲继续讲解回调函数的另一种用法。 首先我们将上一讲做好的按键名称以及自定义回调事件中的按键名称修改&#xff0c;改为默认模式为“open”当点击按键时进入回调函数将按键名称改为“close”&#xff0c;具…

Burp Suite Professional 2024版本安装激活指南

文章目录 burpsuite简介Burp Suite的主要组件&#xff1a;Burp Suite的版本使用场景 下载地址使用教程 burpsuite简介 Burp Suite 是一个广泛使用的网络安全测试工具&#xff0c;特别是在Web应用程序安全领域。它主要用于发现和修复Web应用中的安全漏洞&#xff0c;特别适用于渗…

【c++深入系列】:类与对象详解(上)

&#x1f525; 本文专栏&#xff1a;c &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 你仰望的星辰并非遥不可及&#xff0c;而是跋涉者脚印的倒影&#xff1b;你向往的远方未必需要翅膀&#xff0c;只要脚下始终有路&#x…

6、进程理论和简单进程创建

一、了解进程推荐看这个视频&#xff0c;很详细 1、概念 进程(Process)程序的运行过程&#xff0c;是系统进行资源分配和调度的独立单元程序的运行过程&#xff1a;多个不同程序 并发&#xff0c;同一个程序同时执行多个任务。 就需要很多资源来实现这个过程。 每个进程都有一…

Todesk介绍

文章目录 ToDesk 软件介绍1. 软件概述2. ToDesk 的功能特点2.1 简单易用2.2 高质量的图像与流畅的操作2.3 跨平台支持2.4 多屏显示与协作2.5 文件传输功能2.6 实时聊天与语音通话2.7 远程唤醒与自动启动2.8 多种权限设置与安全性2.9 无需公网 IP 3. ToDesk 的应用场景3.1 个人使…

Linux 进程3-fork创建子进程继承父进程缓冲区验证

目录 1. fork创建子进程继承父进程缓冲区验证 1.1 write向标准输出&#xff08;终端屏幕&#xff09;写入数据验证 1.1.1 write函数写入数据不带行缓冲刷新 \n 1.1.2 write函数写入数据带行缓冲刷新 \n 1.2 fork创建前执行printf函数 1.2.1 fork创建前执行printf函数带\n…

应用服务接口第二次请求一直pending问题

目录 一、问题背景二、问题排查过程三、解决方案四、总结 一、问题背景 升级内容发布到灰度环境&#xff0c;验证相关服务&#xff0c;查看接口调用日志&#xff0c;发现第一次请求正常&#xff0c;第二次相同接口请求就一直pending&#xff0c;其他服务也是如此 二、问题排查…

基于FPGA的ESP8266无线数据传输(温湿度DTH11、光照强度BH1750、WIFI模块)连接中国移动onenet云平台,仿真+上板

文章目录 一、创建云平台产品设备二、FPGA仿真WIFI模块通信过程仿真分析2.上板 总结 一、创建云平台产品设备 使用串口助手测试传输过程 相关信息记录 二、FPGA仿真WIFI模块通信过程 仿真分析 //各个状态tx_dataalways (posedge clk or negedge rst_n) beginif(!rst_n) beg…

5款视觉OCR开源模型

一、号称「世界上最好的 OCR 模型」Mistral OCR Mistral OCR 擅长理解复杂的文档元素&#xff0c;包括交错图像、数学表达式、表格和高级布局&#xff08;如 LaTeX 格式&#xff09;。该模型可以更深入地理解丰富的文档&#xff0c;尤其是包含图表、图形、公式和数字的科学论文…

计算机二级(C语言)考试高频考点总汇(三)—— 结构体和共用体、结构体对齐规则、联合体大小计算

目录 九、结构体和共用体 十、结构体对齐规则 十一、联合体大小计算 九、结构体和共用体 141. 结构体是&#xff08;不同类型成员的集合&#xff09;&#xff0c;是⼀种用户自定义的数据类型&#xff0c;可以将不同类型的成员组合在⼀起&#xff0c;用于表示&#xff08;复…

Charles抓HTTPS包

一、电脑端 1、证书下载与安装 安装完之后&#xff0c;重新点开看一看&#xff0c;确认下证书状态&#xff0c;安装的没问题 2、charles设置 抓电脑端要把这个点开 3、抓包 正经人看浏览器的包一般是F12&#xff0c;不过这里就用浏览器代替电脑软件了 如果配制好charles之后…

JavaScript模板字符串:

1.示例代码&#xff08;包含注释&#xff09;: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>JS-数…

【系统架构设计师】数据库系统 ③ ( 数据库设计过程 | 概念结构设计 | ER 图 简介 | 概念设计阶段 工作拆分 )

文章目录 一、数据库设计过程 概述二、ER 图 简介1、ER 图 概念2、ER 图 示例3、ER 图 关系类型① 一对一 ( 1:1 ) 关系② 一对多 ( 1:n ) 关系③ 多对多 ( n:n ) 关系 三、概念设计阶段 工作拆分 一、数据库设计过程 概述 数据库设计过程 : 需求分析阶段 : 明确 用户需求 ; …

Servlet开发与生命周期详解-2

一、在集成开发环境当中开发Servlet程序 1.集成开发工具很多&#xff0c;其中目前使用比较多的是&#xff1a; IntelliJ IDEA&#xff08;这个居多&#xff0c;IDEA在提示功能方面要强于Eclipse&#xff0c;也就是说IDEA使用起来比Eclipse更加智能&#xff0c;更好用。JetBrai…

将网络安全和第三方风险管理与业务目标相结合

在网络安全风险领域&#xff0c;我们经常遇到与企业语言不通的问题。这可能导致网络安全风险管理计划得不到支持。当发现网络安全风险时&#xff0c;困难在于以符合组织语言和目标的方式来表达它。 第三方风险属于另一个灰色地带。在组织内部&#xff0c;许多利益相关者&#…