基于SpringBoot的合家云社区物业管理平台 - 项目介绍

合家云社区物业管理平台

2.合家云需求&设计

2.1 项目概述

2.1.1 项目介绍

合家云社区物业管理平台是一个全新的 ”智慧物业解决方案“,是一款互联网+的专业社区物业管理系统。平台通过社区资产管理、小区管理、访客管理、在线报修、意见投诉等多种功能模块,来全面提升社区工作人员的工作效率和客户服务质量,主要致力于构建一个为社区居民更好服务的优质互联网平台。

image.png

2.1.2 主要模块介绍

1)系统管理模块

  • 该模块包括了用户权限的管理、部门以及岗位的管理、还有字典数据和日志数据的管理。

2)系统监控模块

  • 该模块可以获取当前系统用户信息、服务器状态、JVM相关参数等等。

3)社区资产模块

  • 该模块主要管理社区内的相关资产信息,包括小区信息、楼栋信息、单元信息以及具体的房屋信息。

4)小区管理

  • 该模块主要负责管理业主相关信息和业主的审核信息。

5)互动信息模块

  • 管理社区论坛内居民发送的互动信息。

2.2 需求分析

  • 详见具体功能开发

2.3 系统设计

2.3.1 前后端分离

2.3.1.1 前后端分离架构介绍

前后端分离已成为互联网项目开发的业界标准使用方式,将前端和后端的开发进行解耦。并且前后端分离会为以后的大型分布式架构、微服务架构、多端化服务(各种客户端,比如浏览器、车载终端、安卓、IOS等)打下坚实的基础。

前后端分离的核心思想就是前端HTML页面通过AJAX调用后端的API接口,并通过JSON数据进行交互。

image.png

2.3.1.2 前后端分离的优势

1)前后端耦合的开发方式

  • 这种方式中 Java程序员又当爹又当妈,又搞前端,又搞后端。 正所谓术业有专攻,一个人如果什么都会,那么他肯定也什么都不精.

image.png

2)前后端耦合的缺陷 (以JSP为例)

  1. UI出好设计图之后,前端开发工程师只负责将设计图切成HTML,需要由Java开发工程师来将HTML套成JSP页面,修改问题的时候需要双方协同开发,效率低下。
  2. JSP页面必须要在支持Java的WEB服务器上运行(如Tomcat、Jetty等),无法使用Nginx等(官方宣称单实例HTTP并发高达5W),性能提升不上来。
  3. 第一次请求JSP,必须要在WEB服务器中编译成Servlet,第一次运行会较慢。 之后的每次请求JSP都是访问Servlet再用输出流输出的HTML页面,效率没有直接使用HTML高

3)前后端分离的开发方式

image.png

4)前后端分离的优势

  1. 前后端分离的模式下,如果发现Bug,可以快速定位是谁的问题,不会出现互相踢皮球的现象
  2. 前后端分离可以减少后端服务器的并发/负载压力。除了接口以外的其他所有HTTP请求全部转移到前端Nginx上,接口的请求则转发调用Tomcat.
  3. 前后端分离的模式下,即使后端服务器暂时超时或宕机了,前端页面也会正常访问,只不过数据刷不出来而已。
  4. 前后端分离会更加合理的分配团队的工作量,减轻后端团队的工作量,提高了性能和可扩展性。
2.3.1.3 接口文档介绍

1)什么是接口文档?

在我们的项目中使用的是前后端分离开发方式,需要由前后端工程师共同定义接口,编写接口文档,之后大家都根据这个接口文档进行开发,到项目结束前都要一直进行接口文档的维护。

2)为什么要写接口文档?

  1. 项目开发过程中前后端工程师有一个统一的文件进行沟通交流,并行开发
  2. 项目维护中或者项目人员更迭,方便后期人员查看、维护

3)接口规范是什么?

  • 接口地址: http://localhost/hejiayun/community/list?pageNum=1&pageSize=10&communityName=&communityCode=COMMUNITY_1675945745985
  • 请求方式: GET
  • 接口描述: 获取小区信息
  • 请求参数说明
参数名称参数说明是否必须
pageNum当前页是
pageSize每页显示条数是
communityCode小区编码否
communityName小区名称否
  • 响应结果说明
