ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于SpringBoot实现的抽奖系统(一)

基于SpringBoot实现的抽奖系统(一) 项目背景和介绍抽奖系统类似于直播中的抽奖活动,在日常生活中也是比较常见,于是基于SpringBoot提供一个安全,可靠,易于维护的抽奖平台,本次项目采用了以下的策略:1.集成多种技术组件:项目中集成了MySql,redis,RabbitMQ等常见的中间件.2.允许管理员创建配置抽奖活动,管理人员和奖品信息.3.使用了哈希加密,对称加密等加密方法保障用户的隐私数据.4.提供了比较全面的日志处理与异常处理机制,简化维护过程.项目结构展示层:使用web的方式展示前端界面.通信层:使用HTTP协议进行通信.服务层:包含日志模块,业务模块,中间件.数据层:使用mysql存储用户的数据和活动信息本次项目的结构中,common层表示存放的一些全局使用例如错误码,统一返回结果,拦截器等controller层中主要是与前端交互的接口,service层中就是接收controller层中任务处理.dao层是提供数据库中的查询等操作.数据库设计⽤户表存储⽤⼾信息如⽤户名、密码、邮箱等。活动表存储活动信息如活动名称、描述、活动状态等。奖品表存储奖品信息如奖品名称、奖品图等。活动奖品关联表存储⼀个活动下关联了哪些奖品。活动⽤户关联表存储⼀个活动下设置的参与⼈员。中奖记录表存储⼀个活动的中奖名单如活动id奖品id中奖者id等。项目启动定义错误码错误码是一种明确的表示错误信息的方式,与模糊的异常相比可以准确的指出错误所在,而错误码是由数字组成,也方便在日志中寻找.本次项目的错误码主要包含两个信息,错误码与错误信息,方便区分错误的类别.也定义了多模块中的错误码,将controller层与service层中的不同错误码分开,同时设计了全局的错误码,来对付意外的错误.自定义异常类自定义异常类作用是为了在可能抛出异常的地方,希望抛出我们可控的异常,这样可以方便定位到问题所在,异常类可以和错误码一起使用.统一返回结果为了方便返回,我们定义了CommonResultT来表示统一的返回结果,包括成功信息,错误信息,状态码.这样做的好处是将无论调用哪个接口,都确保客户端收到的响应具有一至的结构.错误码和错误消息也可以让客户端快速识别和处理错误.在实际应⽤中,CommonResultT作为控制器层⽅法的返回类型,可以被Springboot框架等⾃动转换为JSON或其他格式的响应体,发送给客⼾端,这种⽅式提⾼了API的可⽤性和可维护性.序列化工具序列化工具本次使用的是Jackson,序列化工具的使用场景例如在日志打映的时候,将传入的JSON字符转为字符串.我们自己实现的工具类中,也是参考了SpringBoot中源码的设计思路.当我们调用parseMap时,就会调用tryparse来传入表示序列化的lamda表达式,而在t方法中,又调用了call方法,相当于执行那一段lamda表达式,此时又会捕捉异常,这样的做法可以防止每一次调用序列化时都需要捕捉异常,是一种很巧妙的做法.日志处理日志处理采用的是SLF4Jlogback的处理机制,在本地测试时会将日志打映在控制台上,而在运行环境下又会分文件处理.此处提供配置文件:application文件配置和新增的logback.xmllogging.configclasspath:logback-spring.xml spring.profiles.activedev?xml version1.0 encodingUTF-8? configuration scantrue scanPeriod60 seconds debugfalse springProfile namedev !--输出到控制台-- appender nameconsole classch.qos.logback.core.ConsoleAppender encoder pattern%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n%ex/pattern /encoder /appender root levelinfo appender-ref refconsole / /root /springProfile springProfile nameprod,test !--ERROR级别的日志放在logErrorDir目录下INFO级别的日志放在logInfoDir目录下-- property namelogback.logErrorDir value/root/lottery-system/logs/error/ property namelogback.logInfoDir value/root/lottery-system/logs/info/ property namelogback.appName valuelotterySystem/ contextName${logback.appName}/contextName !--ERROR级别的日志配置如下-- appender namefileErrorLog classch.qos.logback.core.rolling.RollingFileAppender !--日志名称如果没有File 属性那么只会使用FileNamePattern的文件路径规则 如果同时有File和FileNamePattern那么当天日志是File明天会自动把今天 的日志改名为今天的日期。即File 的日志都是当天的。 -- File${logback.logErrorDir}/error.log/File !-- 日志level过滤器保证error.***.log中只记录ERROR级别的日志-- filter classch.qos.logback.classic.filter.LevelFilter levelERROR/level onMatchACCEPT/onMatch onMismatchDENY/onMismatch /filter !--滚动策略按照时间滚动 TimeBasedRollingPolicy-- rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy !--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-- FileNamePattern${logback.logErrorDir}/error.%d{yyyy-MM-dd}.log/FileNamePattern !--只保留最近14天的日志-- maxHistory14/maxHistory !--用来指定日志文件的上限大小那么到了这个值就会删除旧的日志-- !--totalSizeCap1GB/totalSizeCap-- /rollingPolicy !--日志输出编码格式化-- encoder charsetUTF-8/charset pattern%d [%thread] %-5level %logger{36} %line - %msg%n%ex/pattern /encoder /appender !--INFO级别的日志配置如下-- appender namefileInfoLog classch.qos.logback.core.rolling.RollingFileAppender !--日志名称如果没有File 属性那么只会使用FileNamePattern的文件路径规则 如果同时有File和FileNamePattern那么当天日志是File明天会自动把今天 的日志改名为今天的日期。即File 的日志都是当天的。 -- File${logback.logInfoDir}/info.log/File !--自定义过滤器保证info.***.log中只打印INFO级别的日志, 填写全限定路径-- filter classcom.example.lotterysystem.common.filter/ !--滚动策略按照时间滚动 TimeBasedRollingPolicy-- rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy !--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-- FileNamePattern${logback.logInfoDir}/info.%d{yyyy-MM-dd}.log/FileNamePattern !--只保留最近14天的日志-- maxHistory14/maxHistory !--用来指定日志文件的上限大小那么到了这个值就会删除旧的日志-- !--totalSizeCap1GB/totalSizeCap-- /rollingPolicy !--日志输出编码格式化-- encoder charsetUTF-8/charset pattern%d [%thread] %-5level %logger{36} %line - %msg%n%ex/pattern /encoder /appender root levelinfo appender-ref reffileErrorLog / appender-ref reffileInfoLog/ /root /springProfile /configuration
返回列表