【Springboot开发】后端代码基础框架

前言:主要介绍最基础的springboot开发架构

目录

  • 1. overall
  • 2. 配置文件
    • 2.1 YAML
    • 2.2 properties
    • 2.3 配置文件加载顺序
    • 2.4 多配置文件
  • 3. 代码包
    • 3.1 infrastructure
      • 3.1.1 persistence
    • 3.2 application
      • 3.2.1 dto
      • 3.2.2 converter
      • 3.2.3 service
    • 3.3 api
      • 3.3.1 vo
      • 3.3.2 req
      • 3.3.3 converter
      • 3.3.4 controller
  • **结语**

1. overall

在这里插入图片描述
核心部分主要是src包,main包存放的是后端代码,test是用于测试main包的代码。main包主要包含以下几个部分:

  • java:存放后端代码
  • resources:存放配置文件
  • webapp:存放资源文件,如前端jsp、图片资源等

2. 配置文件

springboot使用固定名字的配置文件:application.propertiesapplication.yml

2.1 YAML

基本语法

  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • 大小写敏感

yml举例

server:
  port: 8080

2.2 properties

properties举例:

spring.application.name=apply

2.3 配置文件加载顺序

  1. 按目录。位置高的将覆盖位置低的。
    在这里插入图片描述
  2. application.properties 的优先级高于 application.yml
  3. 互补读取:
  • 如果优先级高的配置文件中没有某个配置项,则会到优先级低的配置文件中找该配置项,即具有互补功能。
  • 文件名相同才会互补

2.4 多配置文件

有时候为了分开produce和test配置,会使用多个配置文件。
在这里插入图片描述
这种情况下可以在application.yml文件中指定使用的配置文件:
在这里插入图片描述

3. 代码包

代码包的路径为:
在这里插入图片描述
其中buildbaseframe为项目名。
后端代码主要包含以下几个部分:

  • BuildBaseFrameApplication: 启动类
  • utils:工具代码包
  • infrastructure
  • application
  • api

3.1 infrastructure

对应数据访问层,主要包含:

  • common包: 底层的一些公共配置
  • 模块包: 如用户模块
    在这里插入图片描述
    本节主要对各个模块包进行说明。

3.1.1 persistence

数据持久化层,主要包括mysqlrepository

  1. mysql
    主要是用来和数据库做绑定,映射对象到PO。
    在这里插入图片描述
    xml文件固定格式为:
<?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.example.buildbaseframe.infrastructure.user.persistence.mysql.mapper.UserPoMapper">
    <select id="findThis" resultType="com.example.buildbaseframe.infrastructure.user.persistence.repository.po.UserPo">
        select *
        from t_user
        where id = #{id}
    </select>
</mapper>

namespace是为了绑定mysql包下对应的映射文件,下写各种sql操作语句。
xxxPoMapper文件是为了做数据库对象和PO对象的映射,举例:

@Mapper
public interface UserPoMapper extends BaseMapper<UserPo> {

    /**
     * 测试xml方式绑定查询
     */

    UserPo findThis(@Param("id") Long id);

}
  • PoMapper文件只需要写一个接口继承自BaseMapper,类型名为同名的Po类(自定义)
  • PoMapper文件的方法名和xml文件中的操作id需要一致
  • @Param传入参数也需要和xml对应
  1. repository
    主要操作PO对象。
    在这里插入图片描述
    PO包
    将数据库表结构映射到JAVA,举例:
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@TableName("t_user")
public class UserPo extends BaseDatabasePo {
    private static final long serialVersionUID = 1L;

    /**
     * 用户昵称
     */
    @TableField(value = "name")
    private String nickname;

    /**
     * 用户头像url
     */
    @TableField(value = "avatar_url")
    private String avatarUrl;

    /**
     * 用户个人介绍
     */
    @TableField(value = "description")
    private String introduction;

    /**
     * 用户性别
     */
    @TableField(value = "gender")
    private Integer gender;

}

由于对PO对象有一些公共操作,通常先在common包中写一个公共类:

@Data
@EqualsAndHashCode(exclude = {"createTime", "updateTime"})
public class BaseDatabasePo implements Serializable {

    /**
     * 主键ID
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    protected Long id;

    /**
     * 创建时间
     */
    @TableField
    protected LocalDateTime createTime;

    /**
     * 更新时间
     */
    @TableField
    protected LocalDateTime updateTime;

}

repository接口
主要包含一些对数据对象的最基本的操作方法。举例:

public interface UserRepository {
    public UserPo get(Long userId);

    public int update(UserPo po, Long userId);

    public Long insertOneUser(UserPo userPo);
}

repository实现类
主要是对接口类的实现。

