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

java抽奖系统(二)

 3. 新建项目

3.1 选择相应的框架

pom文件配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.6</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>lottery_system</artifactId><version>0.0.1-SNAPSHOT</version><name>lottery_system</name><description>lottery_system</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>


3.2 代码结构设计

分层结构如下:

 

4. 功能模块设计

4.1 错误码

        我们对dao层不进行定义错误码;

对controller层和servoce层进行定义错误码;

对于一个全局的错误码,成功,失败,未知;

代码如下:

package com.example.lotterysystem.common;/*** @version 1.0* @Author 作者名* @Date 2024/11/24 19:55* @注释*/
public interface GlobalErrorCodeConstants {ErrorCode SUCCESS = new ErrorCode(200,"成功!");ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500,"系统异常!");ErrorCode UNKNOW = new ErrorCode(101,"未知错误!");
}

4.2 ⾃定义异常类

根据控制层和服务层来分别写相应的代码,其实两部分的代码都相近,同时引入了@EqualsAndHashCode(callSuper = true)注解:

@Data
@EqualsAndHashCode(callSuper = true)
public class ControllerException extends RuntimeException{/*** @see com.example.lotterysystem.common.errcode.ControllerErrorCodeConstants*/private int code;//异常吗private String message;//异常消息//为了序列化public ControllerException(){}public ControllerException(Integer code,String message){this.code = code;this.message = message;}public ControllerException(ErrorCode errorCode){this.code = errorCode.getCode();this.message= errorCode.getMessage();}
}

4.3. CommonResult<T>

        CommonResult<T>作为控制器层⽅法的返回类型,封装HTTP接⼝调⽤的结果,包括成功数据、错 误信息和状态码。它可以被SpringBoot框架等⾃动转换为JSON或其他格式的响应体,发送给客⼾端。

关于为什么要封装?

1. 统⼀的返回格式:确保客⼾端收到的响应具有⼀致的结构,⽆论处理的是哪个业务逻辑。 2. 错误码和消息:提供错误码(code)和错误消息(msg),帮助客⼾端快速识别和处理错误。

3. 泛型数据返回:使⽤泛型允许返回任何类型的数据,增加了返回对象的灵活性。

4. 静态⽅法:提供了error()和success()静态⽅法,⽅便快速创建错误或成功的响应对象。

5. 错误码常量集成:通过ErrorCode和GlobalErrorCodeConstants使⽤预定义的错误码,保持错 误码的⼀致性和可维护性。

6. 序列化:实现了Serializable接⼝,使得CommonResult对象可以被序列化为多种格式,如 JSON或XML,⽅便⽹络传输。

7. 业务逻辑解耦:将业务逻辑与API的响应格式分离,使得后端开发者可以专注于业务逻辑的实 现,⽽不必关⼼如何构建HTTP响应。

8. 客⼾端友好:客⼾端开发者可以通过统⼀的接⼝获取数据和错误信息,⽆需针对每个API编写特 定的错误处理逻辑。

@Data
//因为时进行http传输,为了成功传输就要进行序列化
public class CommonResult<T> implements Serializable {private Integer code;private T data;private String message;public static  <T> CommonResult<T> success(T data){CommonResult<T> result = new CommonResult<>();result.code = GlobalErrorCodeConstants.SUCCESS.getCode();result.data = data;result.message = "";return result;}public static  <T> CommonResult<T> error(Integer code,String message){Assert.isTrue(!GlobalErrorCodeConstants.SUCCESS.getCode().equals(code),"code不是错误的异常");CommonResult<T> result = new CommonResult<>();result.code = code;result.message = message;return result;}public static  <T> CommonResult<T> error(ErrorCode errorCode){return error(errorCode.getCode(),errorCode.getMessage());}}

  4.4 jackson工具实现序列化

        相对而言protobuf(pb实现序列化非常快,但是可视化非常差);