字段名称字段说明是否必须
code状态码是
msg查询成功/查询失败是
total总条数是
rows小区数据信息集合是
  • 响应结果示例:
{"total": 1,"rows": [{"searchValue": null,"createBy": "admin","createTime": "2023-02-09 20:29:06","updateBy": "admin","updateTime": "2023-02-09 20:29:06","remark": null,"params": {},"communityId": "1623660256618201090","communityName": "宏福苑小区","communityCode": "COMMUNITY_1675945745985","communityProvenceCode": "1","communityProvenceName": "北京市","communityCityCode": "10","communityCityName": "北京市","communityTownCode": "1010","communityTownName": "昌平区","communityDetailedAddress": "北京市昌平区宏福苑","communityLongitude": null,"communityLatitude": null,"deptId": 103,"communitySort": null}],"code": 200,"msg": "查询成功"
}

2.3.2 技术选型&数据库设计

2.3.2.1 前端技术选型
前端技术说明
vue-cliVue 的脚手架工具,用于自动生成 Vue 项目的目录及文件。
Element UI库element-ui 是饿了么前端出品的基于 Vue.js的 后台组件库, 方便程序员进行页面快速布局和构建
node.js简单的说 Node.js 就是运行在服务端的 JavaScript 运行环境 .
axios对ajax的封装, 简单来说就是ajax技术实现了局部数据的刷新,axios实现了对ajax的封装,
2.3.2.2 后端技术选型
后端技术说明
SpringBootSpring Boot 是一款开箱即用框架,提供各种默认配置来简化项目配置。让我们 的
Spring 应用变的更轻量化、更快的入门。
Spring SecuritySpring Security 是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问
控制解决方案的安全框架。
MyBatis-plusmybatis-plus是一款Mybatis增强工具,用于简化开发,提高效率。
Redis使用Redis进行数据缓存

2.3.3 数据库设计

  • 详见数据库设计文档。
  • 执行数据库创建脚本,SQL脚本见项目资料。

3.5 后台系统搭建

在创建项目之前首先创建数据库、表。直接导入提供的数据库脚本即可。

image.png

3.5.1 创建SpringBoot项目

1)创建一个空的项目

image.png

image.png

image.png

2)在当前空项目下,创建一个module,选择Spring Initializr

image.png

Spring Initializr是一个Web应用,它提供了一个基本的项目结构,能够帮助我们快速构建一个基础的Spring Boot项目 .

  • Project SDK”用于设置创建项目使用的JDK版本,这里,使用之前初始化设置好的JDK版本即可;
  • 在“Choose Initializr Service URL(选择初始化服务地址)”下使用默认的初始化服务地址“https://start.spring.io”进行Spring Boot项目创建.

image.png

3)指定坐标、打包方式、版本等信息

image.png

4)选择springboot版本,以及要添加的依赖.

image.png

注意: 创建时不要选错路径!

image.png

提示: 如果使用IDEA快速构建SpringBoot项目,就必须要联网. 所谓的快速构建指的是在开发工具执行各项参数后,有Spring提供的URL所对应的服务器生成.

IDEA会将服务器生成的SpringBoot项目下载到本地工作空间中.

3.5.2 编写相关配置文件

