后端接收不到注册界面输入的数据(错题记录)

目录

项目描述

问题描述

问题分析

解决流程

1. 持久层测试(mapper)

2. 业务层测试(service)

3. 检查控制层代码(controller)

4. 确认是前端代码的问题

4.1  确认与控制层的接口

4.2  表单method属性

4.3  input标签的name属性

4.4  参数命名不规范导致无法接收数据

4.5  其他原因


项目描述

用springboot创建一个人才招聘网站,我使用的是IDEA 2020版本。

问题描述

在实现用户注册的时候,在页面中输入了账号密码,但出现500的错误提示,如下图所示:

查看控制台报错信息,显示用户账号(J_account)不能为空。

问题分析

我在做完业务层之后就对后端的代码进行过测试,所以可以排除持久层(mapper)和业务层(service)代码的问题,如果没有做测试可以先根据下面的方法测试一下。

排除持久层和业务层之后,我们首先要确认控制层的接口是否与业务层匹配,然后再确认前端数据是否发送成功。

可以直接从控制层(controller)开始测试,如果报错了往前面看,如果没报错往后面看。

解决流程

1. 持久层测试(mapper)

1.1  在test文件夹中如下位置创建一个mapper包,在包中新建一个测试类,命名为UserMapperTests

1.2  对我们mapper层进行测试

查看xml文件的接口,这里我的接口是insert.

<!-- 这是我的xml文件中的插入操作相关代码 -->
    <insert id="insert">
        INSERT INTO jobseeker (j_account, j_pwd, j_name, j_sex, j_state, j_tel) VALUES (
        #{jAccount}, #{jPwd}, #{jName}, #{jSex}, #{jState}, #{jTel}
        )
    </insert>

测试类中进行测试,对应你的xml接口哦

package com.gp.recruit.mapper;


import com.gp.recruit.demos.web.entity.User;
import com.gp.recruit.demos.web.mapper.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


// @SpringBootTest: 表示标注当前的类是一个测试类,不会随同项目一块打包发送
@SpringBootTest
// @RunWith: 表示启动这个单元测试类(使这个类可以运行),需要传递一个参数,必须是SpringRunner的实例类型
@RunWith(SpringRunner.class)
public class UserMapperTests {

    @Autowired
    private UserMapper userMapper;
    /**
     * 单元测试方法:(可以单独独立运行,不用启动整个项目)
     * 1. 必须被@Test注解修饰
     * 2. 返回值类型必须是void
     * 3. 方法的参数列表不能指定任何类型
     * 4. 方法的访问修饰符必须是public
     */
    @Test
    public void insert() {
        User user = new User();
        user.setjAccount("13579");
        user.setjPwd("123");
        Integer rows = userMapper.insert(user);
        System.out.println(rows);
    }
}

这里如果在自动装配声明mapper层接口的时候报错的话,也就是

@Autowired
private UserMapper userMapper;

这里的userMapper如果有一段红色的波浪线,

因为IDEA有检测的功能,接口是不能够直接创建Bean的,具体啥意思我也不懂,反正,解决方法,把权限等级降低:

1.3 点击如下图所示位置,运行测试类

1.4  看控制台是否成功

1.5  如果报错了,则(去找找别的博客吧)

(1)检查数据库是否成功连接;

(2)检查xml文件是否书写有误;

(3)确认你的测试类中传递的参数是否正确,以及传递的内容是否符合要求。

可能还有别的错误原因,根据控制台报错提示慢慢找吧emmmm

如果你的注册功能还有其他操作,也可以一并测试,比如你想在注册之前先查询该账号是否已经存在,在测试类中继续写查询的测试方法就行。

2. 业务层测试(service)

如果我们的持久层没问题的话,那么再进行业务层测试吧

2.1  同样的,我们先在test文件夹中如下位置创建一个service包,在包中新建一个测试类,命名为UserServiceTests

2.2  对service层进行测试,这里我有对处理异常进行测试,如果service层中没有异常处理的相关代码的话,直接进行注册的插入操作就行了,即将try catch的方法省略,直接写try中的代码即可

package com.gp.recruit.service;

import com.gp.recruit.demos.web.entity.User;
import com.gp.recruit.demos.web.service.IUserService;
import com.gp.recruit.demos.web.service.ex.ServiceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceTests {

    @Autowired
    private IUserService userService;
    @Test
    public void reg() {
        try {
            User user = new User();
            user.setjAccount("721");
            user.setjPwd("1235678910");
            userService.reg(user);
            System.out.println("OK");
        } catch (ServiceException e) {
            // 获取类的对象,再获取类的名称
            System.out.println(e.getClass().getSimpleName());
            // 获取异常的具体描述信息
            System.out.println(e.getMessage());
        }
    }
}

2.3  运行这个测试方法

2.4  控制台出现OK即为成功,说明service层没有问题

2.5  如果报错了,则说明service层有问题,可以检查接口参数类型是否匹配啥的,具体的还是根据控制台信息查看错误原因。

3. 检查控制层代码(controller)

应该大概都没问题吧,就,检查一些接口吧emmmm,启动项目后直接访问登录注册的页面。

