当前位置: 首页 > news >正文

如何高效地架构一个Java项目

引言

        Java是企业级应用开发的主流语言之一,而我们作为使用Java语言的程序员,职称有初级、中级、高级、资深、经理、架构,但我们往往只是慢慢通过经验的积累迭代了自己的等级,如果没有保持学习的习惯,大多数程序员会停留在接近高级的位置,简单来讲就是CRUD工程师,小编不甘心于此,所以长期保持学习新知识的习惯,尝试很多大于自身能力的事情,我相信未来的某一天我会感谢曾经努力的自己,下面的内容是我在尝试架构项目时总结的经验,希望能帮助到大家

前期准备

  • 需求分析:明确项目的功能需求
  • 技术选型:
    • Java版本
      • 8,17
    • 框架选择
      • 应用:Spring,SpringBoot,SpringCloud
      • ORM(对象关系映射):JPA,MyBatis(Plus)
    • 数据库选择
      • 关系型:MySQL,PostgreSQL,Oracle
      • 非关系型:Redis,MongoDB
      • 时序数据库(物联网):TDengine,IoTDB
    • 构建工具
      • Maven,Gradle

项目结构设计

  • 分层架构
    • 认证授权
    • 控制层
    • 业务层
    • 数据层
  • 模块划分
    • 按功能划分
    • 按业务划分

简单示例

        跳过项目的功能需求分析(具体项目具体分析),技术选型,Java版本选择17,应用框架选择SpringBoot,ORM(对象关系映射)框架选择MyBatis-Plus,数据库选择MySQL 8.x,构建工具选择Maven,项目结构,拦截器中完成认证授权,控制层接收用户请求调用业务层的方法,业务层处理逻辑调用数据层的方法,数据层与数据库交互,跳过模块划分(具体项目具体分析)

准备开发环境

1.下载安装配置Java17

访问官方的下载地址:Java Archive Downloads - Java SE 17

1.下载并解压 

2.配置环境变量

我的电脑 -> 属性 -> 高级系统设置 -> 环境变量 ->系统变量(S) -> 新建(W)

双击系统变量(S)中的Path -> 新建(N) 

确定后打开命令提示符界面(快捷键 win+R 输入 cmd 回车),输入java -version命令查看是否安装成功

2.下载安装MySQL 8.x

访问官方的下载地址:MySQL :: Download MySQL Installer (Archived Versions)

参考文章:【MySQL8.0.39下载安装】_mysql8.0.39.0安装教程-CSDN博客 

架构项目

1.创建SpringBoot项目 

2.创建包/文件结构

3.认证与授权 

        首先确定使用什么标准和框架进行认证与授权,常见的标准有:OAuth 2.0,JWT,常见的框架有:Spring Security,Apache Shiro,我采用的是近几年很火的轻量级框架:SaToken,如何集成可以参考我的另一篇文章:Java集成Sa-Token进行认证与授权_基于satoken的 sop-CSDN博客

4.创建数据库、用户表(含索引)

DROP DATABASE IF EXISTS `muze`;
CREATE DATABASE `muze` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
USE `muze`;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',username VARCHAR(30) COLLATE utf8mb4_0900_bin NOT NULL COMMENT '用户名',password VARCHAR(255) COLLATE utf8mb4_0900_bin NOT NULL COMMENT '密码',PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
CREATE INDEX idx_username ON t_user(username);

5.创建用户实体

        为了方便实体类的编写,我们引入依赖 - 小辣椒

<!-- 小辣椒 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
/*** 用户实体* @author muze*/
@Data
@TableName("t_user")
public class User implements Serializable {@Serialprivate static final long serialVersionUID = 684552117916625567L;/*** 主键*/@TableId(type = IdType.AUTO)private Long id;/*** 账号*/private String username;/*** 密码*/private String password;
}

6.创建用户数据层

       技术选型时数据库是MySQL,ORM(对象关系映射)框架是MyBatis-Plus,因此引入对应依赖

