智能化校园:深入探讨云端管理系统设计与实现(一)

推荐阅读

轻松驾驭JDBC:一篇文章帮你搞定数据库连接
ChatGPT爆火一周年,快来拥有专属你的ChatGPT应用!


文章目录

  • 推荐阅读
  • 智慧校园云端管理系统的设计和实现
    • 项目简介
    • 项目技术栈
    • 项目功能
    • 项目开发
      • 项目搭建
        • 修改pom.xml文件
        • 项目包结构
        • 配置application.yml文件
          • Hikari
          • jackson
          • mybatis-plus
        • 配置类
          • 分页插件配置类
          • Swagger2的配置类
        • 工具类
          • 验证码图片生成类
          • JwtHelper
          • AuthContextHolder类
          • MD5加密类
          • 全局统一返回类
          • 返回状态结果响应类
          • 文件上传类
        • pojo和mapper类


image.png

智慧校园云端管理系统的设计和实现

项目简介

智慧校园云端管理系统主要用来管理校内学生、老师、班级、年级的相关信息,进行老师和学生信息记录和统计的功能,而这些信息是校园信息化建设的核心基础业务数据。
项目采用前后端分离架构思想,前端采用HTML+CSS+VUE来实现页面效果展示,后端采用SpringBoot+MybatisPlus框架实现数据存储等服务。存储层使用高性能的MySQL,服务器使用SpringBoot内置的Tomcat9.x,项目构建工具使用Maven来管理jar包和项目构建。

智慧校园指的是信息化为基础构建起来的校园信息化教育管理的一种新的模式,智慧校园能够实现校园工作,学习和生活的一体化发展,在各种信息系统应用的基础上,能实现教学,科研管理和校园生活的有效融合。智慧校园建设所包括的内容很丰富,通过云计算,互联网技术将校园运行中的所有数据有效的联系在一起,通过相关软件系统的有效应用,实现学校智能监控和智能识别的综合信息服务平台的有效构建。
智慧校园有三个基本特征,第一,智慧校园能够提供个性化的服务,通过智能化服务平台及智能感知功能,实现教育管理工作的个性化服务。第二,智慧校园是建立在互联网基础上的, 通过互联网实现信息服务与校园各种应用领域的结合。第三,智慧校园在个性化定制服务的基础上,能够为学校与外部世界的联系提供有效的平台和接口,促进学校资源与外部资源的有效融合。智慧校园是校园信息化的一种高级形式,通过智慧校园可以把学校的物理空间和数字空间结合起来,为师生学习生活,提供智能化的学习生活环境,为师生提供个性化的智能服务。

项目技术栈

image.png

项目功能

智慧校园云端管理系统的使用者主要包含三种用户角色,其一是管理员角色,其二是老师角色,其三是学生角色。这三个角色的具体功能如下:

  • 管理员角色:管理员登录智慧校园系统后可以进行相应的管理操作,主要包含:学生信息管理、老师信息管理、年级信息管理、班级信息管理、个人信息管理、账户密码重置等操作。
  • 老师用户角色:老师用户登录智慧校园系统后可以进行参与相关学生、班级信息管理的相关操作以及个人信息管理等操作。
  • 学生用户角色:学生进入系统后,主要查看自己的班级,同学信息以及个人信息管理等操作。

image.png

项目开发

项目搭建

使用idea的springboot脚手架搭建一个maven项目
1646278072789.png
项目创建完成后,更改一下maven的配置,改成自己的本地maven仓库。
image.png