我们先看一下控制层代码,可以看到我的代码中,如果要访问注册界面,需要先访问users界面

package com.gp.recruit.demos.web.controller;

import com.gp.recruit.demos.web.entity.User;
import com.gp.recruit.demos.web.service.IUserService;
import com.gp.recruit.demos.web.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController // @Controller + @ResponseBody(响应结果以json格式进行数据的响应给到前端)
@RequestMapping("users")
public class UserController extends BaseController {
    @Autowired
    private IUserService userService;

    @RequestMapping("reg")
    public JsonResult<Void> reg(User user) {
        userService.reg(user);
        return new JsonResult<>(OK);
    }
}

启动项目后,我们直接在浏览起中打开localhost:8080/users/reg?jAccount=654321&jPwd=123456,也就是说,我在注册页面中输入jAccount的值为654321以及jPwd的值为123456

如果你是先做了前面的测试,那么需要注意修改启动项目

完成浏览器中的插入之后,在数据库中查看数据是否被插入,我这个密码长得比较奇怪是因为我对密码进行加密处理了,没有加密处理的话显示的就是你输入的密码值,也就是123456

如果前面都没报错,这里报错了的话,可以检查一下接口,我这里是需要先访问users,再访问reg的,根据自己的控制层代码确认一下接口。

4. 确认是前端代码的问题

这里只有我出现过的问题,可能还会有别的问题,不过如果前面的测试都没问题,则可以确认是前端代码的问题了。

4.1  确认与控制层的接口

这里我用的是ajax函数,url就是我们需要访问的地址,也就是注册页面,data中获取表单数据,注意这个接口名称需要与你前面的表单id一致。

4.2  表单method属性

首先是需要将input标签放入一个表单内,并且给这个表单加上method属性

             <form action="/users/reg" id="form-reg" method="post">
                <!-- 手机号输入框 -->
                <img src="../img/user.svg" class="icon" alt=""/>
                <input id="j_account" type="text" name="jAccount" class="input" placeholder="手机号码" /><br>
                <!-- 密码输入框 -->
                <img src="../img/square-lock.svg" class="icon" alt=""/>
                <input id="j_pwd" type="Password" name="jPwd" class="input" placeholder="密码" /><br>
                <!-- 重复密码输入框 -->
                <img src="../img/square-lock.svg" class="icon" alt=""/>
                <input id="j_pwd_s" type="Password" class="input" placeholder="再次输入密码" /><br>
                <span id="msg" class="emptyWarn"></span><br>
            </form>

我一开始忘记加这个属性了,注册方法一般使用POST,这是我在看上去似乎比较官方的网站上看到的,总之,注册使用POST就没错了。

4.3  input标签的name属性

这个name属性就是对应的接口,需要与你的参数名保持一致

4.4  参数命名不规范导致无法接收数据

在数据库中我们经常会出现如 j_account 这样的字段,但似乎在java中并不支持这种命名方式,需要使用大头命名法(应该是这个名字),即 jAccount,但在数据库中并没有区分大小写,即,如果你在数据库中设置字段名为 jAccount,那么它在java中就变成了 jaccount,并且还会给你画一条波浪线提示你拼写错误。

那么如果我的数据库中字段是如 j_account 这种形式的怎么办呢?

需要在mapper层中,注册方式对应的xml文件中加入自定义映射规则

<!-- 自定义映射规则:resultMap标签来完成映射规则的定义 -->
    <!--
        id属性:标签给这个映射规则分配一个唯一的id值,对应的就是resultMap=“id的属性值”
        type属性:取值是一个类,表示的是数据库中的查询结果与java中哪个实体类进行结果集的映射
     -->
    <resultMap id="UserEntityMap" type="com.gp.recruit.demos.web.entity.User">
        <!-- 将表的字段和类的属性不一致的字段进行匹配指定,名称一致的字段可以省略不写 -->
        <!--
            配合完成名称不一致的映射:
            column属性:表示表中的资源名称
            property属性:表示类中的属性名称
        -->
        <!-- 在定义映射规则时,主键不可省略 -->
        <result column="j_account" property="jAccount"></result>
        <result column="j_pwd" property="jPwd"></result>
        <result column="j_name" property="jName"></result>
        <result column="j_sex" property="jSex"></result>
        <result column="j_state" property="jState"></result>
        <result column="j_tel" property="jTel"></result>
    </resultMap>

然后修改实体类,顺便再检查一下其他地方的参数名

/** 用户的实体类 */
public class User implements Serializable {
    private String jAccount;
    private String jPwd;
    private String salt;
    private String jName;
    private Integer jSex;
    private Integer jState;
    private String jTel;
// get和set等方法已省略
}
4.5  其他原因

如果以上都没能解决你的问题,可以考虑一下:

(1) 确保前端发送的请求中参数名称与实体类中字段名称一致,且数据类型匹配;

(2)如果使用了JavaScript框架(jQuery、axios等),确保构建对象正确并发送了数据。

(3)这是我在做的时候知道的可能出现的问题,如果至此你的问题还没有解决,那就只能祝你好运了。

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值