public class JacksonUtil {private JacksonUtil(){}private final static ObjectMapper OBJECT_MAPPER;//1点对objectmapper进行私有化单例操作static {OBJECT_MAPPER = new ObjectMapper();}private static ObjectMapper getObjectMapper(){return  OBJECT_MAPPER;}//2点。使用callable支持使用lamda表达式来进行处理,无论序列化的操作过程中出现的//异常都可以tryparse进行捕捉private static <T > T tryParse(Callable<T> parser) {return tryParse(parser, JacksonException.class);}private static <T > T tryParse(Callable<T> parser, Class<? extends Exception> check){try {return parser.call();} catch (Exception ex) {if (check.isAssignableFrom(ex.getClass())) {throw new JsonParseException(ex);}throw new IllegalStateException(ex);}}/***序列化objectmapper* @param value* @return*/public static String writeValueAsString(Object value) {return JacksonUtil.tryParse(()->JacksonUtil.getObjectMapper().writeValueAsString(value));}/**反序列化objectmapper* @param content* @param valueType* @return* @param <T>*/public static <T > T readValue(String content, Class<T> valueType) {return JacksonUtil.tryParse(()->JacksonUtil.getObjectMapper().readValue(content, valueType));}/**反序列化list* @param content* @param parameterClasses* @return* @param <T>*/public static <T > T readListValue(String content, Class<?> parameterClasses) {JavaType javaType =  JacksonUtil.getObjectMapper().getTypeFactory().constructParametricType(List.class, parameterClasses);return JacksonUtil.tryParse(()->{ return JacksonUtil.getObjectMapper().readValue(content,javaType);});}
}

4.5. ⽇志处理

        使用SLF4J+logback的配置

在本地(dev),通过控制台来打印出日志;

服务器:日志主要存在目标目录文件;

application.properties配置:

spring.application.name=lottery_system
## logback xml ##
logging.config=classpath:logback-spring.xml
spring.profiles.active=dev

新增logback-spring.xml文件:

对于本地和服务器的日志进行配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="60 seconds" debug="false"><springProfile name="dev"><!--输出到控制台--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n%ex</pattern></encoder></appender><root level="info"><appender-ref ref="console" /></root></springProfile><springProfile name="prod,test"><!--ERROR级别的日志放在logErrorDir目录下,INFO级别的日志放在logInfoDir目录下--><property name="logback.logErrorDir" value="/root/lottery-system/logs/error"/><property name="logback.logInfoDir" value="/root/lottery-system/logs/info"/><property name="logback.appName" value="lotterySystem"/><contextName>${logback.appName}</contextName><!--ERROR级别的日志配置如下--><appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。--><File>${logback.logErrorDir}/error.log</File><!-- 日志level过滤器,保证error.***.log中只记录ERROR级别的日志--><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><!--滚动策略,按照时间滚动 TimeBasedRollingPolicy--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间--><FileNamePattern>${logback.logErrorDir}/error.%d{yyyy-MM-dd}.log</FileNamePattern><!--只保留最近30天的日志--><maxHistory>30</maxHistory><!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志--><!--<totalSizeCap>1GB</totalSizeCap>--></rollingPolicy><!--日志输出编码格式化--><encoder><charset>UTF-8</charset><pattern>%d [%thread] %-5level %logger{36} %line - %msg%n%ex</pattern></encoder></appender><!--INFO级别的日志配置如下--><appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。--><File>${logback.logInfoDir}/info.log</File><!--自定义过滤器,保证info.***.log中只打印INFO级别的日志, 填写全限定路径--><filter class="com.example.lotterysystem.common.filter.InfoLevelFilter"/><!--滚动策略,按照时间滚动 TimeBasedRollingPolicy--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间--><FileNamePattern>${logback.logInfoDir}/info.%d{yyyy-MM-dd}.log</FileNamePattern><!--只保留最近14天的日志--><maxHistory>14</maxHistory><!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志--><!--<totalSizeCap>1GB</totalSizeCap>--></rollingPolicy><!--日志输出编码格式化--><encoder><charset>UTF-8</charset><pattern>%d [%thread] %-5level %logger{36} %line - %msg%n%ex</pattern></encoder></appender><root level="info"><appender-ref ref="fileErrorLog" /><appender-ref ref="fileInfoLog"/></root></springProfile>
</configuration>

