如何开发一个Spring boot工程

引言

很多网站的后端都是基于Spring boot - mybatis进行开发的。
本文以此技术栈进行一个功能模块的开发

以最常见的注册功能为例

全部用最新的版本进行开发

工具

  1. 操作系统:Windows 10
  2. Java开发包:JDK 21
  3. 项目管理工具:Maven 3.6.3
  4. 项目开发工具:IntelliJ IDEA 2021.1.3 x64
  5. 数据库:Mysql
  6. 浏览器:Edge
  7. 服务器架构:Spring Boot 3.2.5 + MyBatis 3.0.3 + AJAX

部分坐标

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter-test</artifactId>
    <version>3.0.3</version>
    <scope>test</scope>
</dependency>

功能模块分析

本文开发的是注册模块,所以我们只会用一张表,其他模块思路与本文一致。

开发顺序

  • 我们应该遵循:数据库 -> 持久层 -> 业务层 -> 表现层 -> 前端页面 这样的顺序进行开发。

  • 功能上,我们应该先做基础功能,并遵循 增 -> 查 -> 删 -> 改的顺序来开发。

创建数据库

制作注册功能,本质是将用户的信息存放到数据库中。
我们建立一个数据库名为db

CREATE DATABASE db character SET utf8;

此时我们就需要考虑用户表中应该有哪些字段。

  • 首先应该有一个id并且这个id是唯一且不能为空,也就是主键,并且我们也可以为这个字段设置为自增字段。
  • 主要信息。在我们常用的软件上不难看出厂商保留了我们的哪些信息。
    如:用户名:username,密码:password。
  • 上面这两个是必不可少的,根据我们实际的项目,也可以保存其他的信息
    如:手机号:phone,电子邮箱:email,性别:sex,头像:avatar等。

此处我们就选用:自增主键id,用户名username,密码password,性别sex,手机号phone。

后续可能会有一些补充

建表语句:

CREATE TABLE `user` (
  `id` bigint NOT NULL,
  `username` varchar(32) NOT NULL,
  `password` varchar(32) NOT NULL,
  `sex` int,
  `phone` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

建表后在配置文件中连接数据库

此处使用yml类型的配置文件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

项目开发

此处开始我们代码的正式开发

创建实体类

我们在给数据库添加数据时,不能将字段全部用变量传入,这样很麻烦,也不方便后续的一些操作,所以我们会创建表对应的实体类对象
User

package com.angelday.test.entity;

public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String phone;
    /*后面是构造方法,Setter、Getter、toString方法
    由于可以使用IDEA自动生成,此处不再赘述*/
}

持久层

前面说过,注册的本质就是向数据库中添加一行数据
所以它的SQL语句是:

INSERT INTO db (username, password, age, phone) VALUES (值列表);

本项目使用的是mybatis进行开发
我们在根目录下创建一个包 mapper,并且在这个包下创建一个接口

package com.angelday.test.mapper;

import com.angelday.test.entity.User;
import org.apache.ibatis.annotations.Mapper;


@Mapper
public interface UserMapper {

    /**
     * 添加用户
     * @param user 添加来的user对象
     * @return 受影响的行数
     */
    Integer insertUser(User user);
}

