Web开发学习笔记20210427_RuoYi-fast新建子菜单并实现一些功能

1 准备工作

这是一个Web开发入门学习若依权限管理系统的记录帖
数据库刚接触,前端完全不懂,连蒙带抄实现一个最简单的子菜单,参考了系统中最不复杂的“岗位管理”模块。

环境准备:

需要知道的概念:

  • Spring框架和 spring-boot
  • MyBatis框架
  • Shiro安全框架(暂时没用到)
  • Thymeleaf模板(前端)

接下来是走一步看一步了,做到哪里不会就现查现学……

2 RuoYi-fast运行

在IDEA中直接下载引入若依:
登陆gitee - IDEA 工具栏 - VSC - Get from version control - URL输入Ruoyi-fast下载地址https://gitee.com/y_project/RuoYi-fast

等待下载完成,进行配置,doc文件夹下有《若依环境使用手册》,写得很清楚,好像没遇到什么难题,运行RuoYiApplication,登陆成功
若依系统首页

3 实现一个系统管理子菜单:测试管理

3.1 实现过程

  • 在数据库中新建一个test表,参考post表,加入几个条目
  • resources - mybatis - system下新建TestMapper.xml编写数据库映射
    新建中没有mapper选项:IDEA创建Mapper.xml文件
  • com.ruoyi.project.system新建test包,创建需要的类和接口
    1)因为test名字特殊,controller包里的TestController调试可以通过,但运行时报告了与com.ruoyi.project.tool.swagger下的类重名错误,导致系统启动失败,因此需要改个名字如MyTestController
    2)编写时涉及名称或编码是否唯一问题时需要两个user constant值,在com.ruoyi.common.constant.UserConstants里添加:
    /** 测试名称是否唯一的返回结果码 */
    public final static String TEST_NAME_UNIQUE = "0";
    public final static String TEST_NAME_NOT_UNIQUE = "1";
    /** 测试编码是否唯一的返回结果码 */
    public final static String TEST_CODE_UNIQUE = "0";
    public final static String TEST_CODE_NOT_UNIQUE = "1";
  • 编译TestMapper.xml可以检查上述所有,通过后开始写html
  • resources - templates - system下添加test路径,编写(抄)需要的html

3.2 遇到的问题

3.2.1 不显示菜单错误

现在可以运行了,可是运行出来仿佛我加的程序从未存在……一开始以为系统菜单在main.html里修改,但main中所有左侧菜单都用变量统一表述了,没看懂,但应该不是改这个。然后在project里搜索了一下,发现相关条目保存在数据库的sys_menu表里,我没有在这里添加相应条目:
系统菜单表
添加条目时,需要仔细检查层级有没有填对,信息有没有填完整,否则出现菜单打不开,变成404的现象。
顺便全面看了一下数据库里的表,发现还有一个sys_role_menu表,保存了系统操作角色id对应的菜单id:
系统角色菜单表
不确定影不影响前端显示,总之把条目id先加上。

3.2.2 无法读取数据库表内容错误

现在再次启动服务器:
若依系统首页
菜单里出现了我添加的“测试管理”条目,条目下所有功能也都显示了,但又有了新问题,读取不到我在数据库中添加的条目,应该是mapper.xml文件问题,检查了一下居然是包名打错字母,我晕😠

现在正常了:
若依系统首页

3.2.3 页面功能实现错误

试用下页面上的功能,又出了问题:

  • 搜索键没有反应,按照名称、编码、状态都无法搜索单一条目
  • 编辑条目中更改状态出现错误,显示重名
  • 新增或者编辑名称和编码不论写什么值都会显示已存在
  • 删除条目报错:nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression ‘array’. Return value (1) was not iterable.

可以说是除了重置和导出,其他所有功能都不能实现😰去寻找下原因

  • 搜索功能:com.ruoyi.project.system.test.domain的Test类中所有set方法都没有声明类型和变量,修改后搜索功能正常了
  • 编辑状态功能:com.ruoyi.project.system.test.controller的MyTestController类的editSave方法返回了return toAjax(testService.insertTest(test));从addSave复制过来漏改了……改成return toAjax(testService.updateTest(test));状态信息就可以编辑了
  • 删除功能:com.ruoyi.project.system.test.service的TestServiceImpl类的deleteTestByIds(String ids)方法返回值和实际值不符,返回int,而我在之前编写时直接return testMapper.deleteTestByIds(ids);改为在return语句前添加convert:
	/**
     * 批量删除test信息
     *
     * @param ids 需要删除的数据id
     * @throws BusinessException
     */
    @Override
    public int deleteTestByIds(String ids) throws BusinessException
    {
   
        Long[] testIds = Convert.toLongArray(ids);
        return testMapper.deleteTestByIds(testIds);
    }
  • 编辑名称功能:编辑名称时抛出异常:Request method ‘TEST’ not supported,是html文件里的type: "post",写成test了,此post非彼post,果然对html一窍不通还是不行😵
  • 新增功能异常1:和上述一样修改后不再显示重名错误,但抛出了新的运行时异常:nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression ‘remark !=null and remark != ‘‘0’’’.写得比较清楚,是xml文件里赋值时if声明的语法有错误,写多了一个0,改成<if test="remark != null and remark != ''">#{remark},</if>
  • 新增功能异常2:修改上述内容后又报了新的运行时异常:Error updating database. Cause: java.sql.SQLException: Field ‘test_id’ doesn’t have a default value在新增操作时没有设置id,而id没有默认值,导致id为空。在数据库的设计表中可以看到别的表的id都设置了自动递增,因此将新建的sys_test表的id也设置为自动递增,id就产生默认值了