在配置的包中自定义过滤info级别日志的类:

public class InfoLevelFilter extends Filter<ILoggingEvent> {//过滤器来过滤info级别的日志,将info的日志进行接受;@Overridepublic FilterReply decide(ILoggingEvent iLoggingEvent) {if (iLoggingEvent.getLevel().toInt() == Level.INFO.toInt()){return FilterReply.ACCEPT;}return FilterReply.DENY;}
}

使用测试类来进行日志打印测试:

ps:未完待续

相关文章:

java抽奖系统(二)

3. 新建项目 3.1 选择相应的框架 pom文件配置如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:s…...

STM32F10x 定时器

使用定时器实现&#xff1a;B5 E5的开关 添加相关的.h路径文件 添加相关的.c配置文件 led.h文件 用于声明LED函数 #ifndef __LED_H //没有定义__LED_H #define __LED_H //就定义__LED_H #define LED1_ON GPIO_ResetBits(GPIOB,GPIO_Pin_5) #defi…...

从0开始学PHP面向对象内容之常用设计模式(适配器,桥接,装饰器)

二&#xff0c;结构型设计模式 上两期咱们讲了创建型设计模式&#xff0c;都有 单例模式&#xff0c;工厂模式&#xff0c;抽象工厂模式&#xff0c;建造者模式&#xff0c;原型模式五个设计模式。 这期咱们讲结构型设计模式 1、适配器模式&#xff08;Adapter&#xff09; …...

玩转数字与运算:用C语言实现24点游戏的扑克牌魅力

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

前端入门之VUE--基础与核心

前言 VUE是前端用的最多的框架&#xff1b;这篇文章是本人大一上学习前端的笔记&#xff1b;欢迎点赞 收藏 关注&#xff0c;本人将会持续更新。 Vue学习笔记 用于构建用户界面的渐进式框架 构建用户界面&#xff1a;基于数据动态渲染页面渐进式&#xff1a;循序渐近的学…...

logback 初探学习

logback 三大模块 记录器&#xff08;Logger&#xff09;、追加器&#xff08;Appender&#xff09;和布局&#xff08;Layout&#xff09; 配置文件外层最基本的标签如图示 xml中定义的就是这个三个东西下面进入学习 包引入参考springboot 官方文档 Logging :: Spring Boo…...

在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的?

大家好&#xff0c;我是锋哥。今天分享关于【在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f;】面试题。希望对大家有帮助&#xff1b; 在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f; 在 Elasticsearch 中…...

1992-2021年 各省市县经过矫正的夜间灯光数据(GNLD、VIIRS)区域汇总:省份、城市、区县面板数据

1992-2021年 各省市县经过矫正的夜间灯光数据&#xff08;GNLD、VIIRS&#xff09;区域汇总&#xff1a;省份、城市、区县面板数据 .r.rar https://download.csdn.net/download/2401_84585615/90001905 从1992年至2021年&#xff0c;中国各省份、城市及区县的夜间灯光数据经过…...

linux实战-黑链——玄机靶场

黑链的特征&#xff1a; 隐藏链接&#xff1a;黑链通常隐藏在网站页面中&#xff0c;使用CSS、JavaScript或其他手段使其对普通用户不可见&#xff0c;但仍然能被搜索引擎爬虫检测到。恶意内容&#xff1a;这些链接指向的内容可能包含恶意软件、钓鱼页面或其他不良内容&#x…...

鸿蒙NEXT开发案例:字数统计

【引言】 本文将通过一个具体的案例——“字数统计”组件&#xff0c;来探讨如何在鸿蒙NEXT框架下实现这一功能。此组件不仅能够统计用户输入文本中的汉字、中文标点、数字、以及英文字符的数量&#xff0c;还具有良好的用户界面设计&#xff0c;使用户能够直观地了解输入文本…...

uniapp vue2项目迁移vue3项目

uniapp vue2项目迁移vue3项目&#xff0c;必须适配的部分 一、main.js 创建应用实例 // 之前 - Vue 2 import Vue from vue import App from ./App Vue.config.productionTip false // vue3 不再需要 App.mpType app // vue3 不再需要 const app new Vue({ ...App }) …...