并在resources包下创建一个包mapper用作UserMapper接口的映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.angelday.test.mapper.UserMapper">
    <!--id为对应接口的方法名,useGennerateadKeys开启自增,keyProperty指明自增字段-->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="uid">
        INSERT INTO t_user(username, password, phone, sex)
        VALUES (#{username}, #{password}, #{phone}, #{sex})
    </insert>
</mapper>

只有这个配置文件SpringBoot并不能识别到它,所以我们应该在配置文件中指定扫描路径

mybatis:
 mapper-locations: classpath:mapper/*.xml

单元测试

昨晚持久层之后我们要利用Springboot提供的@SpringBootTest进行测试,测试一定不要省略,这样可以减小问题的范围。

package com.angelday.store;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class StoreApplicationTests {

    @Autowired
    private UserMapper userMapper

    @Test
    void userMapperTest(){
    	User user = new User();
    	user.setUsername("Zhangsan");
    	user.setPassword("123456");
    	user.setSex(1);//一般都是规定1是男0是女
    	user.setPhone("12332112321");
    	//该方法返回int类型的整数表示受影响的行数
    	int rows = insertUser(User user);
    }
}

执行这个方法之后去数据库中查看信息,如果信息没有任何问题,即可执行下一步。

业务层

包结构一般为根目录下建一个service包
service包中有impl和ex两个包分别装Service的实现类与业务层中可能出现的异常。

规划异常

我们的用户名并没有设置为唯一,所以没有常见的用户名重复异常,我们就建立一个最大的异常作为所有Service层中会发生的异常

package com.angelday.test.service.ex;

/**
 * 业务异常基类,所有的业务层异常都继承这个异常
 */
public class ServiceException extends RuntimeException{

    public ServiceException() {
        super();
    }

    public ServiceException(String message) {
        super(message);
    }

    public ServiceException(String message, Throwable cause) {
        super(message, cause);
    }

    public ServiceException(Throwable cause) {
        super(cause);
    }

    protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

开发Service接口

我们在service包下建立一个UserService接口

package com.angelday.test.service;

import com.angelday.test.entity.User;
import org.springframework.stereotype.Service;

/**
 * 用户模块
 */
@Service
public interface IUserService {
	/**
     * 用户注册
     * @param user
     */
    void reg(User user);
}

实现类

在现实项目中一般我们的表中会有创建人创建时间修改人修改时间等字段用来记录日志,
而这些日志信息前端不会主动传来,所以我们会在业务层中补充这些字段

package com.angelday.store.service.impl;

import ...

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;
	
	/**
     * 用户注册
     * @param user 表单内容
     */
    @Override
    public void reg(User user){

        //将user中的信息完善如:创建人创建时间等
        user.setCreatedUser(user.getUsername());
        user.setModifiedUser(user.getUsername());

        Date date = new Date();
        user.setCreatedTime(date);
        user.setModifiedTime(date);

//密码一般不会用明文的形式存储到数据库中,此处就用常见的md5加密,对密码加密
        //md5加密
        String password = user.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));

        user.setPassword(password);

        //执行成功返回1
        Integer rows = userMapper.insertUser(user);
        if (rows != 1){
            throw new ServiceException("产生未知错误");
        }
    }
}

单元测试

记住,一定要测试!一定要测试!一定要测试!!!

@SpringBootTest
class StoreApplicationTests {

    @Autowired
    private UserService userService;

    @Test
    void userServiceTest(){
		User user = new User();
    	user.setUsername("Lisi");
    	user.setPassword("654321");
    	user.setSex(1);
    	user.setPhone("12332112321");
    	//该方法返回int类型的整数表示受影响的行数
    	int rows = reg(User user);
	}
}

执行后检查数据库的数据是否正确

表现层

这里我们需要确定前端具体要访问什么路径,一般都是由项目经理提前订好了,此处我们就自定义一个user/reg路径,前端传来User对象,请求方式为POST

请求参数:/user/reg
请求参数:User user
请求类型:POST
响应结果:Result< Void>

约定响应结果

后端所有的响应结果都要封装到这个类中,它一般包含以下三个变量
1.状态码 2. 消息 3. 数据

com.angelday.test.util下建立Result

package com.angelday.test.util;

/**
 * 统一返回结果类
 */
public class JsonResult<E> {
    private Integer state;
    private String message;
    private E data;
	//构造方法 & Getter和Setter方法
}

Controller

根据与前端的约定,我们创建UserController

@RestController
@RequestMapping("users")
public class UserController{

    @Autowired
    private UserService userService;

    /**
     * 用户注册
     * @param user 表单内的注册信息
     * @return 返回成功状态码
     */
    @RequestMapping("reg")
    public Result<Void> reg(User user){
        userService.reg(user);
        return new Result<>(200);
    }
}

优化

写到这里发现:

  • 还有业务层的异常没有处理
  • 成功的状态码不应该直接我们自己写,而是由前后端约定好的值,声明为常量
集中处理异常,声明状态码与消息的常量

创建一个Controler的基类,所有的表现层都继承这个类,在这个类里我们进行集中处理异常,并且封装一些状态码和信息做为常量。

使用@ExceptionHandler可以集中处理异常

/**
 * 控制类的基类,负责管理通用的操作与数据
 */
public class BaseController {

    public static final int OK = 200;

    /**
     * 集中处理异常
     * @param e 异常对象
     * @return 返回的json格式数据
     */
    @ExceptionHandler({ServiceException.class,FileUploadException.class})
    public Result<Void> handlerException(Throwable e){
        Result<Void> result = new Result(e);
        if (e instanceof ServiceException){
            result.setState(1000);
            result.setMessage("在插入数据时发生未知错误");
        }
    }
}

最后我们让UserController继承BaseController

测试

此处可以使用PostMan或者直接用浏览器访问该路径

localhost:8080/users/reg?username=zhangsan&password=123456

如果数据成功添加到数据库中,本模块开发完成

前端页面

页面的组件此处不详细讲解,只是向大家说明,表单的idform-register,提交表单数据的按钮idbutton-register
大家只需要根据自己的表单id与按钮id修改名称即可。

