springboot多级分类源码

简介: springboot多级分类源码

如何实现多级分类,方便维护,容易获取子分类、父级分类、某个子分类的顶级分类的所有子分类;

一、数据建表

 

DROP TABLE IF EXISTS `oa_classification`;
CREATE TABLE `oa_classification`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '分类名称',
  `parent_id` bigint(20) NULL DEFAULT 0 COMMENT '父分类id',
  `sort` int(11) NOT NULL DEFAULT 0 COMMENT '显示顺序',
  `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '分类状态(0正常 1停用)',
  `deth` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '纵深',
  `deth_name` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '纵深名称',
  `deth_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '纵深ID',
  `create_by` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '更新者',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '项目分类表' ROW_FORMAT = Dynamic;
 
SET FOREIGN_KEY_CHECKS = 1;

二、maven主要依赖

<!-- Mysql驱动包 -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
</dependency>
 
<!--ORM-->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.5.1</version>
</dependency>
 
<!--hutool-->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.0</version>
</dependency>

三、代码

1、controller

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
 
 
@Api(tags = "OA-系统设置-报销项目分类")
@RestController
@RequestMapping("/projectManagement")
@Validated
@Slf4j
public class ClassificationController extends BaseController {
 
    @Resource
    private OaClassificationService classificationService;
 
 
    @PostMapping("/classification/create")
    @ApiOperation("创建报销项目分类")
    public AjaxResult createClassification(@Valid @RequestBody ClassificationCreateReqVO reqVO) {
        Long classificationId = classificationService.createClassification(reqVO);
        return toAjax(true);
    }
 
    @PutMapping("update")
    @ApiOperation("更新报销项目分类")
    public AjaxResult updateClassification(@Valid @RequestBody ClassificationUpdateReqVO reqVO) {
        classificationService.updateClassification(reqVO);
        return toAjax(true);
    }
 
    @GetMapping("/get")
    @ApiOperation("获得报销项目分类信息")
    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
    public AjaxResult getClassification(@RequestParam("id") Long id) {
        OaClassification classification = classificationService.getClassification(id);
        return success(classification);
    }
 
    @DeleteMapping("delete")
    @ApiOperation("删除报销项目分类")
    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1", dataTypeClass = Long.class)
    public AjaxResult deleteClassification(@RequestParam("id") Long id) {
        classificationService.deleteClassification(id);
        return toAjax(true);
    }
 
 
    @GetMapping("/listChildren")
    @ApiOperation("获取报销项目分类列表-子分类")
    public AjaxResult listClassificationsChildren(ClassificationListReqVO reqVO) {
        List<OaClassification> list = classificationService.getSimpleClassifications(reqVO);
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        // 排序字段,这个字段不能是null,不然会报错,默认最好是数字
        treeNodeConfig.setWeightKey("sort");
        treeNodeConfig.setIdKey("id");
        // 父级id字段
        treeNodeConfig.setParentIdKey("parentId");
        // 最大递归深度
        //treeNodeConfig.setDeep(3);
        //转换器
        List<Tree<Integer>> build = TreeUtil.build(list, 0, treeNodeConfig, ((object, treeNode) -> {
            treeNode.setId(object.getId().intValue());//id
            treeNode.setParentId(object.getParentId().intValue());//父id
            treeNode.putExtra("name", object.getName());
            treeNode.putExtra("sort", object.getSort());
            treeNode.putExtra("status", object.getStatus());
        }));
        log.info(JSON.toJSONString(build));
        return success(build);
    }
 
    @GetMapping("/list-all-simple-children")
    @ApiOperation(value = "获取报销项目分类精简信息列表-子分类", notes = "只包含被开启的报销项目分类,主要用于前端的下拉选项")
    public AjaxResult getSimpleClassificationsChildren() {
        List<Tree<Integer>> simpleClassificationsChildren = classificationService.getSimpleClassificationsChildren();
        return success(simpleClassificationsChildren);
    }
}

2、service

import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
 
/**
 *
 */
public interface OaClassificationService extends IService<OaClassification> {
    /**
     * 创建分类
     *
     * @param reqVO 分类信息
     * @return 分类编号
     */
    Long createClassification(ClassificationCreateReqVO reqVO);
 