<!-- MySQL -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version>
</dependency>
<!-- MyBatis-Plus -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.7</version>
</dependency>

在启动类上打MyBatis-Plus提供的@MapperScan("MyBatis Mapper 接口包路径"),自动扫描指定包下的 MyBatis Mapper 接口,并将它们注册为 Spring 容器中的 Bean

/*** 启动类* @author muze*/
@MapperScan("com.muze.project.mapper")
@SpringBootApplication
public class ProjectApplication {public static void main(String[] args) {SpringApplication.run(ProjectApplication.class, args);}}

在配置文件application.yml中添加数据库连接信息

spring:datasource:url: jdbc:mysql://localhost:3306/muze?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8username: 你的用户名password: 你的密码driver-class-name: com.mysql.cj.jdbc.Driver

用户数据层

/*** 用户数据层* @author muze*/
public interface UserMapper extends BaseMapper<User> {
}

7.创建用户业务层

        我习惯将业务层分离为接口层和实现层,所以我会在sevice包下创建一个impl包,如果你不习惯可以只编写实现层,编写用户登录方法前需要定义方法入参和返回值

入参:请求实体(用户名 + 密码)

返回值:登录结果

创建DTO(请求实体)

/*** 用户登录请求实体* @author muze*/
@Data
public class UserLoginDTO implements Serializable {@Serialprivate static final long serialVersionUID = -1706553212610156227L;/*** 用户名*/private String username;/*** 密码*/private String password;
}

用户登录业务接口层和实现层

/*** 用户业务接口层*/
public interface IUserService {/*** 登录* @param userLoginDTO 用户登录请求实体* @return 登录结果*/String login(UserLoginDTO userLoginDTO);
}
/*** 用户业务实现层* @author muze*/
@Service
public class UserServiceImpl implements IUserService {/*** 注入用户数据层*/@Autowiredprivate UserMapper userMapper;@Overridepublic String login(UserLoginDTO userLoginDTO) {// 取出用户名和密码String username = userLoginDTO.getUsername();String password = userLoginDTO.getPassword();// 构建查询条件LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<User>().eq(User::getUsername, username);// 查询用户User user = userMapper.selectOne(userLambdaQueryWrapper);// 如果用户为空或者输入密码与用户密码不匹配则返回:用户名或密码错误if (user == null || !password.equals(user.getPassword())) return "用户名或密码错误";// 使用SaToken的工具类StpUtil调用登录方法login,入参:用户idStpUtil.login(user.getId());// 返回:登录成功return "登录成功";}
}

8.创建用户控制层

        编写控制层前我们要先确定请求路径,请求方式,请求参数,响应数据

请求路径:/user/login

请求方式:POST

请求参数:用户名 + 密码

响应数据:响应码 + 响应消息 + 响应数据

DTO(请求实体)已经在编写用户业务层时创建好了

VO(响应实体)使用SaToken提供的SaResult

/*** 用户控制层*/
@RestController
@RequestMapping("/user")
public class UserLogin {/*** 注入用户业务接口层*/@Autowiredprivate IUserService userService;/*** 登录* @param userLoginDTO 用户登录请求实体* @return 响应码 + 响应消息 + 响应数据*/@PostMapping("/login")public SaResult login(@RequestBody UserLoginDTO userLoginDTO) {return SaResult.ok(userService.login(userLoginDTO));}
}

测试

编写sql语句新增一条用户信息用于测试登录

INSERT INTO t_user (username, password) VALUES ("muze", "123456");

启动项目,使用接口调试工具测试登录功能

端口默认为8080 

可以发现,Cookie中放入了一个令牌

 