AJAX请求

一般在body标签的结尾前添加script标签,用来添加函数

<body>
..........
<!--页面的组件-->
	<script>
		//首先监听按钮是否被点击
		//此处使用id选择器,并且为其添加click事件
		$("#button-register").click(function (){
			//按钮点击后发送AJAX请求
			$.ajax({
				url: "/users/reg",
				type: "POST",
				// 使用serialize()方法会自动将表单json数据转化为username=Xxx的形式
				data: $("#form-register").serialize(),
				dataType: "JSON",
				//成功的回调函数
				success: function (json) {
					if (json.state == 200){
						alert("注册成功");
					} else {
						alert("注册失败");
					}
				},
				//失败的回调函数
				error: function (xhr) {
					alert("注册时产生未知错误,请稍后重新尝试!"+ xhr.status);
				}	
			});
		});
	</script>
</body>

单元测试

此处我们可以运行TestApplication主程序开启服务,并在页面填入数据进行提交,如果返回警告框:注册成功,并且数据库中的数据没有异常,整个模块功能的开发阶段,完成!

结语

如果有其他的问题欢迎私信我,后续有其他的优化:如:使用Redis、使用会话跟踪技术、拦截器/过滤器等,我会再创一个分栏。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

应用层协议——http协议和https协议

目录 一、HTTP协议 1、概念 2、URL 二、HTTP协议格式 1、请求协议格式 2、响应协议格式 三、HTTP的请求方法 四、HTTP的状态码 五、HTTP常见的报头 六、HTTP和HTTPS 1、HTTPS协议 2、HTTPS的加密原理 1、基本概念 2、加密原理 通常我们程序员在网络编程的时候&am…

CSDN如何转载他人文章(超简单)

经常遇到一篇很好的文章&#xff0c;但是CSDN没有转载功能&#xff0c;所以需要我们自己处理一下。以谷歌浏览器打开某篇文章为例 一、按F12打开开发者工具 二、复制转载文章内容 按Ctrlf查找content_views&#xff0c;找到这一行<div id"content_views" class&…

2024项目拆解日均引流100+精准创业粉,全程干货

详情介绍 2024年项目拆解引流高质量创业粉&#xff0c;全程干货单日轻松引流100&#xff0c;项目拆解类视频本身引流效果就非常不错&#xff0c;视频内容针对性强直击创业粉内心&#xff0c;获客非常有效。做好视频钩子&#xff0c;和后端承接&#xff0c;赚钱没那么难。 课程…

没有精益管理内容的数字化,会是成功的数字化吗?

精益管理与数字化的结合被认为是制造业和企业管理中的一种重要转型策略。精益管理注重消除浪费、提升效率和质量&#xff0c;而数字化则通过技术手段来实现这一目标&#xff0c;两者的结合能够带来更高效、更智能的生产和管理方式。 首先&#xff0c;精益管理的核心理念是价值…

什么是HTTPS证书?怎么免费申请?——值得收藏

SSL证书的核心功能在于保障互联网数据传输的安全性和网站身份的可靠性。它通过加密通信防止信息被窃取或篡改&#xff0c;同时验证网站的真实身份&#xff0c;有效抵御钓鱼攻击&#xff0c;增强用户信任。此外&#xff0c;使用SSL证书还有助于提升网站在搜索引擎中的排名&#…

Docker 入门篇(六)-- idea 打包 docker 镜像流程

环境准备&#xff1a; idea 环境&#xff1a;IntelliJ IDEA 2021.3.1 (Ultimate Edition)docker 版本&#xff1a;v. 26.1.0准备 springboot jar 文件 &#xff1a;target/DockerDemo-0.0.1-SNAPSHOT.jardocker 可视化管理工具 portainer &#xff1a;v2.6.0 一. 配置docker远…

前端面试题大合集3----网络篇

一、Http协议详解&#xff0c;http请求方式&#xff0c;http状态码 Http协议详解&#xff1a; 全称Hyper Text Transfer Protocol&#xff0c;即超文本传输协议&#xff0c;是互联网上应用最为广泛的一种网络传输协议。 是一个无状态的应用层协议&#xff0c;即不会保存客户…

【管理咨询宝藏92】国际咨询公司为大型药企数字化转型项目规划方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏92】国际咨询公司为大型药企数字化转型项目规划方案 【格式】PDF版本 【关键词】国际咨询公司、药企转型、数字化转型 【核心观点】 - 企业业务…

51-48 CVPR 2024 | Vlogger: make your dream a vlog 自编剧制作视频博客