1)pom.xml
<?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>2.7.8</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.msb</groupId><artifactId>hjy-community</artifactId><version>0.0.1-SNAPSHOT</version><name>hjy-community</name><packaging>jar</packaging><description>合家云社区物业管理平台</description><properties><java.version>11</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven-jar-plugin.version>3.1.1</maven-jar-plugin.version><druid.version>1.2.2</druid.version><bitwalker.version>1.21</bitwalker.version><swagger.version>2.9.2</swagger.version><kaptcha.version>2.3.2</kaptcha.version><pagehelper.boot.version>1.4.1</pagehelper.boot.version><fastjson.version>1.2.74</fastjson.version><oshi.version>5.3.6</oshi.version><jna.version>5.6.0</jna.version><commons.io.version>2.5</commons.io.version><commons.fileupload.version>1.3.3</commons.fileupload.version><poi.version>4.1.2</poi.version><velocity.version>1.7</velocity.version><jwt.version>0.9.1</jwt.version></properties><dependencies><!--阿里数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version></dependency><!-- 解析客户端操作系统、浏览器等 --><dependency><groupId>eu.bitwalker</groupId><artifactId>UserAgentUtils</artifactId><version>${bitwalker.version}</version></dependency><!-- servlet包 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId></dependency><!-- SpringBoot Web容器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- pagehelper 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pagehelper.boot.version}</version></dependency><!-- SpringBoot 拦截器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- 获取系统信息 --><dependency><groupId>com.github.oshi</groupId><artifactId>oshi-core</artifactId><version>${oshi.version}</version></dependency><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>${jna.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna-platform</artifactId><version>${jna.version}</version></dependency><!-- pool 对象池 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!-- redis 缓存操作 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><!--暂时使用jedis来进行操作redis,lettuce目前缺失心跳处理--><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency><!--io常用工具类 --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>${commons.io.version}</version></dependency><!--文件上传工具类 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>${commons.fileupload.version}</version></dependency><!-- excel工具 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>${poi.version}</version></dependency><!--velocity代码生成使用模板 --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity</artifactId><version>${velocity.version}</version></dependency><!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency><!--Token生成与解析--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>${jwt.version}</version></dependency><!--验证码 --><dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>${kaptcha.version}</version><exclusions><exclusion><artifactId>javax.servlet-api</artifactId><groupId>javax.servlet</groupId></exclusion></exclusions></dependency><!-- 自定义验证码 --><dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version></dependency><!-- spring-boot-devtools --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> <!-- 表示依赖不会传递 --></dependency><!-- Mysql驱动包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.32</version></dependency><!-- Spring框架基本的核心工具 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!-- SpringWeb模块 --><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId></dependency><!-- spring security 安全认证 -->
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-security</artifactId>-->
<!--        </dependency>--><!-- 自定义验证注解 --><dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId></dependency><!--常用工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><!-- JSON工具类 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- yml解析器 --><dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
2)application.yml
# 项目相关配置
hjy-community:# 名称name: hjy-community# 版本version: 1.0.0# 开发环境配置
server:#服务器的HTTP端口port: 8888servlet:# 应用的访问路径context-path: /tomcat:# tomcat的URI编码uri-encoding: UTF-8# tomcat最大线程数,默认为200max-threads: 800# Tomcat启动初始化的线程数,默认值25min-spare-threads: 30# 日志配置
logging:level:com.msb: debugorg.springframework: warn# Spring配置
spring:# 资源信息messages:# 国际化资源文件路径basename: i18n/messagesprofiles:active: druid# MyBatis配置# PageHelper分页插件
pagehelper:#数据库类型helperDialect: mysql #查询合理化 当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页reasonable: true # 自动分页的配置,依据的是入参,如果参数中有pageNum,pageSize分页参数,则会自动分页supportMethodsArguments: true# params:为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值params: count=countSql## mybatis-plus配置
mybatis-plus:## plus的实体别名包,不需要写出实体类的完整路径,只需要写出类名即可type-aliases-package: com.msb.hjycommunity.**.domain## mybatis  mapper.xml的位置mapper-locations: classpath:mapper/**/*Mapper.xml## mybatis  config的配置文件位置config-location: classpath:mybatis/mybatis-config.xml## 全局配置global-config:db-config:## id生成策略为雪花idid-type: assign_id## 不启用mybatis-plus的bannerbanner: false

1)helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect属性来指定分页插件使用哪种方言。

2)reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页,pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。

3)supportMethodsArguments:支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。

4)params:为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero。

3)application-druid.yml
# 数据源配置
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/hejiayun_community?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: 123456#druid 数据源专有配置druid:# 初始连接数initialSize: 5# 最小连接池数量minIdle: 10# 最大连接池数量maxActive: 20# 配置获取连接等待超时的时间maxWait: 50000# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒timeBetweenEvictionRunsMillis: 60000# 配置一个连接在池中最小生存的时间,单位是毫秒minEvictableIdleTimeMillis: 300000# 配置一个连接在池中最大生存的时间,单位是毫秒maxEvictableIdleTimeMillis: 900000# 配置检测连接是否有效validationQuery: SELECT 1 FROM DUAL#申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。testWhileIdle: true#配置从连接池获取连接时,是否检查连接有效性,true每次都检查;false不检查。做了这个配置会降低性能。testOnBorrow: false#配置向连接池归还连接时,是否检查连接有效性,true每次都检查;false不检查。做了这个配置会降低性能。testOnReturn: false#采集web-jdbc关联监控的数据。webStatFilter:enabled: true# Druid内置提供了一个StatViewServlet用于展示Druid的统计信息。statViewServlet:enabled: true# 设置白名单,不填则允许所有访问allow:url-pattern: /druid/*# 控制台管理用户名和密码login-username:login-password:#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入filter:stat:enabled: true# 慢SQL记录log-slow-sql: trueslow-sql-millis: 1000merge-sql: truewall:config:multi-statement-allow: true
3)mybatis-config.xml