修改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><!--继承方式 使用spring--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.13</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.project</groupId><artifactId>smart_campus</artifactId><version>0.0.1-SNAPSHOT</version><name>smart_campus</name><description>smart_campus</description><properties><java.version>11</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--单元测试启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- thymeleaf支持--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--  mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.1</version></dependency><!-- 依赖MyBatis核心包 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><!-- 简化POJO实体类开发 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.3.1</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version></dependency><!--swagger--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version></dependency><!--swagger ui--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.7.0</version></dependency><!--swagger2  增强版接口文档--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>2.0.4</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version></dependency><!--开发者工具--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.29</version></dependency><!-- JWT生成Token--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency></dependencies><build><plugins><!--spring boot maven插件 , 可以将项目运行依赖的jar包打到我们的项目中--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.0</version><!-- 插件的依赖 --><dependencies><!-- 逆向工程的核心依赖 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.2</version></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency></dependencies></plugin></plugins></build></project>

项目包结构
  1. java目录下
  • config : 项目的配置类
  • controller: 控制层
  • mapper : 持久层接口
  • pojo : 实体类
  • service: 服务层
  • util: 工具类包
  • SmartCampusApplication : 启动类
  1. resources目录下
  • mapper :持久层映射文件
  • public/upload:文件上传目录
  • static: 静态资源目录
  • application.yml :SpringBoot核心配置文

image.png

这里注意一下:public/upload
设置该目录时,如果为public.upload,那么在本地文件夹,并不会创建一个public下的新文件夹upload ,默认为该文件的文件名。
但是如果设置时,按照这种 public/upload 格式,虽然在目录中显示为public.upload (这是因为public目录下目前只有一个文件夹),但是实际上upload是public文件夹下的一个文件。

image.png

配置application.yml文件
server:port: 9000
spring:#解决SpringBoot2.6.0与swagger冲突问题【原因是在springboot2.6.0中将SpringMVC 默认路径匹配策略从AntPathMatcher 更改为PathPatternParser,导致出错,解决办法是切换回原先的AntPathMatcher】mvc:pathmatch:matching-strategy: ant_path_matcher#配置数据源datasource:#配置数据源类型type: com.zaxxer.hikari.HikariDataSource#配置数据库连接属性driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://......./sgg_zhxy_db?characterEncoding=utf-8&serverTimezone=GMT%2B8&userSSL=falseusername: rootpassword: root#mybatis-plus内置连接池hikari:connection-test-query: SELECT 1connection-timeout: 60000idle-timeout: 500000max-lifetime: 540000maximum-pool-size: 12minimum-idle: 10pool-name: GuliHikariPoolthymeleaf:#模板的模式,支持 HTML, XML TEXT JAVASCRIPTmode: HTML5#编码 可不用配置encoding: UTF-8#开发配置为false,避免修改模板还要重启服务器cache: false#配置模板路径,默认是templates,可以不用配置prefix: classpath:/static/jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8servlet:#设置文件上传上限multipart:max-file-size: 10MBmax-request-size: 100MB
mybatis-plus:configuration:#添加日志支持log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath*:/mapper/**/*.xml

Hikari

hikari使用

<dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>5.0.0</version>
</dependency>

初始化

HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("123456");

基于配置文件的初始化

HikariConfig config = new HikariConfig("/../hikari.properties");
HikariDataSource ds = new HikariDataSource(config);// properties file
dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=test
dataSource.password=test
dataSource.databaseName=mydb
dataSource.portNumber=5432
dataSource.serverName=localhost

常用参数

    hikari:connection-test-query: SELECT 1connection-timeout: 60000idle-timeout: 500000max-lifetime: 540000maximum-pool-size: 12minimum-idle: 10pool-name: GuliHikariPool

根据 less is more 的设计哲学,以 Hikari 开头的配置都是可选的配置,都有默认的值,不配也行的。