24年1月&#xff0c;上海交大、上海人工智能实验室、中科院联合发布Vlogger&#xff1a;make your dream a vlog。该论文主要工作是生成超过5分钟的视频博客vlog。鉴于现有文本到视频T2V生成方法很难处理复杂的故事情节和多样化的场景&#xff0c;本文提出了一个名为Vlogger的通…

百度文库最新AI旋转验证码

上个月发现百度文库最新出了一个验证码&#xff0c;是AI生成的。内容每次可能都不一样&#xff0c;所以给识别造成 了很大困难。传统的比对放松完全失效。 一、介绍 这个是最近才出的最新验证码&#xff0c;内容主要以工厂、建筑、山峰、机器人、汽车、盆栽植物等为主。如下图…

Elasticsearch:如何使用 Java 对索引进行 ES|QL 的查询

在我之前的文章 “Elasticsearch&#xff1a;对 Java 对象的 ES|QL 查询”&#xff0c;我详细介绍了如何使用 Java 来对 ES|QL 进行查询。对于不是很熟悉 Elasticsearch 的开发者来说&#xff0c;那篇文章里的例子还是不能单独来进行运行。在今天的这篇文章中&#xff0c;我来详…

【DPU系列之】Bluefield 2 DPU卡的功能图,ConnectX网卡、ARM OS、Host OS的关系?(通过PCIe Switch连接)

核心要点&#xff1a; CX系列网卡与ARM中间有一个PCIe Swtich的硬件单元链接。 简要记录。 可以看到图中两个灰色框&#xff0c;上端是Host主机&#xff0c;下端是BlueField DPU卡。图中是BF2的图&#xff0c;是BF2用的是DDR4。DPU上的Connect系列网卡以及ARM系统之间有一个…

第一课为SimaPro的基本特征

问题&#xff1a; 咖啡机的设计中的环境影响指标。 step 1 点击Wizards&#xff0c;看到“Guided tour (with coffee)”。 在这个例子里&#xff0c; 定义了两种咖啡机&#xff1a; Sima型咖啡机 和 Pro型咖啡机&#xff0c; 具有以下规格&#xff1a; Sima型咖啡机 Pro型咖啡…

MySQL——Windows平台下MySQL安装与配置(一)MySQL安装

Windows平台下安装和配置 基于Windows平台的MySQL安装文件有两个版本&#xff0c;一种是以.msi作为后缀名的二进制分发版&#xff0c;一种是以.zip作为后缀的压缩文件。其中.msi的安装文件提供了图形化的安装向导&#xff0c;按照向导提示进行操作即可安装完成&#xff0c;.zip…

7-92 骨牌铺方格

在2n的一个长方形方格中&#xff0c;用一个12的骨牌铺满方格&#xff0c;输入n&#xff0c;输出铺放方案的总数。例如n3时&#xff0c;骨牌的铺放方案有3种&#xff0c;如下图所示。 输入格式: 测试数据有多组&#xff0c;处理到文件尾。每组测试输入一个整数n&#xff08;0&l…

【华为】AC直连二层组网隧道转发实验配置

【华为】AC直连二层组网隧道转发实验配置 实验需求拓扑配置AC数据规划表 AC的配置顺序AC1基本配置(二层通信)AP上线VAP组关联--WLAN业务流量 LSW1AR1STA获取AP的业务流量 配置文档 实验需求 AC组网方式&#xff1a;直连二层组网。 业务数据转发方式&#xff1a;隧道转发。 DHC…

[JUCE]从一个有关右值引用的bug,探幽移动语义

一、问题 当我尝试在\JUCE\extras\WindowsDLL\Builds\VisualStudio2022目录下编译JUCE库的时候&#xff0c;提示报错如下&#xff1a; 报错提示如下&#xff1a; 这里涉及到两个问题 一、这个std::move是干嘛用的 二、为什么这里会报错&#xff1f; 另外&#xff0c;我在实…

Mybatis进阶2

Mybatis进阶1-CSDN博客 Mybatis入门-CSDN博客 Mybatis入门2-CSDN博客 我们接下来要学习Mybatis的高级查询 我们先在数据库中准备我们需要的数据表 teacher表 课程表&#xff1a;与教师表是一对多的关系&#xff0c;所以有一个外键字段 学生表 由于学生表和课程表是多对多的…

Android selinux权限

一.SE 概述 SELinux 是由美国NSA&#xff08;国安局&#xff09;和 SCC 开发的 Linux的一个扩张强制访问控制安全模块。原先是在Fluke上开发的&#xff0c;2000年以 GNU GPL 发布。从 fedora core 2开始&#xff0c; 2.6内核的版本都支持SELinux。 在 SELinux 出现之前&#…
最新文章