mybatis核心配置文件,在resources目录下创建mybatis目录,在mybatis目录下创建该文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><setting name="useGeneratedKeys"         value="true" />  <!-- 允许 JDBC 支持自动生成主键 --><setting name="logImpl"                  value="STDOUT_LOGGING" /> <!-- 指定 MyBatis 所用日志的具体实现 --></settings></configuration>
4)logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!-- 日志存放路径 --><property name="log.path" value="/home/hejiayun/logs" /><!-- 日志输出格式 --><property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统日志输出 --><appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-info.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>INFO</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-error.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>ERROR</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><!-- 用户访问日志输出  --><appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-user.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天回滚 daily --><fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统模块日志级别控制  --><logger name="com.msb" level="info" /><!-- Spring日志级别控制  --><logger name="org.springframework" level="warn" /><root level="info"><appender-ref ref="console" /></root><!--系统操作日志--><root level="info"><appender-ref ref="file_info" /><appender-ref ref="file_error" /></root><!--系统用户操作日志--><logger name="sys-user" level="info"><appender-ref ref="sys-user"/></logger>
</configuration>

3.5.3 创建包结构&Entity基类

3.5.3.1 项目包结构
com.msb.hjycommunity
|———— common		//通用工具
|———— framework		//核心框架
|———— community 	//后台服务
|———— system		//系统管理
|———— web		//后台接口
3.5.3.2 创建Entity基类

在搭建的后端应用中,我们使用了 mybatis-plus 框架作为扩展,减少 sql 的书写,提升开发效率,其中有个功能很好用,就是自动填充。在项目中,我们的后台表一般会具有一些标准字段,作为强制建表规范,比如:

  • create_by 创建者
  • creation_date 创建时间
  • last_updated_by 最后更新者
  • last_update_date 最后更新时间

这些字段我们会放到 Entity类中,作为其他 Entity的超类,这样就不用重复定义了,但是有个问题,在每次修改数据时,都需要给这几个字段赋值,这显然就有点繁琐了,如果能系统自动读取相关值并填充就能省略很多代码,mybatis plus 的自动填充正是一个这样的功能。

我们在 com.msb.hjycommunity.common.core.domain 包下,创建这个Entity基类

package com.msb.hjycommunity.common.core.domain;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;import java.io.Serializable;
import java.util.Date;
import java.util.Map;/*** Entity 基类* @author spikeCong* @date 2023/2/23**/
public class BaseEntity implements Serializable {private static final long serialVersionUID = 1L;/*** 搜索值* @TableField(exist = false)注解加载bean属性上,表示当前属性不是数据库的字段,* 但在项目中必须使用,这样在新增等使用bean的时候,mybatis-plus就会忽略这个,不会报错*/@TableField(exist = false)private String searchValue;/*** 创建者* fill 在需要被填充的字段上使用注解,声明什么时候要被填充* FieldFill.INSERT 只在插入时填充* FieldFill.INSERT_UPDATE 插入和更新时都填充*/@TableField(fill = FieldFill.INSERT)private String createBy;/** 创建时间 */@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@TableField(fill = FieldFill.INSERT)private Date createTime;/** 更新者 */@TableField(fill = FieldFill.INSERT)private String updateBy;/** 更新时间 */@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@TableField(fill = FieldFill.INSERT)private Date updateTime;/** 备注 */private String remark;/** 请求参数 */@TableField(exist = false)private Map<String, Object> params;//get/set ......
}

3.5.4 启动类添加@MapperScan注解

@SpringBootApplication
@MapperScan("com.msb.hjycommunity.**.mapper")
public class HjyCommunityApplication {public static void main(String[] args) {SpringApplication.run(HjyCommunityApplication.class, args);System.out.println("合家云后台系统启动成功!");}}