@Repository
public class UserRepositoryImpl implements UserRepository {

    @Autowired
    private UserPoMapper mapper;

    @Override
    public UserPo get(Long userId) {
        return mapper.selectById(userId);
    }

    @Override
    public int update(UserPo po, Long userId) {
        UpdateWrapper<UserPo> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", userId);
        if (po.getNickname() != null)
            wrapper.set("nickname", po.getNickname());
        if (po.getAvatarUrl() != null)
            wrapper.set("avatar_url", po.getAvatarUrl());
        if (po.getIntroduction() != null)
            wrapper.set("introduction", po.getIntroduction());
        if (po.getGender() != null)
            wrapper.set("gender", po.getGender());
        return mapper.update(po, wrapper);
    }

    @Override
    public Long insertOneUser(UserPo userPo){
        mapper.insert(userPo);
        return userPo.getId();
    }
}
  • 先注入PoMapper对象,用于调用各种对数据库底层的操作

3.2 application

对应应用层,主要结构如下:
在这里插入图片描述

  • common包:公共配置,主要涉及到一些exception的处理
  • 各模块包
    主要讲解各模块包,结构如下,其中dto、converter、service是必须的:
    在这里插入图片描述

3.2.1 dto

前端给后端传递的数据,举例:

@Data
public class UserInfoDto {

    /**
     * 用户id
     */
    private Long id;

    /**
     * 用户昵称
     */
    private String nickname;

    /**
     * 用户头像url
     */
    private String avatarUrl;

    /**
     * 用户个人介绍
     */
    private String introduction;

    /**
     * 用户性别
     */
    private GenderEnum gender;

}

3.2.2 converter

只用写接口,具体方法会自动实现。用来实现Po和Dto对象之间的转换。

@Mapper(componentModel = "spring")
public interface UserAppConverter {

    UserInfoDto toUserInfoDto(UserPo po);

    UserPo toUserPo(UserInfoDto dto);

}

3.2.3 service

服务层的接口和实现,用来实现和数据访问层的交互。
接口

public interface UserService {

    public UserInfoDto getUserInfo(Long userId);

    public UserInfoDto updateUserInfo(UserInfoDto dto, Long userId);

    public Long insertOneUser(UserInfoDto userInfoDto);
}

实现类

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserAppConverter userAppConverter;

    /**
     * 根据id获取用户信息
     * @param userId
     * @return
     */
    @Override
    public UserInfoDto getUserInfo(Long userId) {
        UserPo po = userRepository.get(userId);
        if (po == null) {
            throw new NotFoundException("用户信息");
        }

        System.out.println(po);

        return userAppConverter.toUserInfoDto(po);
    }

    /**
     * 更新用户信息
     * @param dto
     * @param userId
     * @return
     * @throws NotFoundException
     */
    @Override
    public UserInfoDto updateUserInfo(UserInfoDto dto, Long userId){
        UserPo po = userAppConverter.toUserPo(dto);
        if (userRepository.get(userId) == null) {
            throw new NotFoundException("用户信息");
        }
        int succ = userRepository.update(po, userId);
        return userAppConverter.toUserInfoDto(userRepository.get(userId));
    }

    /**
     * 添加新用户
     * @param userInfoDto
     * @return
     */
    @Override
    public Long insertOneUser(UserInfoDto userInfoDto){
        UserPo userPo = userAppConverter.toUserPo(userInfoDto);
        UserPo userPo1 = userRepository.findByName(userPo.getNickname());

        if(userPo1!=null){
            throw new BusinessException(ExceptionType.DUPLICATE_ERROR);
        }

        Long id = userRepository.insertOneUser(userPo);

        return id;
    }

}

3.3 api

控制器层,目录结构如下:
在这里插入图片描述

  • common包:公共类,包括异常捕获、权限、page验证等功能
  • 各模块包
    主要讲解模块包,结构如下:
    在这里插入图片描述

3.3.1 vo

数据视图对象,后端传给前端的数据。

@Data
public class UserInfoVo {

    /**
     * 用户id
     */
    private String id;

    /**
     * 用户昵称
     */
    private String nickname;

    /**
     * 用户头像url
     */
    private String avatarUrl;

    /**
     * 用户个人介绍
     */
    private String introduction;

    /**
     * 用户性别
     */
    private String gender;

}

3.3.2 req

对vo对象做检查。

@Data
public class UserCreateReq {

    /**
     * 用户昵称
     */
    @Length(min = 2, max = 64, message = "昵称长度应在2-64之间")
    private String nickname;

    /**
     * 用户头像url
     */
    @URL(message = "头像应当是有效的图片url")
    @Length(max = 255, message = "头像URL长度不能超过255")
    private String avatarUrl;