16.C++STL 3(string类的模拟,深浅拷贝问题)

⭐本篇重点&#xff1a;string类的模拟&#xff0c;自己实现一个简单的string类 ⭐本篇代码&#xff1a;c学习/05.string类的学习 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 经典string类的模拟 1.1 深浅拷贝问题 1.2 使用深拷贝完成经典string类的…...

神经网络10-Temporal Fusion Transformer (TFT)

Temporal Fusion Transformer (TFT) 是一种专为时序数据建模而设计的深度学习模型&#xff0c;它结合了Transformer架构和其他技术&#xff0c;旨在有效地处理和预测时序数据中的复杂模式。TFT 于 2020 年由 Google Research 提出&#xff0c;旨在解决传统模型在时序预测中的一…...

“iOS profile文件与私钥证书文件不匹配”总结打ipa包出现的问题

目录 文件和证书未加载或特殊字符问题 证书过期或Profile文件错误 确认开发者证书和私钥是否匹配 创建证书选择错误问题 申请苹果 AppId时勾选服务不全问题 ​总结 在上线ios平台的时候&#xff0c;在Hbuilder中打包遇见了问题&#xff0c;生成ipa文件时候&#xff0c;一…...

《图像梯度与常见算子全解析:原理、用法及效果展示》

简介:本文深入探讨图像梯度相关知识&#xff0c;详细介绍图像梯度是像素灰度值在不同方向的变化速度&#xff0c;并以 “pig.JPG” 图像为例&#xff0c;通过代码展示如何选取图像部分区域并分析其像素值以论证图像梯度与边缘信息的关联。接着全面阐述了 Sobel 算子&#xff0c…...

【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨文章所属专栏&#xff1a;c篇–CSDN博客 文章目录 前言一.std::string对象的创建二.std::string对象的访问三.std::str…...

LlamaIndex ollama 搭建本地RAG应用,建立本地知识库

目录 简介安装前的准备下载ollama创建llamaindex conda环境&#xff0c;为后面编码作准备 环境变量迁移ollama到其他盘运行ollama方式一方式二禁止ollama开机自启动运行第一个模型 Chatbox聊天下载Chatbox配置ollama地址和模型验证 建立自身特定知识数据搭配大语言模型创建项目…...

draggable的el-dialog实现对话框标题可以选择

请看图 这个对话框使用了el-dialog并且draggable属性设置成了true&#xff0c;所以标题栏这里就可以拖动&#xff0c;现在用户想选中标题栏的文本进而复制。我看到这个需求头都大了。 我能想到的方案有三个&#xff1a;1. 取消draggable为true 2. 标题文案后面加一个复制按钮 …...

2024年Android面试总结

2024年Android面试总结 1.动画类型有哪些&#xff1f;插值器原理&#xff1f; 2.StringBuffer和StringBuilder区别&#xff1f; 3.jvm内存模型&#xff1f; 4.线程池7大核心参数及原理&#xff1f; 5.Android多进程通信方式有哪些&#xff1f;各自的优缺点&#xff1f; 6…...

树莓派3:64位系统串口(UART)使用问题的解决方法

前言 当我们要使用串口进行zigbee的短距离通信时,发现无法使用串口. 原因 树莓派3bCPU内部有两个串口,一个硬件串口(就是我们平时使用的UART),还有一个迷你串口(mini-uart),在老版本的树莓派中把硬件串口分配在GPIO上,可以单独使用.但是在新的树莓派中官方把硬件串口给了蓝牙…...

DeepSeek 服务故障,稳定性挑战待解

3 月 29 日晚至 30 日上午&#xff0c;DeepSeek 网页和 App 连崩 10 多个小时。这已不是其首次出问题&#xff0c;随着可能发布的 DeepSeek - V4&#xff0c;系统稳定性成梁文锋亟待解决的难题。事故回顾3 月 29 日 21:35&#xff0c;DeepSeek 网页/APP 服务异常&#xff0c;23…...