3.5.5 IDEA连接mysql数据库

3.6.1 连接步骤

1、在idea 中选项栏中找到view

2、在选项栏下拉框中选择 Tool Windows

3、在Tool Windows 右侧小三角出现的列表中找到 Database

image.png

上述步骤完成之后,会出现如下界面

image.png

4、选择Database 下面的 + 号

5、选择Data Source

6、选择 MySQL

image.png

上述步骤完成之后,会出现如下界面

image.png

3.6.2 连接测试

1.点击Test Connection

image.png

2.当然第一次进入这页面的时候,Test Connection 这个按钮是灰色的,因为没有响应的驱动文件,这时就需要下载驱动文件,具体如图所示

image.png

3.连接成功, 显示要使用的数据库,可以自主选择

image.png

3.6.3 时区问题解决

如果出现MySQL时区问题: Server returns invalid timezone. Go to ‘Advanced‘ tab and set ‘serverTimezon

1.输入 show variables like'%time_zone'; 回车,显示时区配置如果显示 SYSTEM 就是没有设置时区2.输入 set global time_zone = '+8:00'; 回车显示Query OK, 0 rows affected (0.00 sec)就是设置成功了。3.然后关闭cmd重新打开cmd重新连接数据库,连接成功后输入show variables like'%time_zone'; 回车

image.png

3.5.6 idea自动生成代码插件EasyCode
3.6.1 安装插件
  1. 在idea的plugins搜索 Easy Code

image.png

安装之后重启idea。

2.5.2 插件配置
  1. 打开 Setting

  2. 选择 Other Setting – Easy Code,初始页可以设置代码作者,也可以导入导出模板

    image.png

  3. 设置数据库数据类型对应java类型

    image.png

  4. 创建一个maven项目

    image.png

  5. 选中一张表,右键 选择EasyCode,生成代码

    image.png

  6. 选择需要生成的代码类型,填写包名,点击确定

    image.png

  7. 生成的代码

    image.png

3.6 后端接口开发的统一规范

日常工作中,我们开发接口时,一般都会涉及到参数校验、异常处理、封装结果返回等处理。

如果每个后端开发在参数校验、异常处理等都是各写各的,没有统一处理的话,代码就不优雅,也不容易维护。所以,作为一名合格的后端开发工程师,我们需要统一校验参数,统一异常处理、统一结果返回,让代码更加规范、可读性更强、更容易维护。

3.6.1 接口统一响应对象返回

作为后端开发,我们项目的响应结果,需要统一标准的返回格式。一般一个标准的响应报文对象,有一下几个属性

  • code :响应状态码
  • message :响应结果描述
  • data:返回的数据

1)响应状态码一般用枚举表示:

包结构: com.msb.hjycommunity.common.core.domain.ResultCode

/*** 响应状态码* @author spikeCong* @date 2023/2/28**/
public enum ResultCode {/**操作成功**/SUCCESS("200","操作成功"),/**操作失败**/ERROR("500","操作失败"),;/*** 自定义状态码**/private String code;/**自定义描述**/private String message;ResultCode(String code, String message) {this.code = code;this.message = message;}public String getCode() {return code;}public String getMessage() {return message;}
}

2)因为返回的数据类型不是确定的,我们可以使用泛型,如下:

包结构:com.msb.hjycommunity.common.core.domain.BaseResponse

/*** 响应结果封装对象* @author spikeCong* @date 2023/3/1**/
public class BaseResponse<T> implements Serializable {private static final long serialVersionUID = 1901152752394073986L;/*** 响应状态码*/private String code;/*** 响应结果描述*/private String message;/*** 返回的数据*/private T data;/*** 成功返回* @param data* @return: com.msb.hjycommunity.common.core.domain.BaseResponse<T>*/public static <T> BaseResponse<T> success(T data){BaseResponse<T> response = new BaseResponse<>();response.setCode(ResultCode.SUCCESS.getCode());response.setMessage(ResultCode.SUCCESS.getMessage());response.setData(data);return response;}/*** 失败返回* @param message* @return: com.msb.hjycommunity.common.core.domain.BaseResponse<T>*/public static <T> BaseResponse<T> fail(String message){BaseResponse<T> response = new BaseResponse<>();response.setCode(ResultCode.ERROR.getCode());response.setMessage(message);return response;}/*** 失败返回* @param message* @return: com.msb.hjycommunity.common.core.domain.BaseResponse<T>*/public static <T> BaseResponse<T> fail(String code, String message){BaseResponse<T> response = new BaseResponse<>();response.setCode(code);response.setMessage(message);return response;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}
}