    /**
     * 更新分类
     *
     * @param reqVO 分类信息
     */
    void updateClassification(ClassificationUpdateReqVO reqVO);
 
    /**
     * 删除分类
     *
     * @param id 分类编号
     */
    void deleteClassification(Long id);
 
    /**
     * 筛选分类列表
     *
     * @param reqVO 筛选条件请求 VO
     * @return 分类列表
     */
    List<OaClassification> getSimpleClassifications(ClassificationListReqVO reqVO);
 
    /**
     *获取项目分类精简信息列表-子分类
     * @return
     */
    List<Tree<Integer>> getSimpleClassificationsChildren();
 
    /**
     * 获得所有子分类,从缓存中
     *
     * @param parentId 分类编号
     * @param list 是否递归获取所有
     * @return 子分类列表
     */
    void getClassiByParentId( List<OaClassification> list,Long parentId);
 
 
    /**
     * 获得分类信息
     *
     * @param id 分类编号
     * @return 分类信息
     */
    OaClassification getClassification(Long id);
 
}
 
 
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
 
/**
 *
 */
@Service
public class OaClassificationServiceImpl extends ServiceImpl<OaClassificationMapper, OaClassification>
        implements OaClassificationService {
    String slash = "/";
    String comma = ",";
    @Resource
    private OaClassificationMapper classificationMapper;
 
 
    @Override
    public Long createClassification(ClassificationCreateReqVO reqVO) {
        // 校验正确性
        Long parentId = reqVO.getParentId();
        checkCreateOrUpdate(null, parentId, reqVO.getName());
        // 插入分类
        OaClassification classifiction = new OaClassification();
        BeanUtils.copyProperties(reqVO, classifiction);
        setLevelDept(parentId, classifiction);
        classificationMapper.insert(classifiction);
        Long id = classifiction.getId();
        if (Objects.equals(classifiction.getParentId(), 0L)) {
            OaClassification update = new OaClassification();
            update.setId(id);
            update.setDethId(String.valueOf(id));
            classificationMapper.updateById(update);
        } else {
            OaClassification parentClass = classificationMapper.selectById(classifiction.getParentId());
            OaClassification update = new OaClassification();
            update.setId(id);
            update.setDethId(parentClass.getDethId().concat(slash).concat(String.valueOf(id)));
            classificationMapper.updateById(update);
        }
        return id;
    }
 
 
    @Override
    public void updateClassification(ClassificationUpdateReqVO reqVO) {
        Long id = reqVO.getId();
        Long parentId = reqVO.getParentId();
        // 校验正确性
        checkCreateOrUpdate(id, parentId, reqVO.getName());
        // 更新分类
        OaClassification updateObj = new OaClassification();
        BeanUtils.copyProperties(reqVO, updateObj);
        setLevelDept(parentId, updateObj);
        classificationMapper.updateById(updateObj);
        if (!Objects.equals(parentId, 0L)) {
            OaClassification parentClass = classificationMapper.selectById(parentId);
            OaClassification update = new OaClassification();
            update.setId(id);
            update.setDethId(parentClass.getDethId().concat(slash).concat(String.valueOf(id)));
            classificationMapper.updateById(update);
        }
        //修改是修改子分类名称
        reName(updateObj.getId());
    }
 
    /**
     * @param parentId      父级ID
     * @param classifiction
     */
    private void setLevelDept(Long parentId, OaClassification classifiction) {
        //如果不是一级分类插入层级、纵深
        if (parentId == null || Objects.equals(parentId, 0L)) {
            //设置层级
 
            classifiction.setParentId(0L);
            classifiction.setDethName(classifiction.getName());
            return;
        } else {
            OaClassification dbOaClassification = classificationMapper.selectById(parentId);
 
            //设置纵深
            String deth = dbOaClassification.getDeth();
            if (StrUtil.isEmpty(deth)) {
                classifiction.setDeth(String.valueOf(parentId));
            } else {
                classifiction.setDeth(deth.concat(comma).concat(String.valueOf(parentId)));
            }
            classifiction.setDethName(dbOaClassification.getDethName().concat("/").concat(classifiction.getName()));
        }
    }
 
    @Async
    public void reName(Long id) {
        List<OaClassification> classificationDOs = classificationMapper.selectByParentId(id);
        if (classificationDOs == null) {
            return;
        }
        //遍历子类
        classificationDOs.forEach((tem) -> {
            Long parentId = tem.getParentId();
            OaClassification dbOaClassification = classificationMapper.selectById(parentId);
            //设置层级
 
            //设置纵深
            String deth = dbOaClassification.getDeth();
            if (StrUtil.isEmpty(deth)) {
                tem.setDeth(String.valueOf(parentId));
            } else {
                tem.setDeth(deth.concat(comma).concat(String.valueOf(parentId)));
            }
            tem.setDethName(dbOaClassification.getDethName().concat(slash).concat(tem.getName()));
            tem.setDethId(dbOaClassification.getDethId().concat(slash).concat(tem.getId().toString()));
            classificationMapper.updateById(tem);
            reName(tem.getId());
        });
    }
 
    @Override
    public void deleteClassification(Long id) {
        // 校验是否存在
        checkClassificationExists(id);
        // 校验是否有子分类
        List<OaClassification> oaClassifications = classificationMapper.selectByParentId(id);
        if (!CollUtil.isEmpty(oaClassifications)) {
            throw new ServiceException("存在子分类,无法删除");
        }
 
        classificationMapper.deleteById(id);
    }
 
    @Override
    public List<OaClassification> getSimpleClassifications(ClassificationListReqVO reqVO) {
        return classificationMapper.selectPageList(reqVO);
    }
 
    @Override
    public List<Tree<Integer>> getSimpleClassificationsChildren() {
        // 获得项目分类列表,只要开启状态的
        ClassificationListReqVO reqVO = new ClassificationListReqVO();
        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
        List<OaClassification> list = getSimpleClassifications(reqVO);
 
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        // 排序字段,这个字段不能是null,不然会报错,默认最好是数字
        treeNodeConfig.setWeightKey("sort");
        treeNodeConfig.setIdKey("id");
        // 父级id字段
        treeNodeConfig.setParentIdKey("parentId");
        // 最大递归深度
        //treeNodeConfig.setDeep(3);
        //转换器
        List<Tree<Integer>> trees = TreeUtil.build(list, 0, treeNodeConfig, ((object, treeNode) -> {
            treeNode.setId(object.getId().intValue());//id
            treeNode.setParentId(object.getParentId().intValue());//父id
            treeNode.putExtra("name", object.getName());
        }));
        return trees;
    }
 
    @Override
    public void getClassiByParentId(List<OaClassification> list, Long id) {
        if (id == null) {
            return;
        }
        List<OaClassification> classificationDOs = classificationMapper.selectByParentId(id);
        if (CollUtil.isEmpty(classificationDOs)) {
            return;
        }
        list.addAll(classificationDOs);
        // 递归,简单粗暴
        classificationDOs.forEach((tem) -> {
            this.getClassiByParentId(list, tem.getId());
        });
 
        return;
    }
 
 
    private void checkCreateOrUpdate(Long id, Long parentId, String name) {
        // 校验自己存在
        checkClassificationExists(id);
        // 校验父分类的有效性
        checkParentClassificationEnable(id, parentId);
        // 校验分类名的唯一性
        checkClassificationNameUnique(id, parentId, name);
    }
 
    private void checkParentClassificationEnable(Long id, Long parentId) {
        if (parentId == null || Objects.equals(parentId, 0L)) {
            return;
        }
        // 不能设置自己为父分类
        if (parentId.equals(id)) {
            throw new ServiceException("不能设置自己为父分类");
        }
        // 父不存在
        OaClassification classifiction = classificationMapper.selectById(parentId);
        if (classifiction == null) {
            throw new ServiceException("父级分类不存在");
        }
        // 父分类被禁用
        if (!CommonStatusEnum.ENABLE.getStatus().equals(classifiction.getStatus())) {
            throw new ServiceException("分类不处于开启状态,不允许选择");
        }
        // 父分类不能是原来的子分类
        List<OaClassification> children = new ArrayList<>();
        this.getClassiByParentId(children, id);
        if (children.stream().anyMatch(classifiction1 -> classifiction1.getId().equals(parentId))) {
            throw new ServiceException("不能设置自己的子分类为父分类");
        }
    }
 
    private void checkClassificationExists(Long id) {
        if (id == null) {
            return;
        }
        OaClassification classifiction = classificationMapper.selectById(id);
        if (classifiction == null) {
            throw new ServiceException("分类不存在");
        }
    }
 
 
    private void checkClassificationNameUnique(Long id, Long parentId, String name) {
        OaClassification menu = classificationMapper.selectByParentIdAndName(parentId, name);
        if (menu == null) {
            return;
        }
        // 如果 id 为空,说明不用比较是否为相同 id 的
        if (id == null) {
            throw new ServiceException("已经存在该名字的分类");
        }
        if (!menu.getId().equals(id)) {
            throw new ServiceException("已经存在该名字的分类");
        }
    }
 
 
    @Override
    public OaClassification getClassification(Long id) {
        return classificationMapper.selectById(id);
    }
 
 
}
 
 
 
 