现在增删查改都可以实现了:
测试管理页面
前端更改后的数据库表:
数据库表界面
虽然是简单内容,但是手打一遍出现了很多很多问题……把主要问题记录在了本帖中。

4 总结

关于后端六个文件的个人理解:

  • TestMapper.xml:动态sql操作文件,描述了系统和数据库的映射关系
    因为在namespace里填写了mapper接口<mapper namespace="com.ruoyi.project.system.test.mapper.TestMapper">所以编译这个文件可以检查所有相关class和interface(吗?)
  • TestMapper.java:dao层接口文件,方法名和 xml 中定义的每个 statement 的 id 同名,输入参数类型和 xml 中定义的 statement 的parameterType 类型相同,返回类型和 xml 中定义的 statement 的resultType 类型相同
  • ITestService.java:service层接口文件,定义方法的参数、返回值
  • TestServiceImpl.java:service层类文件,实现ITestService接口的方法
  • MyTestController.java:controller层类文件,接收前端请求,调用service层方法实现
  • Test.java:domain层类文件,和数据库中的表一一对应的JavaBean,实现set和get方法

业务实现流程:controller层接受前端发来的请求,同时向后端发送请求,——>service 层——>serviceImpl实现service层,同时连接dao层,(在dao层中同样是接口)——>通过dao层去实现对数据库的操作——>在XML文件中通过namespace完成连接dao层

5 补充说明

以上demo没有做和user的依赖关联,是最最最简单的子菜单实现,用于自己了解系统各层的作用,和开发的简单流程。编写过程中学习的帖子们(部分):

如何阅读别人的代码 [原]
详细SpringBoot教程之入门(一)
做web开发,怎么能不懂cookie、session和token呢?
SpringBoot注解最全详解(整合超详细版本)
JavaWeb——Servlet(全网最详细教程包括Servlet源码分析)
mybatis看这一篇就够了,简单全面一发入魂
AJAX&JSON超级最详细讲解
Mybatis的mapper.xml配置文件——详解
MyBatis Mapper XML文件详解
为什么dao层和service层要用接口?
SpringMVC中的@Controller和@RequestMapping作用详解
controller层的作用
初学SpringBoot框架: Dao层、Service层、Controller层的作用
解析Java框架中entity层,mapper层,service层,controller各层作用
domain层详解
Java Bean详解
POJO和JavaBean的区别
Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释
GET和POST两种基本请求方法的区别

6 所有新增代码

6.1 后端

TestMapper.xml

<?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.ruoyi.project.system.test.mapper.TestMapper">

    <resultMap type="Test" id="TestResult">
        <id     property="testId"       column="test_id"        />
        <result property="testCode"     column="test_code"      />
        <result property="testName"     column="test_name"      />
        <result property="status"       column="status"         />
        <result property="createBy"     column="create_by"      />
        <result property="createTime"   column="create_time"    />
        <result property="updateBy"     column="update_by"      />
        <result property="updateTime"   column="update_time"    />
        <result property="remark"       column="remark"         />
    </resultMap>

    <sql id="selectTestVo">
        select test_id, test_code, test_name, status, create_by, create_time, remark
        from sys_test
    </sql>

    <select id="selectTestList" parameterType="Test" resultMap="TestResult">
        <include refid="selectTestVo" />
        <where>
            <if test="testCode != null and testCode != ''">
                AND test_code like concat('%', #{testCode}, '%')
            </if>
            <if test="status != null and status != ''">
                AND status = #{status}
            </if>
            <if test="testName != null and testName != ''">
                AND test_name like concat('%', #{testName}, '%')
            </if>
        </where>
    </select>

    <select id="selectTestAll" resultMap="TestResult">
        <include refid="selectTestVo" />
    </select>

    <select id="selectTestById" parameterType="Long" resultMap="TestResult">
        <include refid="selectTestVo" />
        where test_id = #{testID}
    </select>

    <select id="checkTestNameUnique" parameterType="String" resultMap="TestResult">
        <include refid="selectTestVo" />
        where test_name = #{testName} limit 1
    </select>

    <select id="checkTestCodeUnique" parameterType="String" resultMap="TestResult">
        <include refid="selectTestVo" />
        where test_code = #{testCode} limit 1
    </select>

    <delete id="deleteTestByIds" parameterType="Long">
        delete from sys_test where test_id in
        <foreach collection="array" item="testId" open="(" separator="," close=")">
            #{testId}
        </foreach>
    </delete>

    <update id="updateTest" parameterType="Test">
        update sys_test
        <set>
            <if test="testCode != null and testCode != ''">test_code = #{testCode},</if>
            <if test="testName != null and testName != ''">test_name = #{testName},</if>
            <if test="status != null and status != ''">status = #{status},</if>
            <if test="remark != null">remark = #{remark},</if>
            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
            update_time = sysdate()
        </set>
        where test_id = #{testId}
    </update>

    <insert id="insertTest" parameterType="Test" useGeneratedKeys="true" keyProperty="testId">
        insert into sys_test(
            <if test="testId !=null and testId != 0">test_id,</if>
            <if test="testCode !=null and testCode != ''">test_code,</if>
            <if test="testName !=null and testName != ''">test_name,</if>
            
  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值