3)测试

  • 创建user实体类
public class User {private String userId;private String username;public User() {}public User(String userId, String username) {this.userId = userId;this.username = username;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}
}
  • 创建UserController
@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/queryUserById")public BaseResponse<User> queryUserById(String userId){if(userId != null){return BaseResponse.success(new User(userId,"spike"));}else{return BaseResponse.fail("查询用户信息失败!");}}
}
  • 测试
http://localhost:8888/user/queryUserById?userId=1//output
{"code": "200","message": "操作成功","data": {"userId": "1","username": "tom"}
}http://localhost:8888/user/queryUserById//output
{"code": "500","message": "查询用户信息失败!","data": null
}

3.6.2 使用注解,统一参数校验

我们在实际的开发过程中经常会遇到需要对参数进行校验的情况,比如在需要用户输入手机号的时候他是不是真的输入了一个合法的手机号,在需要用户输入一个邮箱的时候他是不是真的输入了一个合法的邮箱,用户输入的内容是不是超出了长度限制等等。

当一个表单的数据较多的时候,单纯的数据校验代码就会占到很大的幅度,所以简化基础数据的校验可以省去我们很多的工作,让我们能更专注于功能的实现。

接下来我们一起看一下 springboot中参数校验(validation)的使用,首先导入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Validator可以非常方便的制定校验规则,并自动帮你完成校验。首先在入参里需要校验的字段加上注解,每个注解对应不同的校验规则,并可制定校验失败后的信息:

public class User {private String userId;@NotNull(message = "username 不能为空")private String username;
}

校验规则和错误提示信息配置完毕后,接下来只需要在接口需要校验的参数上加上@Validated注解,并添加BindResult参数即可方便完成验证:

@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/addUser")public BaseResponse addUser(@Validated User user, BindingResult bindingResult){List<FieldError> fieldErrors = bindingResult.getFieldErrors();//如果参数校验失败,会将错误信息封装成对象组装在 BindingResultif(!fieldErrors.isEmpty()){return BaseResponse.fail(fieldErrors.get(0).getDefaultMessage());}return BaseResponse.success("OK");}
}

测试

http://localhost:8888/user/addUser?username="tom"{"code": "500","message": "userId 不能为空","data": null
}http://localhost:8888/user/addUser?username="tom"&userId=1{"code": "200","message": "操作成功","data": "OK"
}

内置的校验注解有很多,罗列如下:

image.png

3.6.3 统一异常处理

日常开发中,我们一般都是自定义统一的异常类

  • 自定义异常可以携带更多的信息。
  • 项目开发中经常是很多人负责不同的模块,使用自定义异常可以统一了对外异常展示的方式。
  • 自定义异常语义更加清晰明了,一看就知道是项目中手动抛出的异常。

自定义异常类, 所在包结构: com.msb.hjycommunity.common.core.exception.BaseException

/*** 基础异常* @author spikeCong* @date 2023/2/28**/
public class BaseException extends RuntimeException{/*** 错误码*/private String code;/*** 错误消息*/private String defaultMessage;public BaseException() {}public BaseException(String code, String defaultMessage) {this.code = code;this.defaultMessage = defaultMessage;}public String getCode() {return code;}public String getDefaultMessage() {return defaultMessage;}
}

在controller 层,我们来使用这个自定义异常:

@RequestMapping("/queryUser")
public BaseResponse queryUser(User user){//模拟查询失败抛出异常throw new BaseException("500","测试异常类!");
}

这块代码,没什么问题,但是如果在很多地方都抛出这个异常,我们处理起来就会比较麻烦。

这时我们可以借助注解@RestControllerAdvice,让代码更优雅。@RestControllerAdvice是一个应用于Controller层的切面注解,它一般配合@ExceptionHandler注解一起使用,作为项目的全局异常处理。示例代码如下:

/*** 全局异常处理器* @author spikeCong* @date 2023/2/28**/
@RestControllerAdvice
public class GlobalExceptionHandler {}