3、mapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
import org.apache.ibatis.annotations.Param;
 
import java.util.List;
 
/**
 * @Entity generator.domain.OaClassification
 */
public interface OaClassificationMapper extends BaseMapper<OaClassification> {
 
    List<OaClassification> selectPageList(@Param("reqVO") ClassificationListReqVO reqVO);
 
 
    OaClassification selectByParentIdAndName(@Param("parentId") Long parentId, @Param("name") String name);
 
 
    List<OaClassification> selectByParentId(Long parentId);
 
 
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxx.mapper.OaClassificationMapper">
 
    <resultMap id="BaseResultMap" type="com.xxxx.domain.OaClassification">
        <id property="id" column="id" jdbcType="BIGINT"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="parentId" column="parent_id" jdbcType="BIGINT"/>
        <result property="sort" column="sort" jdbcType="INTEGER"/>
        <result property="status" column="status" jdbcType="TINYINT"/>
        <result property="deth" column="deth" jdbcType="VARCHAR"/>
        <result property="dethName" column="deth_name" jdbcType="VARCHAR"/>
        <result property="dethId" column="deth_id" jdbcType="VARCHAR"/>
        <result property="createBy" column="create_by" jdbcType="VARCHAR"/>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
        <result property="updateBy" column="update_by" jdbcType="VARCHAR"/>
        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
    </resultMap>
 