        到此,一个拥有基础功能:登录,认证与授权的Java项目就架构完成了,后续就是按照功能需求划分模块进行开发了,希望能对你有所帮助!

彩蛋:你肯定也发现了,密码并没有进行加密解密,虽然在HTTPS协议中Post请求会对传输数据加密,但在HTTP协议中Post请求不会对传输数据加密,因此我们还应该对数据传输进行加密,小编会在后续更新一篇与数据加密相关的文章,敬请期待

相关文章:

如何高效地架构一个Java项目

引言 Java是企业级应用开发的主流语言之一&#xff0c;而我们作为使用Java语言的程序员&#xff0c;职称有初级、中级、高级、资深、经理、架构&#xff0c;但我们往往只是慢慢通过经验的积累迭代了自己的等级&#xff0c;如果没有保持学习的习惯&#xff0c;大多数程序员会停留…...

Scala的模式匹配(8)

package hfdobject Test35_1 { //需求:现在有一个数组Array(1,2,3,4)。我希望能定义三个变量&#xff0c;他们的值分别是数组中的第1&#xff0c;2&#xff0c;3个元素的值 def main(args: Array[String]): Unit {val arr Array(1,2,3,4,5)//第一个元素的值&#xff1a;arr(0…...

nodejs30: CSS 剪辑路径clip-path导致伪元素不可见问题及解决方法

相关问题 应用圆角裁剪时无法显示::after 取消clip-path设置&#xff1a; 完整问题代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, i…...

Git分布式版本控制工具 Git基本概念、Git工作流程、Git常用命令、Git远程仓库、IDEA操作Git

目录 ​​​​​​ 1.Git基本概念 1.1 概述 1.1.1 开发中的实际场景 1.1.2 版本控制器的方式 1.1.2.1 集中式版本控制工具(SVN) 1.1.2.2 分布式版本控制工具(Git) 2.概述git工作流程 3.Git常用命令 3.1 Git环境配置 3.1.1 下载与安装 3.1.2 基本配置 3.1.3 为常用指令配置别名&…...

十,[极客大挑战 2019]Secret File1

点击进入靶场 查看源代码 有个显眼的紫色文件夹&#xff0c;点击 点击secret看看 既然这样&#xff0c;那就回去查看源代码吧 好像没什么用 抓个包 得到一个文件名 404 如果包含"../"、"tp"、"input"或"data"&#xff0c;则输出"…...

Android 获取数字键盘和输入类型

在Android中&#xff0c;获取数字键盘可以通过为EditText设置输入类型为number或numberPassword来实现。以下是一个简单的例子&#xff1a; <!-- 在XML布局文件中 --> <EditText android:id"id/editTextNumber" android:layout_width"match_parent…...

8. 一分钟读懂“代理模式”

8.1 模式介绍 代理模式是一种结构型设计模式&#xff0c;它通过提供一个代理对象来替代对另一个对象&#xff08;真实对象&#xff09;的访问。代理对象与真实对象实现相同的接口&#xff0c;并通过代理类对真实对象的访问进行控制&#xff0c;可以在调用前后执行附加操作&…...

【实战攻略】如何从零开始快速实现深度学习新想法?——四步走战略

标题 【实战攻略】如何从零开始快速实现深度学习新想法&#xff1f;——四步走战略 【核心结论】 通过四步走战略&#xff0c;即找到baseline论文、深入baseline代码、搭建自己的pipeline、融入核心算法&#xff0c;新手也能快速实现深度学习新想法。 【通俗解释&#xff0…...

Creating Server TCP listening socket *:6379: bind: No error

启动redis报错&#xff1a;Creating Server TCP listening socket *:6379: bind: No error 解决方案&#xff1a; 1、直接在命令行中输入 redis-cli.exe 2、输入shutdown&#xff0c;关闭 3、输exit&#xff0c;退出 4、重新输入 redis-server.exe redis.windows.conf&…...

Go热加载工具air-使用说明-win11问题解决指南

写web程序 每次都要ctrlc 然后go run .非常但疼 用一下这个热加载工具air Live reload for Go apps 贴个github地址&#xff1a;https://github.com/air-verse/air 1. go版本1.23先install一下 go install github.com/air-verse/airlatest下载完发现输入air windows还是报…...

华为HarmonyOS 让应用快速拥有账号能力 -- 2 获取用户头像昵称

场景介绍 如应用需要完善用户头像昵称信息&#xff0c;可使用Account Kit提供的头像昵称授权能力&#xff0c;用户允许应用获取头像昵称后&#xff0c;可快速完成个人信息填写。以下只针对Account kit提供的头像昵称授权能力进行介绍&#xff0c;若要获取头像还可通过场景化控…...

oracle表迁移至postgre

第一步: 导出表结构 进入脚本 第二步: 删除spool相关和prompt相关(不需要表空间的情况下) 类似以下语句 第三步: 修改数据类型 VARCHAR2 --> VARCHAR VARCHAR2(200 CHAR) --> VARCHAR(200) NUMBER(10,2) --> numeric(10,2…...

【PlantUML系列】类图(一)

目录 一、类 二、接口 三、抽象类 四、泛型类 五、类之间的关系 六、添加注释 七、包图 八、皮肤参数 一、类 使用class关键字定义类&#xff0c;类名后跟大括号&#xff0c;声明类的属性和方法。 属性&#xff1a;格式为{visibility} attributeName : AttributeType…...

Unity AssetBundles(AB包)

目录 前言 AB包是什么 AB包有什么作用 1.相对Resources下的资源AB包更好管理资源 2.减小包体大小 3.热更新 官方提供的打包工具:Asset Bundle Browser AB包资源加载 AB包资源管理模块代码 前言 在现代游戏开发中&#xff0c;资源管理是一项至关重要的任务。随着游戏内容…...

腾讯面试:如何解决哈希冲突?

我们面试时经常被问到HashMap是怎么解决哈希冲突的&#xff0c;很多同学对其含糊其词、一知半解。因此小编对相关知识进行了总结&#xff0c;希望帮助读者加深对其理解。 哈希表就是通过散列函数将键映射到定值&#xff0c;简单来说就是一个键对应一个值。 而通过散列函数映射…...

【动手学运动规划】 4.5 A*算法

我宁愿永远做我自己&#xff0c;也不愿成为别人&#xff0c;即使那个人比你更快乐。 —《成为简奥斯汀》 &#x1f3f0;代码及环境配置&#xff1a;请参考 环境配置和代码运行! 4.5.1 概述 Dijkstra算法是基于广度优先搜索策略来遍历空间内的所有节点&#xff0c;最终计算出…...

Spring Boot 3.4.0 发布:功能概览与示例

Spring Boot 3.4.0 带来了许多增强功能&#xff0c;使现代应用开发更加高效、便捷和强大。以下是最新功能的完整概述&#xff0c;以及一些帮助您快速入门的代码示例。 1. 应用程序版本管理 Spring Boot 引入了 spring.application.version 属性&#xff0c;方便开发者设置和访…...

【48】Android通过libjpeg-turbo库实现图片压缩

&#xff08;1&#xff09;公司为节约图片占用服务器存储资源成本&#xff0c;需要对Android手机客户端所传递到云存储服务器中的图片进行压缩&#xff0c;在不影响图片失真程度的情况下&#xff0c;最大限度的压缩图片以节省图片所占用的存储空间。 &#xff08;2&#xff09;…...

Linux输入设备应用编程

本章学习输入设备的应用编程&#xff0c;首先要知道什么是输入设备&#xff1f;输入设备其实就是能够产生输入事件的设备就称为输入设备&#xff0c;常见的输入设备包括鼠标、键盘、触摸屏、按钮等等&#xff0c;它们都能够产生输入事件&#xff0c;产生输入数据给计算机系统。…...

【Vulkan入门】03-创建Device

目录 先叨叨git信息关键代码VulkanEnv::CreateDevice() 编译并运行程序题外话 先叨叨 在上篇已经选择了一个合适的PhysicalDevice。 本篇要为这个PhysicalDevice创将一个Device。Device可以理解为APP与PhysicalDevice之间的代理。 所有APP与PhysicalDevice之间交互的资源都通过…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...