我们有想要拦截的异常类型,比如想拦截BaseException类型,就新增一个方法,使用@ExceptionHandler注解修饰,并指定你想处理的异常类型,接着在方法内编写对该异常的操作逻辑,就完成了对该异常的全局处理!

@RestControllerAdvice
public class GlobalExceptionHandler {/*** 基础异常* @param e* @return: com.msb.hjycommunity.common.core.domain.BaseResponse*/@ExceptionHandler(BaseException.class)@ResponseBodypublic BaseResponse baseExceptionHandler(BaseException e){return BaseResponse.fail(e.getDefaultMessage());}}

测试

http://localhost:8888/hejiayun/user/queryUser{"code": "500","message": "测试异常类!","data": null
}

3.6.4 总结

自此整个后端接口基本体系就构建完毕了

  • 通过Validation 完成了方便的参数校验
  • 通过全局异常处理 + 自定义异常完成了异常操作的规范
  • 通过数据统一响应完成了响应数据的规范
  • 多个方面组装非常优雅的完成了后端接口的协调,让开发人员有更多的经历注重业务逻辑代码,轻松构建后端接口。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

指针笔试题模拟

题目一 int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1);printf( "%d,%d", *(a 1), *(ptr - 1));return 0; } 1*&#xff08;a1&#xff09;可以等价于a[1],即第一个打印的是数组第二个下标的元素&#xff1a;2 2 而ptr拿到的是整个数组的地…

CentOS上如何自定义开机启动服务

一&#xff1a;简单的例子 在CentOS7之后自定义开机启动服务&#xff0c;可以通过创建一个systemd服务单元文件来实现。以下是创建自定义服务并设置其开机启动的步骤&#xff1a; 1&#xff0c;编辑服务文件&#xff0c;并添加以下内容&#xff1a; [Unit] DescriptionMy cu…

MySQL慢SQL优化技术深度学习指南

引言 在现代数据驱动的应用环境中&#xff0c;MySQL作为广泛应用的关系型数据库管理系统&#xff0c;其性能直接影响着整个系统的响应速度与用户体验。随着数据规模的增长和业务复杂性的提升&#xff0c;一些SQL查询可能会逐渐演变为慢查询&#xff0c;成为系统性能瓶颈。本文旨…

Ubuntu安装中文输入法

Ubuntu默认没有中文输入法&#xff0c; 本文将安装搜狗拼音输入法。 1 安装搜狗拼音输入法 下载安装搜狗拼音输入法&#xff1a; 先去官网下载安装包&#xff0c; 然后执行安装&#xff1a; sudo dpkg -i sogoupinyin_4.0.1.2800_x86_64.deb 2 安装fcitx sudo apt install fci…

SVM中常用的核函数及适用场景

常用的核函数 核函数&#xff08;Kernel functions&#xff09;在机器学习中尤其是在支持向量机&#xff08;SVM&#xff09;中扮演着重要的角色&#xff0c;它们能够将数据映射到高维空间&#xff0c;从而解决非线性问题。以下是一些常用的核函数及其适用场景&#xff1a; 线…

大模型的幻觉---探讨及解决之道

大模型「幻觉」背景 幻觉可以说早就已经是LLM老生常谈的问题了&#xff0c;那为什么会产生这个现象该如何解决这个问题呢&#xff1f;大模型幻觉产生的背景主要涉及人类视觉系统的特性和大规模机器学习模型的复杂性。以下是对大模型幻觉产生背景的详细说明和介绍&#xff1a; …

C语言之详细讲解文件操作

什么是文件 与普通文件载体不同&#xff0c;文件是以硬盘为载体存储在计算机上的信息集合&#xff0c;文件可以是文本文档、图片、程序等等。文件通常具有点三个字母的文件扩展名&#xff0c;用于指示文件类型&#xff08;例如&#xff0c;图片文件常常以KPEG格式保存并且文件…

第5篇:创建Nios II工程之Hello_World<四>

Q&#xff1a;最后我们在DE2-115开发板上演示运行Hello_World程序。 A&#xff1a;先烧录编译Quartus硬件工程时生成的.sof文件&#xff0c;在FPGA上成功配置Nios II系统&#xff1b;然后在Nios II Eclipse窗口右键点击工程名hello_world&#xff0c;选择Run As-->Nios II …

Go语言中,如何做到数据按类别分发给特定的协程处理