    /**
     * 用户个人介绍
     */
    @Length(max = 255, message = "用户介绍长度不能超过255")
    private String introduction;

    /**
     * 用户性别
     */
    @EnumStringValidate(value = GenderEnum.class, message = "不是有效的性别类型")
    private String gender;

}

3.3.3 converter

dto和vo对象的转换。

@Mapper(componentModel = "spring")
public interface UserApiConverter{

    @Mapping(source = "introduction", target = "description")
    UserInfoVo toUserInfoVo(UserInfoDto dto);

    @Mapping(source = "description", target = "introduction")
    UserInfoDto toUserInfoDto(UserCreateReq req);


}

3.3.4 controller

api的实现。

@Validated
@RestController // 既需要返回html数据又需要返回非html数据,类上使用@controller,方法上@requestcontroller或@responsebody
@Slf4j
@RequestMapping("/api/v1/user")
public class UserController {
    @Autowired
    private UserService service;

    @Autowired
    private UserApiConverter userApiConverter;

    @Autowired
    private GenderEnumConverter genderEnumConverter;

    /**
     * 用户获得自己的基本信息
     *
     * @param
     * @return
     * @methodName getOwnInfo
     */
    // 可以不用返回CommonResullt,有包装器会拦截
    @RequestMapping(value = "/info/own", method = RequestMethod.GET)
    public UserInfoVo getOwnInfo() {
        return userApiConverter.toUserInfoVo(service.getUserInfo(SecurityContextHolder.getUserId()));
    }

    /**
     * 根据id获得用户信息
     *
     * @param
     * @return
     * @methodName getUserInfo
     */
    @RequestMapping(value = "/info/{userId}", method = RequestMethod.GET)
    public UserInfoVo getUserInfo(@PathVariable("userId") String userId) {


        return userApiConverter.toUserInfoVo(service.getUserInfo(Long.valueOf(userId)));
    }

}

结语

以上是关于springboot的一个基本框架的梳理,具体细节方面的实现需要根据实际需求修改。

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

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

相关文章

go websocket

WebSocket 是一种网络协议&#xff0c;建立在 HTTP 协议之上&#xff0c;允许双向通信。WebSocket 协议允许服务器发送数据到客户端&#xff0c;同时也可以让客户端向服务器发送数据。WebSocket 使用 HTTP 协议的升级请求和响应来建立连接。WebSocket 的主要优点在于它可以通过…

【JavaSE】接口 详解(下)

前言 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 接口实例运用 代码举例理解 比较对象的年龄 比较对象的姓名 利用冒泡排序实现Array.sort 年龄比较器 姓名比较器 比较示例测试 clone接口 浅拷贝和深拷贝 浅…

代码随想录学习Day 26

332.重新安排行程 题目链接 from collections import defaultdictclass Solution:def findItinerary(self, tickets):targets defaultdict(list) # 创建默认字典&#xff0c;用于存储机场映射关系for ticket in tickets:targets[ticket[0]].append(ticket[1]) # 将机票输入…

GlusterFS分布式存储

目录 前言 一、GlusterFS分布式存储概述 1、GFS概念 2、GFS特点 3、GFS术语 4、GFS构成 5、GFS工作流程 6、后端存储如何定位文件 7、GlusterFs的卷类型 7.1 Distributed Volume&#xff08;分布式卷&#xff09; 7.2 Striped Volume&#xff08;条带卷&#xff09…

【JavaEE初阶系列】——网络初识—TCP/IP五层网络模型

目录 &#x1f6a9;网络的发展史 &#x1f388;局域网LAN &#x1f388;广域网WAN &#x1f6a9;网络通信基础 &#x1f388;IP地址 &#x1f388;端口号 &#x1f388;协议类型 &#x1f388;五元组 &#x1f6a9;协议分层 &#x1f388;什么是协议分层 &#x…

Web前端-Ajax

Ajax 概念:Asynchronous JavaScript And XML,异步的JavaScript和XML。 作用: 1.数据交换:通过Ajax可以给服务器发送请求,并获取服务器响应的数据。 2.异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用的校验等等…

TryHackMe - HTTP Request Smuggling

学完、打完后的复习 HTTP 1 这部分比较简单&#xff0c;直接略过 HTTP2请求走私 首先要了解HTTP2的结构&#xff0c;与HTTP1之间的一些差异 HTTP2中不再使用CRLF来作为字段的边界限定&#xff0c;而是在二进制中直接通过长度、名字、值长度、值&#xff0c;来确认边界 而这…

Leetcode算法训练日记 | day21