    <sql id="Base_Column_List">
        id
        ,name,parent_id,
        sort,status,deth,
        deth_name,deth_id,create_by,
        create_time,update_by,update_time
    </sql>
    <select id="selectPageList" resultType="com.xxxx.domain.OaClassification">
        select * from oa_classification
        <where>
            <if test="reqVO.id != null ">
                id= #{reqVO.name}
            </if>
            <if test="reqVO.name != null and reqVO.name != ''">
                and name like (concat('%', #{reqVO.name}, '%'))
            </if>
            <if test="reqVO.status != null ">
               and status= #{reqVO.status}
            </if>
        </where>
        order by sort desc,id desc
    </select>
    <select id="selectByParentIdAndName" resultType="com.xxxx.domain.OaClassification">
        select * from oa_classification
        <where>
            <if test="parentId != null ">
                parent_id= #{parentId}
            </if>
            <if test="name != null and name != ''">
                and name =#{name}
            </if>
        </where>
    </select>
    <select id="selectByParentId" resultType="com.xxxx.domain.OaClassification">
        select * from oa_classification
        <where>
            <if test="parentId != null ">
                parent_id= #{parentId}
            </if>
        </where>
    </select>
 
 
</mapper>

4、基础类

1.@Data
@TableName(value = "oa_classification", autoResultMap = true)
@EqualsAndHashCode(callSuper = true)
public class OaClassification extends BaseEntityTwo {
 
    /**
    * 分类id
    */
    @ApiModelProperty("分类id")
    private Long id;
    /**
    * 分类名称
    */
    @ApiModelProperty("分类名称")
    //@Length(max= 100,message="编码长度不能超过100")
    private String name;
    /**
    * 父分类id
    */
    @ApiModelProperty("父分类id")
    private Long parentId;
    /**
    * 显示顺序
    */
    @ApiModelProperty("显示顺序")
    private Integer sort;
    /**
    * 分类状态(0正常 1停用)
    */
    @ApiModelProperty("分类状态(0正常 1停用)")
    private Integer status;
    /**
    * 纵深
    */
    @ApiModelProperty("纵深")
    //@Length(max= 255,message="编码长度不能超过255")
    private String deth;
    /**
    * 纵深名称
    */
    @ApiModelProperty("纵深名称")
    //@Length(max= 300,message="编码长度不能超过300")
    private String dethName;
    /**
    * 纵深ID
    */
    @ApiModelProperty("纵深ID")
    //@Length(max= 255,message="编码长度不能超过255")
    private String dethId;
 
}
 
@Data
public class BaseEntityTwo implements Serializable {
    private static final long serialVersionUID = 1L;
 
 
    /**
     * 创建者
     */
    @TableField(fill = FieldFill.INSERT)
    @Excel(name = "创建者",sort = 101)
    private String createBy;
 
    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT)
    @Excel(name = "创建时间", sort = 102,width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Excel.Type.EXPORT)
    private Date createTime;
 
    /**
     * 更新者
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @Excel(name = "更新者",sort = 103)
    private String updateBy;
 
    /**
     * 更新时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @Excel(name = "更新时间", sort = 104,width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Excel.Type.EXPORT)
    private Date updateTime;
 
}
@Data
public class ClassificationBaseVO {
 
    @ApiModelProperty(value = "分类名称", required = true, example = "xxx")
    @NotBlank(message = "分类名称不能为空")
    @Size(max = 30, message = "分类名称长度不能超过30个字符")
    private String name;
 
    @ApiModelProperty(value = "父菜单ID,一级分类", example = "1024")
    private Long parentId;
 
    private Integer sort;
 
 
}
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ClassificationCreateReqVO extends ClassificationBaseVO {
}
@Data
public class ClassificationListReqVO {
 
    @ApiModelProperty(value = "分类名称", example = "王二", notes = "模糊匹配")
    private String name;
 
    @ApiModelProperty(value = "分类ID", example = "1")
    private Long id;
 
    @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类")
    private Integer status;
 
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ClassificationSimpleRespVO {
 
    @ApiModelProperty(value = "分类编号", required = true, example = "1024")
    private Long id;
 
    @ApiModelProperty(value = "分类名称", required = true, example = "王二")
    private String name;
 
    @ApiModelProperty(value = "父分类 ID", required = true, example = "1024")
    private Long parentId;
 
}
@Data
@EqualsAndHashCode(callSuper = true)
public class ClassificationUpdateReqVO extends ClassificationBaseVO {
 
    @ApiModelProperty(value = "分类编号", required = true, example = "1024")
    @NotNull(message = "分类编号不能为空")
    private Long id;
 
    @ApiModelProperty(value = "状态 0开启 1关闭", required = true, example = "1")
    @NotNull(message = "状态不能为空")
    private Integer status;
 
}

四、不足

1、纵深名称和纵深ID使用分隔符+字符存储。可以使用json存储,配合mybatis的typeHandler属性,方便业务使用时结构化;

2、可以增加缓存提升获取分类的效率,如果项目分类比较多,不建议一次取出;

相关文章
|
14天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
160 37
|
2天前
|
JavaScript Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
本文介绍了一个基于Spring Boot和Vue.js实现的在线考试系统。随着在线教育的发展,在线考试系统的重要性日益凸显。该系统不仅能提高教学效率,减轻教师负担,还为学生提供了灵活便捷的考试方式。技术栈包括Spring Boot、Vue.js、Element-UI等,支持多种角色登录,具备考试管理、题库管理、成绩查询等功能。系统采用前后端分离架构,具备高性能和扩展性,未来可进一步优化并引入AI技术提升智能化水平。
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
|
4天前
|
Java 关系型数据库 MySQL
毕设项目&课程设计&毕设项目:springboot+jsp实现的房屋租租赁系统(含教程&源码&数据库数据)
本文介绍了一款基于Spring Boot和JSP技术的房屋租赁系统,旨在通过自动化和信息化手段提升房屋管理效率,优化租户体验。系统采用JDK 1.8、Maven 3.6、MySQL 8.0、JSP、Layui和Spring Boot 2.0等技术栈,实现了高效的房源管理和便捷的租户服务。通过该系统,房东可以轻松管理房源,租户可以快速找到合适的住所,双方都能享受数字化带来的便利。未来,系统将持续优化升级,提供更多完善的服务。
毕设项目&课程设计&毕设项目:springboot+jsp实现的房屋租租赁系统(含教程&源码&数据库数据)
|
9天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
1月前
|
JavaScript Java 关系型数据库
美妆商城系统 SpringBoot + Vue 【毕业设计 资料 + 源码】
这篇文章介绍了一个使用SpringBoot + Vue + Mybatis + Mysql技术栈开发的美妆商城系统,包括系统功能划分、部分页面截图和前后端源码示例,并提供了GitHub上的源码链接。
美妆商城系统 SpringBoot + Vue 【毕业设计 资料 + 源码】
|
1月前
|
JavaScript Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+vue实现的前后端分离的选课管理系统(含教程&源码&数据库数据)
本文介绍了一个基于Spring Boot和Vue.js技术栈的高校选课管理系统的设计与实现。该系统采用前后端分离架构,旨在提高选课效率、优化资源分配及提升用户体验。技术栈包括:后端Spring Boot 2.0、前端Vue 2.0、数据库MySQL 8.0、开发环境JDK 1.8和Maven 3.6等。系统功能覆盖登录、学生信息管理、选课管理、成绩查询等多个方面,并针对学生、教师和管理员提供了不同的操作界面。系统采用了响应式设计,支持多设备访问,并通过Element UI增强了界面的友好性和交互性。
毕设项目&课程设计&毕设项目:基于springboot+vue实现的前后端分离的选课管理系统(含教程&源码&数据库数据)
|
1月前
|
安全 Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+jsp实现的健身房管理系统(含教程&源码&数据库数据)
本文介绍了一款基于Spring Boot和JSP技术实现的健身房管理系统。随着健康生活观念的普及,健身房成为日常锻炼的重要场所,高效管理会员信息、课程安排等变得尤为重要。该系统旨在通过简洁的操作界面帮助管理者轻松处理日常运营挑战。技术栈包括:JDK 1.8、Maven 3.6、MySQL 8.0、JSP、Shiro、Spring Boot 2.0等。系统功能覆盖登录、会员管理(如会员列表、充值管理)、教练管理、课程管理、器材管理、物品遗失管理、商品管理及信息统计等多方面。
|
1月前
|
JavaScript Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+vue实现的前后端分离的考试管理系统(含教程&源码&数据库数据)
在数字化时代背景下,本文详细介绍了如何使用Spring Boot框架结合Vue.js技术栈,实现一个前后端分离的考试管理系统。该系统旨在提升考试管理效率,优化用户体验,确保数据安全及可维护性。技术选型包括:Spring Boot 2.0、Vue.js 2.0、Node.js 12.14.0、MySQL 8.0、Element-UI等。系统功能涵盖登录注册、学员考试(包括查看试卷、答题、成绩查询等)、管理员功能(题库管理、试题管理、试卷管理、系统设置等)。
毕设项目&课程设计&毕设项目:基于springboot+vue实现的前后端分离的考试管理系统(含教程&源码&数据库数据)
|
1月前
|
Web App开发 前端开发 关系型数据库
基于SpringBoot+Vue+Redis+Mybatis的商城购物系统 【系统实现+系统源码+答辩PPT】
这篇文章介绍了一个基于SpringBoot+Vue+Redis+Mybatis技术栈开发的商城购物系统,包括系统功能、页面展示、前后端项目结构和核心代码,以及如何获取系统源码和答辩PPT的方法。