在 Go 语言中&#xff0c;如果你想按类别将数据分配给特定的协程&#xff08;goroutine&#xff09;进行处理&#xff0c;可以使用几种策略。下面我将提供一些方法和示例&#xff0c;说明如何根据数据类别将任务分配给不同的协程来处理。 使用通道&#xff08;Channel&#xf…

C#利用IDbCommand实现通用数据库脚本执行程序

目录 关于 ExecuteNonQuery 数据库脚本程序的执行流程 范例运行环境 通用类的设计 引用 DAL类 实现代码 小结 关于 ExecuteNonQuery 在.net 应用中&#xff0c;在数据库中执行脚本程序是经常用到的功能&#xff0c;如数据操作&#xff08;新增、修改、删除等&#xff0…

C语言趣味代码(四)

这一篇主要编写几个打字练习的小程序&#xff0c;然后通过这些小程序的实现来回顾复习我们之前学过的知识&#xff0c;然后通过这写打字练习的小程序来提升我们的打字技术和编程技术。 1. 打字练习 1.1 基本打字练习 1.1.1 基本实现 首先我们来制作一个用于计算并显示输入一…

github two-factor authentication是个啥?

最近在逛github时&#xff0c;总是时不时会弹出一下界面&#xff0c;很烦 看到红框里的文字&#xff0c;这明显是强制要求做这个认证&#xff0c;如果不认证4天后账号将不可访问&#xff0c;所以今天花点时间看看怎么做这个认证&#xff0c;点“Enable 2FA now”进入这个界面&a…

普通用户执行source报错,sudo: source:找不到命令的解决方案

一、问题描述 当修改/etc/profile文件&#xff08;环境变量&#xff09;后&#xff0c;想让该环境变量立刻生效。需要执行source命令。命令如下&#xff1a; sudo source /etc/profile 执行这个后&#xff0c;不像别人的执行成功&#xff0c;反而报错了。错误信息如下&#…

通配符模式

一、通配符介绍 通配符模式&#xff08;Wildcard Pattern&#xff09;是一种用于字符串匹配的通用模式规则&#xff0c;常见于文件系统、命令行工具以及编程语言中的文件路径匹配、配置筛选等场景。通配符模式是一种使用特殊字符来表示匹配规则的字符串语法&#xff0c;它允许…

linux下安装anaconda

顺手点个关注吧&#xff0c;谢谢&#xff01; 一、下载安装包 https://repo.anaconda.com/archive/ 或者使用命令 wget https://repo.anaconda.com/archive/Anaconda3-5.3.1-Linux-x86_64.sh2.赋予权限并安装 # 给文件执行权限 chmod 777 Anaconda3-5.3.1-Linux-x86_64.sh# 执…

商汤研究院招大模型实习生

商汤研究院招大模型实习生&#xff0c;base上海、北京&#xff0c;400/day。福利&#xff1a;每天50租房补贴&#xff0c;20的餐补。晚上8点之后回去有额外的25元晚餐餐补&#xff0c;10点之后回去可以免费用滴滴。 组内的大模型工作大概分两个方向&#xff1a; 1.3B、3B等小…

基于opencv的单目相机标定

openCv版本&#xff1a;4.4.0 从源码处拷贝标定代码出来使用&#xff0c;需要拷贝samples/cpp/tutorial_code/calib3d/camera_calibration 需要的文件如下&#xff1a; -rw-rw-r-- 1 rog rog 28490 Jul 18 2020 camera_calibration.cpp -rw-rw-r-- 1 rog rog 3152 Jul 18 …

判断前端入参是否空否则提示前端写法

vue2中 前端先声明一个变量&#xff0c;用于alert判断 在templeat中定义一个提示语句 然后在点击事件时判断一下是否展示

【Linux】NFS网络文件系统搭建

一、服务端配置 #软件包安装 [roothadoop01 ~]# yum install rpcbind nfs-utils.x86_64 -y [roothadoop01 ~]# mkdir /share#配置文件修改 #格式为 共享资源路径 [主机地址] [选项] # [roothadoop01 ~]# vi /etc/exports /share 192.168.10.0/24(rw,sync,no_root_squash) #…

ubuntu安装源问题

一、 清华大学开源软件镜像站 https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/ 二、 python镜像源 1、临时配置 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simplepip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U --trusted…