一、二叉搜索树的最小绝对差 1.题目 Leetcode&#xff1a;第 530 题 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝对值。 示例 1&#xff1a; 输入&#xff1a;root [4,2,…

不到6毛钱的I2C总线实时时钟日历芯片LK8563

前言 8563实时时钟芯片&#xff0c;国内外均有多家生产&#xff0c;今推荐一个性价比极高的RTC芯片&#xff0c;LK8563&#xff0c;一片不到6毛钱. 特点 基于32.768kHz晶体的秒&#xff0c;分&#xff0c;小时&#xff0c;星期&#xff0c;天&#xff0c;月和年的计时 带有世…

Redis系列之基于Linux单机安装

Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库&#xff0c;并提供多种语言的 API。最近学习需要用到Redis&#xff0c;所以就去Linux服务器上部署一个&#xff0c;做下记录&#xff0c;方便…

web安全学习笔记【22】——文件上传(1)

WEB攻防-PHP应用&文件上传&函数缺陷&条件竞争&二次渲染&黑白名单&JS绕过 演示案例&#xff1a; PHP-原生态-文件上传-前后端验证PHP-原生态-文件上传-类型文件头验证PHP-原生态-文件上传-后缀黑白名单验证PHP-原生态-文件上传-解析配置&二次渲染…

JUC 线程及创建线程

最近想再系统地复习一遍并发&#xff0c;随便再把以前整理的笔记整理为博客。 概念 了解线程前先要了解一下进程&#xff0c;进程是程序的一次执行过程&#xff0c;是系统运行的基本单位&#xff0c;其可以拥有资源&#xff0c;一个进程在执行期间会执行一系列的命令。 什么…

华为OD机试真题-模拟数据序列化传输 -2024年OD统一考试(C卷)

题目描述: 模拟一套简化的 序列化只 传输方式,请实现下面的数据编码与解码过程 1、编码前数据格式为 [位置,类型,值],多个数据的时候用逗号分隔,位置仅支持数字,不考虑重复等场景;类型仅支持:Integer/String/Compose(Compose的数据类型表示该存储的数据也需要编码) 2.编码…

【攻防世界】Confusion1

php的标志是大象&#xff0c;Python的标志是蛇 。Python 的 Flask 框架( Flask 使用 Jinja2 作为模板引擎 ) 点进register.php 输入{{3*4}} 输入 {{config}} 也有回显&#xff0c;ssti 判断是否存在ssti注入&#xff1a; 1. {{8*8}} 2. {{config}} 过滤了关键字&#xff0…

二、显示图片、提取边缘特征并保存(C# + OpenCV)

实现功能&#xff1a; 1&#xff0c;打开照片&#xff0c;并显示 2&#xff0c;对选择的照片进行Canny边缘检测 3&#xff0c;保存边缘检测之后的结果 一、布局 打开在视图下打开工具箱 选择一个PictureBox&#xff0c;仨Button 对Button改个名字 仨Button&#xff0c;分别…

Python从0到100(十二):函数的定义及模块

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

AI大模型探索之路-应用篇2:Langchain框架ModelIO模块—数据交互的秘密武器

目录 前言 一、概述​​​​​​​ 二、Model 三、Prompt 五、Output Parsers 总结 前言 随着人工智能技术的不断进步&#xff0c;大模型的应用场景越来越广泛。LangChain框架作为一个创新的解决方案&#xff0c;专为处理大型语言模型的输入输出而设计。其中&#xff0c;…

设计模式(22):解释器模式

解释器 是一种不常用的设计模式用于描述如何构成一个简单的语言解释器&#xff0c;主要用于使用面向对象语言开发的解释器和解释器设计当我们需要开发一种新的语言时&#xff0c;可以考虑使用解释器模式尽量不要使用解释器模式&#xff0c;后期维护会有很大麻烦。在项目中&…

【Redis】持久化

文章目录 一、RDB1.1、RDB的自动备份与手动备份1.1.1、自动备份1.1.2、手动备份 1.2、RDB优点1.3、RDB缺点1.4、RDB快照1.5、RDB优化配置项 二、AOF2.1、AOF工作流程2.2、AOF写回策略2.3、MP-AOF实现2.4、AOF优缺点2.5、AOF重写机制 三、RDBAOF混合持久化3.1、数据恢复顺序和加…

阿里云OSS使用流程

准备工作 无论怎么样&#xff0c;你需要准备一个阿里云账号&#xff0c;点击&#xff1a;注册阿里云 输入相关信息&#xff0c;然后注册成功以后&#xff0c;点击 然后注册成功了&#xff0c;实名一下阿里云账号。打开实名入口&#xff0c;选择个人实名或者企业实名。 如果你…