百考通:AI全流程智能化赋能答辩PPT,让学术展示更高效从容

毕业季、开题季&#xff0c;一份专业出彩的PPT是顺利通过答辩的关键。但从论文中提炼核心观点、规划答辩逻辑、设计美观版式&#xff0c;往往让学生们焦头烂额。百考通&#xff08;https://www.baikaotongai.com&#xff09; 凭借AI技术深度赋能&#xff0c;打造出一站式答辩PP…...

零门槛视频创作:OpenCut高效替代方案全解析

零门槛视频创作&#xff1a;OpenCut高效替代方案全解析 【免费下载链接】OpenCut The open-source CapCut alternative 项目地址: https://gitcode.com/gh_mirrors/ap/OpenCut 在数字内容创作爆炸的时代&#xff0c;视频编辑工具的选择直接影响创作效率与作品质量。Open…...

智能驾驶之红绿灯识别 斑马线识别 减速带识别 yolo数据集 深度学习数据集 第10625期

智能驾驶之红绿灯识别 斑马线识别 减速带识别 yolo第10625期 README 项目概述 本数据集聚焦于智能驾驶核心道路要素的识别任务&#xff0c;提供高质量标注图像&#xff0c;专为训练和评估目标检测模型而设计。数据涵盖城市道路常见交通设施与标记&#xff0c;适用于自动驾驶感知…...

Java 使用国密算法实现数据加密传输

本文是混合加密&#xff1a;前端 SM2 SM4&#xff0c;后端 Spring Boot Hutool 解密的完整示例。 方案的逻辑是&#xff1a; 前端随机生成一个 SM4 key 用 SM4 加密整个业务 JSON 用后端提供的 SM2 公钥 加密这个 SM4 key 后端先用 SM2 私钥 解出 SM4 key 再用 SM4 解出…...

Verilog握手信号实战:如何用valid/ready搭建高效数据流水线(附完整代码)

Verilog握手信号实战&#xff1a;如何用valid/ready搭建高效数据流水线&#xff08;附完整代码&#xff09; 在FPGA开发中&#xff0c;数据流水线是实现高性能计算的关键架构。但当我们面对不同处理速度的模块时&#xff0c;如何确保数据既不丢失又不阻塞&#xff1f;valid/rea…...

BGE-Reranker-v2-m3企业部署:高并发请求压力测试案例

BGE-Reranker-v2-m3企业部署&#xff1a;高并发请求压力测试案例 1. 项目背景与价值 在企业级RAG&#xff08;检索增强生成&#xff09;系统中&#xff0c;检索精度直接影响最终的回答质量。传统向量检索虽然快速&#xff0c;但容易受到关键词相似性的干扰&#xff0c;返回大…...

coze-loop效果展示:看AI如何将冗长代码重构为高效简洁版本

coze-loop效果展示&#xff1a;看AI如何将冗长代码重构为高效简洁版本 1. 引言&#xff1a;AI代码优化的革命性工具 在软件开发领域&#xff0c;代码优化一直是一项既重要又具有挑战性的任务。传统的优化过程往往需要开发者具备深厚的算法知识和丰富的经验积累。而今天&#…...

SDXL 1.0电影级绘图工坊真实案例:文化遗产数字化重建与风格复原实践

SDXL 1.0电影级绘图工坊真实案例&#xff1a;文化遗产数字化重建与风格复原实践 想象一下&#xff0c;你面前有一张因年代久远而模糊不清的古建筑照片&#xff0c;或是仅存于文字描述中的历史场景。如何将它们清晰地、生动地、甚至以不同艺术风格再现出来&#xff1f;这曾是考…...

run-aspnetcore-microservices 购物车微服务:Redis分布式缓存与Grpc同步通信实现

run-aspnetcore-microservices 购物车微服务&#xff1a;Redis分布式缓存与Grpc同步通信实现 【免费下载链接】run-aspnetcore-microservices aspnetrun/run-aspnetcore-microservices: 是一个用于部署和运行 ASP.NET Core 微服务应用程序的开源项目&#xff0c;提供了一个简单…...