name描述构造器默认值默认配置validate之后的值validate重置
autoCommit自动提交从池中返回的连接truetrue-
connectionTimeout等待来自池的连接的最大毫秒数SECONDS.toMillis(30) = 3000030000如果小于250毫秒,则被重置回30秒
idleTimeout连接允许在池中闲置的最长时间MINUTES.toMillis(10) = 600000600000如果idleTimeout+1秒>maxLifetime 且 maxLifetime>0,则会被重置为0(代表永远不会退出);如果idleTimeout!=0且小于10秒,则会被重置为10秒
maxLifetime池中连接最长生命周期MINUTES.toMillis(30) = 18000001800000如果不等于0且小于30秒则会被重置回30分钟
connectionTestQuery如果您的驱动程序支持JDBC4,我们强烈建议您不要设置此属性nullnull-
minimumIdle池中维护的最小空闲连接数-110minIdle<0或者minIdle>maxPoolSize,则被重置为maxPoolSize
maximumPoolSize池中最大连接数,包括闲置和使用中的连接-110如果maxPoolSize小于1,则会被重置。当minIdle<=0被重置为DEFAULT_POOL_SIZE则为10;如果minIdle>0则重置为minIdle的值
metricRegistry该属性允许您指定一个 Codahale / Dropwizard MetricRegistry 的实例,供池使用以记录各种指标nullnull-
healthCheckRegistry该属性允许您指定池使用的Codahale / Dropwizard HealthCheckRegistry的实例来报告当前健康信息nullnull-
poolName连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置nullHikariPool-1-
initializationFailTimeout如果池无法成功初始化连接,则此属性控制池是否将 fail fast11-
isolateInternalQueries是否在其自己的事务中隔离内部池查询,例如连接活动测试falsefalse-
allowPoolSuspension控制池是否可以通过JMX暂停和恢复falsefalse-
readOnly从池中获取的连接是否默认处于只读模式falsefalse-
registerMbeans是否注册JMX管理Bean(MBeans)falsefalse-
catalog为支持 catalog 概念的数据库设置默认 catalogdriver defaultnull-
connectionInitSql该属性设置一个SQL语句,在将每个新连接创建后,将其添加到池中之前执行该语句。nullnull-
driverClassNameHikariCP将尝试通过仅基于jdbcUrl的DriverManager解析驱动程序,但对于一些较旧的驱动程序,还必须指定driverClassNamenullnull-
transactionIsolation控制从池返回的连接的默认事务隔离级别nullnull-
validationTimeout连接将被测试活动的最大时间量SECONDS.toMillis(5) = 50005000如果小于250毫秒,则会被重置回5秒
leakDetectionThreshold记录消息之前连接可能离开池的时间量,表示可能的连接泄漏00如果大于0且不是单元测试,则进一步判断:(leakDetectionThreshold < SECONDS.toMillis(2) or (leakDetectionThreshold > maxLifetime && maxLifetime > 0),会被重置为0 . 即如果要生效则必须>0,而且不能小于2秒,而且当maxLifetime > 0时不能大于maxLifetime
dataSource这个属性允许你直接设置数据源的实例被池包装,而不是让HikariCP通过反射来构造它nullnull-
schema该属性为支持模式概念的数据库设置默认模式driver defaultnull-
threadFactory此属性允许您设置将用于创建池使用的所有线程的java.util.concurrent.ThreadFactory的实例。nullnull-
scheduledExecutor此属性允许您设置将用于各种内部计划任务的java.util.concurrent.ScheduledExecutorService实例nullnull-

jackson

Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架.
优点:

  • Jackson 解析大的 json 文件速度比较快;
  • Jackson 运行时占用内存比较低,性能比较好;
  • Jackson 有灵活的 API,可以很容易进行扩展和定制。
    <!-- springboot-json --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></dependency>

按照这种格式去解析日期和时区

  jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8

mybatis-plus
mybatis-plus:configuration:#添加日志支持log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath*:/mapper/**/*.xml

mapper-locations: classpath*:/mapper/**/*.xml
设置映射文件位置:
image.png

配置类

分页插件配置类
@Configuration
@MapperScan("com.project.smart_campus.mapper")
public class MyConfig {/** 分页插件* */@Beanpublic PaginationInterceptor paginationInterceptor(){PaginationInterceptor paginationInterceptor=new PaginationInterceptor();return paginationInterceptor;}}

Swagger2的配置类

引入依赖

<!--swagger-->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version>
</dependency>
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.7.0</version>
</dependency>

配置类

@Configuration
@EnableSwagger2
public class Swagger2Config {@Beanpublic Docket webApiConfig(){//添加head参数startList<Parameter> parameters=new ArrayList<>();ParameterBuilder tokenPar=new ParameterBuilder();tokenPar.name("userId").description("测试用户1").defaultValue("1").modelRef(new ModelRef("string")).parameterType("header").required(false).build();parameters.add(tokenPar.build());ParameterBuilder tmpPar = new ParameterBuilder();tmpPar.name("userTempId").description("测试用户2").defaultValue("1").modelRef(new ModelRef("string")).parameterType("header").required(false).build();parameters.add(tmpPar.build());//添加head参数endreturn new Docket(DocumentationType.SWAGGER_2).groupName("webApi").apiInfo(webApiInfo()).select()//可以测试请求头中:输入token//.apis(RequestHandlerSelectors.withClassAnnotation(ApiOperation.class)).apis(RequestHandlerSelectors.basePackage("com.project.smart_campus.controller"))//过滤掉admin路径下的所有页面//.paths(Predicates.and(PathSelectors.regex("/sms/.*")))//过滤掉所有error或error.*页面//.paths(Predicates.not(PathSelectors.regex("/error.*"))).build().globalOperationParameters(parameters);}private ApiInfo webApiInfo(){return new ApiInfoBuilder().title("网站-API文档").description("本文档描述了网站微服务接口定义").version("1.0").contact(new Contact("sc", "http://mypoject.com", "123456@qq.com")).build();}private ApiInfo adminApiInfo(){return new ApiInfoBuilder().title("后台管理系统-API文档").description("本文档描述了后台管理系统微服务接口定义").version("1.0").contact(new Contact("sc", "http://mypoject.com", "123456@qq.com")).build();}}

常用配置参数表
image.png
swagger常用注解表
image.png
Swagger2 常用注解@ApiOperation@ApiParam
@ApiOperation(使用于在方法上,表示一个http请求的操作)

  • value用于方法描述
  • notes用于提示内容
  • tags可以重新分组(视情况而用)

@ApiParam
使用在方法上或者参数上,字段说明;表示对参数的添加元数据(说明或是否必填等)

  • name–参数名
  • value–参数说明
  • required–是否必填

学生管理系统接口文档示例:
image.png

工具类

验证码图片生成类

先定义验证码图片的基本属性,随后是验证码图片(获取)+验证码(生成+获取+绘制)

public class CreateVerifiCodeImage {/** 定义长宽,字符大小,验证码,验证码图片* */private static int WIDTH = 90;private static int HEIGHT = 35;private static int FONT_SIZE = 20;private static char[] verifiCode;private static BufferedImage verifiCodeImage;/*** @description: 获取验证码图片* @param: no* @return: java.awt.image.BufferedImage*/public static BufferedImage getVerifiCodeImage() {verifiCodeImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_BGR);// create a imageGraphics graphics = verifiCodeImage.getGraphics();verifiCode = generateCheckCode();drawBackground(graphics);drawRands(graphics, verifiCode);graphics.dispose();return verifiCodeImage;}/*** @description: 获取验证码* @param: no* @return: char[]*/public static char[] getVerifiCode() {return verifiCode;}/*** @description: 随机生成验证码* @param: no* @return: char[]*/private static char[] generateCheckCode() {String chars = "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ";char[] rands = new char[4];for (int i = 0; i < 4; i++) {int rand = (int) (Math.random() * (10 + 26 * 2));rands[i] = chars.charAt(rand);}return rands;}/*** @description: 绘制验证码* @param: g* @param: rands* @return: void*/private static void drawRands(Graphics g, char[] rands) {g.setFont(new Font("Console", Font.BOLD, FONT_SIZE));for (int i = 0; i < rands.length; i++) {g.setColor(getRandomColor());g.drawString("" + rands[i], i * FONT_SIZE + 10, 25);}}/*** @description: 绘制验证码图片背景* @param: g* @return: void*/private static void drawBackground(Graphics g) {g.setColor(Color.white);g.fillRect(0, 0, WIDTH, HEIGHT);// 绘制验证码干扰点for (int i = 0; i < 200; i++) {int x = (int) (Math.random() * WIDTH);int y = (int) (Math.random() * HEIGHT);g.setColor(getRandomColor());g.drawOval(x, y, 1, 1);}}/*** @description: 获取随机颜色* @param: no* @return: java.awt.Color*/private static Color getRandomColor() {Random ran = new Random();return new Color(ran.nextInt(220), ran.nextInt(220), ran.nextInt(220));}}

JwtHelper

token口令生成

public class JwtHelper {private static long tokenExpiration = 24*60*60*1000;private static String tokenSignKey = "123456";//生成token字符串public static String createToken(Long userId, Integer userType) {String token = Jwts.builder().setSubject("YYGH-USER").setExpiration(new Date(System.currentTimeMillis() + tokenExpiration)).claim("userId", userId)
//                .claim("userName", userName).claim("userType", userType).signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();return token;}//从token字符串获取useridpublic static Long getUserId(String token) {if(StringUtils.isEmpty(token)) return null;Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);Claims claims = claimsJws.getBody();Integer userId = (Integer)claims.get("userId");return userId.longValue();}//从token字符串获取userTypepublic static Integer getUserType(String token) {if(StringUtils.isEmpty(token)) return null;Jws<Claims> claimsJws= Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);Claims claims = claimsJws.getBody();return (Integer)(claims.get("userType"));}//从token字符串获取userNamepublic static String getUserName(String token) {if(StringUtils.isEmpty(token)) return "";Jws<Claims> claimsJws= Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);Claims claims = claimsJws.getBody();return (String)claims.get("userName");}//判断token是否有效public static boolean isExpiration(String token){try {boolean isExpire = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getExpiration().before(new Date());//没有过期,有效,返回falsereturn isExpire;}catch(Exception e) {//过期出现异常,返回truereturn true;}}/*** 刷新Token* @param token* @return*/public String refreshToken(String token) {String refreshedToken;try {final Claims claims = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody();refreshedToken = JwtHelper.createToken(getUserId(token), getUserType(token));} catch (Exception e) {refreshedToken = null;}return refreshedToken;}}

AuthContextHolder类

从request请求中获取token口令

public class AuthContextHolder {//从请求头token获取useridpublic static Long getUserIdToken(HttpServletRequest request) {//从请求头tokenString token = request.getHeader("token");//调用工具类Long userId = JwtHelper.getUserId(token);return userId;}//从请求头token获取namepublic static String getUserName(HttpServletRequest request) {//从header获取tokenString token = request.getHeader("token");//jwt从token获取usernameString userName = JwtHelper.getUserName(token);return userName;}}

MD5加密类
public final class MD5 {public static String encrypt(String strSrc) {try {char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'a', 'b', 'c', 'd', 'e', 'f' };//getBytes(String charsetName): 使用指定的字符集将字符串编码为 byte 序列,并将结果存储到一个新的 byte 数组中。byte[] bytes = strSrc.getBytes();//获取MD5摘要算法的MessageDiges 的对象MessageDigest md=MessageDigest.getInstance("MD5");//使用了指定字节更新摘要md.update(bytes);//对于给定数量的更新数据,digest 方法只能被调用一次。在调用 digest 之后,MessageDigest 对象被重新设置成其初始状态。bytes = md.digest();// 获取初识状态下摘要的长度int j = bytes.length;char[] chars = new char[j * 2];int k = 0;for (int i = 0; i < bytes.length; i++) {byte b = bytes[i];chars[k++] = hexChars[b >>> 4 & 0xf];chars[k++] = hexChars[b & 0xf];}//返回加密后的md5密钥串return new String(chars);} catch (NoSuchAlgorithmException e) {e.printStackTrace();throw new RuntimeException("MD5加密出错!!+" + e);}}}

全局统一返回类
@Data
@ApiModel(value = "全局统一返回结果")
public class Result<T> {@ApiModelProperty(value = "返回码")private Integer code;@ApiModelProperty(value = "返回消息")private String message;@ApiModelProperty(value = "返回数据")private T data;public Result(){}// 返回数据protected static <T> Result<T> build(T data) {Result<T> result = new Result<T>();if (data != null)result.setData(data);return result;}public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {Result<T> result = build(body);result.setCode(resultCodeEnum.getCode());result.setMessage(resultCodeEnum.getMessage());return result;}public static<T> Result<T> ok(){return Result.ok(null);}/*** 操作成功* @param data* @param <T>* @return*/public static<T> Result<T> ok(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.SUCCESS);}public static<T> Result<T> fail(){return Result.fail(null);}/*** 操作失败* @param data* @param <T>* @return*/public static<T> Result<T> fail(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.FAIL);}public Result<T> message(String msg){this.setMessage(msg);return this;}public Result<T> code(Integer code){this.setCode(code);return this;}public boolean isOk() {if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {return true;}return false;}
}


返回状态结果响应类
@Getter
public enum ResultCodeEnum {SUCCESS(200,"成功"),FAIL(201, "失败"),SERVICE_ERROR(2012, "服务异常"),ILLEGAL_REQUEST( 204, "非法请求"),PAY_RUN(205, "支付中"),ARGUMENT_VALID_ERROR(206, "参数校验错误"),LOGIN_ERROR(207, "用户名或密码错误"),LOGIN_AUTH(208, "未登陆"),PERMISSION(209, "没有权限"),SECKILL_NO_START(210, "秒杀还没开始"),SECKILL_RUN(211, "正在排队中"),SECKILL_NO_PAY_ORDER(212, "您有未支付的订单"),SECKILL_FINISH(213, "已售罄"),SECKILL_END(214, "秒杀已结束"),SECKILL_SUCCESS(215, "抢单成功"),SECKILL_FAIL(216, "抢单失败"),SECKILL_ILLEGAL(217, "请求不合法"),SECKILL_ORDER_SUCCESS(218, "下单成功"),COUPON_GET(220, "优惠券已经领取"),COUPON_LIMIT_GET(221, "优惠券已发放完毕"),LOGIN_CODE(222,"长时间未操作,会话已失效,请刷新页面后重试!"),CODE_ERROR(223,"验证码错误!"),TOKEN_ERROR(224,"Token无效!");private Integer code;private String message;private ResultCodeEnum(Integer code, String message) {this.code = code;this.message = message;}}

文件上传类
public class UploadFile {//存储文件上传失败的错误信息private static Map<String, Object> error_result = new HashMap<>();//存储头像的上传结果信息private static Map<String, Object> upload_result = new HashMap<>();/*** @description: 效验所上传图片的大小及格式等信息...* @param: photo* @param: path* @return: java.util.Map<java.lang.String, java.lang.Object>*/private static Map<String, Object> uploadPhoto(MultipartFile photo, String path) {//限制头像大小(20M)int MAX_SIZE = 20971520;//获取图片的原始名称String orginalName = photo.getOriginalFilename();//如果保存文件的路径不存在,则创建该目录File filePath = new File(path);if (!filePath.exists()) {filePath.mkdirs();}//限制上传文件的大小if (photo.getSize() > MAX_SIZE) {error_result.put("success", false);error_result.put("msg", "上传的图片大小不能超过20M哟!");return error_result;}// 限制上传的文件类型String[] suffixs = new String[]{".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".gif", ".GIF", ".bmp", ".BMP"};SuffixFileFilter suffixFileFilter = new SuffixFileFilter(suffixs);if (!suffixFileFilter.accept(new File(path + orginalName))) {error_result.put("success", false);error_result.put("msg", "禁止上传此类型文件! 请上传图片哟!");return error_result;}return null;}/*** @description: (提取公共代码 : 提高代码的可重用性)获取头像的上传结果信息* @param: photo* @param: dirPaht* @param: portraitPath* @return: java.util.Map<java.lang.String, java.lang.Object>*/public static Map<String, Object> getUploadResult(MultipartFile photo, String dirPaht, String portraitPath) {if (!photo.isEmpty() && photo.getSize() > 0) {//获取图片的原始名称String orginalName = photo.getOriginalFilename();//上传图片,error_result:存储头像上传失败的错误信息Map<String, Object> error_result = UploadFile.uploadPhoto(photo, dirPaht);if (error_result != null) {return error_result;}//使用UUID重命名图片名称(uuid__原始图片名称)String newPhotoName = UUID.randomUUID() + "__" + orginalName;//将上传的文件保存到目标目录下try {photo.transferTo(new File(dirPaht + newPhotoName));upload_result.put("success", true);upload_result.put("portrait_path", portraitPath + newPhotoName);//将存储头像的项目路径返回给页面} catch (IOException e) {e.printStackTrace();upload_result.put("success", false);upload_result.put("msg", "上传文件失败! 服务器端发生异常!");return upload_result;}} else {upload_result.put("success", false);upload_result.put("msg", "头像上传失败! 未找到指定图片!");}return upload_result;}
}

pojo和mapper类

image.png
根据数据库表的信息,可以借助mybatis的逆向工程生成。
配至pom.xml

<!-- 依赖MyBatis核心包 -->
<dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency>
</dependencies><!-- 控制Maven在构建过程中相关配置 -->
<build><!-- 构建过程中用到的插件 --><plugins><!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.0</version><!-- 插件的依赖 --><dependencies><!-- 逆向工程的核心依赖 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.2</version></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency></dependencies></plugin></plugins>
</build>

配置generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration><!--targetRuntime: 执行生成的逆向工程的版本MyBatis3Simple: 生成基本的CRUD(清新简洁版)MyBatis3: 生成带条件的CRUD(奢华尊享版)--><context id="DB2Tables" targetRuntime="MyBatis3"><!-- 数据库的连接信息 --><jdbcConnection driverClass="com.mysql.jdbc.Driver"connectionURL="jdbc:mysql://..../sc_tb"userId="root"password="123456"></jdbcConnection><!-- javaBean的生成策略--><javaModelGenerator targetPackage="com.project.smart_campus.pojo" targetProject=".\src\main\java"><property name="enableSubPackages" value="true" /><property name="trimStrings" value="true" /></javaModelGenerator><!-- SQL映射文件的生成策略 --><sqlMapGenerator targetPackage="com.project.smart_campus.mapper"  targetProject=".\src\main\resources"><property name="enableSubPackages" value="true" /></sqlMapGenerator><!-- Mapper接口的生成策略 --><javaClientGenerator type="XMLMAPPER" targetPackage="com.project.smart_campus.mapper"  targetProject=".\src\main\java"><property name="enableSubPackages" value="true" /></javaClientGenerator><!-- 逆向分析的表 --><!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName --><!-- domainObjectName属性指定生成出来的实体类的类名 --><table tableName="tb_test" domainObjectName="Test"/></context>
</generatorConfiguration>

执行generate目标
image.png

生成相对应的mapper类和pojo类
image.png
感谢您对本文的阅读,期待您继续关注后续的文章,一同探索智慧校园管理系统功能的具体实现和应用。
敬请期待下一篇文章的发布!
在这里插入图片描述

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

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

相关文章

element-ui Tree 树形控件 过滤保留子级并获取过滤后的数据

本示例基于vue2 element-ui element-ui 的官网demo是只保留到过滤值一级的&#xff0c;并不会保留其子级 目标 1、Tree 树形控件 保留过滤值的子级 2、在第一次过滤数据的基础上进行第二次过滤 先看效果 Tree 树形控件 保留过滤值的子级 <el-treeclass"filter-t…

Redis(中)

1、redis的持久化 "Redis 如何将数据写入磁盘"&#xff0c;首先要明白的时候&#xff0c;我们使用的redis的数据保存在内存上的&#xff0c;也就是说&#xff0c;只要我们的电脑关机或者重启服务器&#xff0c;那么在内存中的数据就会消失&#xff0c;所以要想持久化…

网络四元组

文章目录 网络四元组 今天我们来聊聊 网络四元组 网络四元组 四元组&#xff0c;简单理解就是在 TCP 协议中&#xff0c;去确定一个客户端连接的组成要素&#xff0c;它包括源 IP 地址、目标 IP 地址、源端口号、目标端口号。 正常情况下&#xff0c;我们对于网络通信的认识可…

2024,这将是量子计算的真正挑战

2023年&#xff0c;一项项量子计算纪录被打破。 谷歌量子AI团队证明了将多个量子比特分组合成为一个逻辑量子比特的纠错方法可以提供更低的容错率。以往的纠错研究随着比特数的增加&#xff0c;错误率会提高&#xff0c;都是“越纠越错”&#xff0c;而这次谷歌首次实现了“越纠…

Vue3 结合typescript 组合式函数

在App.vue文件中 实现鼠标点击文件&#xff0c;显示坐标值 第一种方法 第二种方法&#xff1a;组合式函数 结果&#xff1a; 官网推荐组合函数&#xff1a;https://vueuse.org

[讲座] - 闲聊工业设计

1&#xff0c;工业设计相关的学科分类 2&#xff0c;工业设计的职业发展路线 3&#xff0c;工业设计师的成名人物 4&#xff0c;设计了可口可乐的Loewy 可口可乐的瓶子&#xff0c;无论白天晚上还是瓶子被打碎&#xff0c;都能认出这个是可口可乐的瓶子。 草图参照了可可豆&am…

项目引入Jar包的几种方式

目录 背景 方式一 前提 创建一个jar包 使用 方式二 背景 通常情况下&#xff0c;使用SpringBoot框架开发项目的过程中&#xff0c;需要引入一系列依赖&#xff0c;首选的就是在项目的 pom.xml 文件里面通过Maven坐标进行引入&#xff08;可以通过Maven的坐标引入jar包的前…

Java中的数据类型和操作符

目录 Java的数据类型&#xff1a; ! >>> ?: 数组另外一种传参形式&#xff1a; 输入&#xff1a; switch: 快捷键&#xff1a; 快捷创建包&#xff1a; 提交Gitee仓库&#xff1a; next和nextLine区别&#xff1a; 注意事项&#xff1a; 循环终…

【零基础入门TypeScript】类型和变量

目录 任意类型 内置类型 Null 和 undefined ─ 它们是一样的吗&#xff1f; 用户定义类型 TypeScript 中的变量声明 示例&#xff1a;TypeScript 中的变量 TypeScript 中的类型断言 例子 TypeScript 中的推断类型 示例&#xff1a;推断类型 TypeScript 变量作用域 …

Vue3-34-路由-路由配置参数 props

说明 路由的路径中可以携带参数&#xff0c; 形式如 &#xff1a;/a/:pname &#xff0c;这个:表示这是个参数&#xff0c;pname &#xff1a;表示 参数名称。 在组件中&#xff0c;可以通过 当前路由对象的 params 属性来获取到这个参数&#xff0c; 当前路由对象 可以通过 us…

scratch小明游泳 2023年12月中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析

目录 scratch小明游泳 一、题目要求 1、准备工作 2、功能实现 二、案例分析

ElasticSearch 复合查询 Boolean Query

官网文档网址&#xff1a;Boolean query | Elasticsearch Guide [7.17] | Elastic 目录 复合查询 Boolean Query 利用bool查询实现功能 总结 复合查询 Boolean Query 布尔查询是一个或多个查询子句的组合。子查询的组合方式有&#xff1a; must:必须匹配每个子查询&#xf…