小工具知识网

当前位置: 首页 > 行业知识 > 完整诞生平庸前后端是怎么样开发 的

行业知识

完整诞生平庸前后端是怎么样开发 的

2026-11-08 14:01:09 来源:互联网转载

完整的电商平台后端API开发总结(三)

���册  |  登录KEY

前言

经过两篇文章的介绍相信大家已经完成了项目开发环境的基础搭建;并且使用MyBatis的逆向工程生成了我们所需要的的数据库表对应Mapper;通过对Spring事务隔离级别的熟悉,也完成了Mapper接口的基本了解和使用,那么;从这一篇开始,我们进入正式的功能实现和代码编写。 

流程简述

    对于开发一个Web项目来说,无论是电商还是其他品类的项目,注册与登录模块都是必不可少的;注册登录功能也是我们在日常生活中最长接触的,对于这个业务场景的需求与逻辑大概是没有什么需要详细介绍的,市面上常见的邮箱注册、手机注册、账号密码注册,其处理方式基本相同,我们这里使用账号密码注册的方式,实现整个平台的注册/登录功能;

让我们开始!

判断用户名是否存在

    实现注册部分的代码,首先想到的就是,我们要对前端所发送过来的请求参数做验证,在有些项目中,会将请求参数的格式验证和合法性验证只写在前端校验,而后端只实现业务逻辑,我认为这是极其危险的编码习惯;当我们的项目放在线上的时候,就会有恶意用户绕过前端验证,直接访问我们的服务器,对线上业务造成破坏,因此前端验证是为了减轻一部分请求直接到达后端,但是相应的验证后端也要去做

    那么,首先我们要实现的就是验证用户注册的用户名是否存在;我们首先来看一下用户表的结构及设计:

从图上我们可以看到用户表中常用的字段,我们用户表以用户的Id为主键,但注意:ID并不是自增长的,这与传统的Id设计不同,这里不是自增的原因是:当系统达到一定的体量时,用户数量激增,我们需要去做分布式集群,需要分库分表,这时自增的ID会给分库分表带来极大的困难,因为,出于日后系统优化的考虑,我们这里的数据库主键,不是自增的。

接口接入开发

    理清业务逻辑,看完数据库结构,我们着手开始编写业务代码;在整个项目代码的编写和接口的实现我们都遵循自底向上的方式,从数据库开始,实现数据的映射,业务实现,结果推送的流程,对应pojo映射---Service编写---Controller控制的过程。

    那么,我们开始啦:首先,我们创建一个UserService接口,在接口中,我们编写我们第一个业务方法:

  • /** * 判断用户名是否存在 */public boolean queryUsernameIsExist(String username);

    我们传入一个userName,返回一个布尔值;有了接口之后,我们去实现这个方法:

    我们在service工程中,新建一个Impl的包,在里面新建一个类UserServiceImpl,去实现UserService接口,并实现其中的方法;我们在这个方法中,需要操作User这个实体类,那么我们先把UserMapper引入进来:

    • @Autowiredpublic UsersMapper usersMapper;

      在方法中,我们使用Example这种使用条件查询的方式去做查询:

      • @Transactional(propagation = Propagation.SUPPORTS)@Overridepublic boolean queryUsernameIsExist(String username) {    Example userExample = new Example(Users.class);    Example.Criteria userCriteria = userExample.createCriteria();    userCriteria.andEqualTo("username",username);    Users result  = usersMapper.selectOneByExample(userExample);    return result == null ? false : true;}

            在这个方法的实现中,我们使用了Example这种方式,Example映射一个实体类,获得一个example对象,为这个对象去添加相应的条件,Criteria对应的方法有很多,可以判断等于,大于,相似等各类条件,使用起来很方便,感兴趣的同学可以去阅读他的源码;这个方法返回一个Users对象,我们去判空,若为空,则用户名可用,若false,则用户名存在;

            实现了Service之后,我们来编写Controller,我们在api工程中,新建一个Controller类。命名为PassportController,我们为他加上RestController注解,并加上路由地址,在这个Controller中,我们需要操作UserService来进行查询,那么,我们先将UserService注入进来:

        • @Autowiredprivate UserService userService;

          并定义一个方法,声明方法的路由地址:

          • @GetMapping("/usernameIsExist")public IMOOCJSONResult usernameIsExist(@RequestParam String username) {    //判断用户名不能为空    if (StringUtils.isBlank(username)) {        return IMOOCJSONResult.errorMsg("用户名不能为空");    }    //查找注册的用户名是否存在    boolean isExist = userService.queryUsernameIsExist(username);    if (isExist) {        return IMOOCJSONResult.errorMsg("用户名已经存在");    }    // 请求成功,用户名没有重复    return IMOOCJSONResult.ok();}

                在这个方法中,我们在判断username为空的时候使用了一个字符串的工具类,他是Apache提供的,我们需要首先引入他的依赖:

            •     commons-codec    commons-codec    1.11    org.apache.commons    commons-lang3    3.4    commons-io    commons-io    1.3.2

              引入之后,我们便可以操作StringUtils,他提供了一个isBlank的方法,来判断字符串是否为空;

                  同时我们在方法中,可以看到一个IMOOCJSONResult对象,这是一个结果集对象,因为在代码中,我们需要返回的结果值类型很多,很不确定,并且,我们需要返回自定义的响应码来告诉前端请求成功与否,前端对约定好的各类返回值做统一处理,避免前端出现代码报错,影响用户体验,同时,自定义的结果响应能提高我们定位错误的速度,规范接口;因此我们先定义一个结果返回类:

              • public class IMOOCJSONResult {    // 定义jackson对象    private static final ObjectMapper MAPPER = new ObjectMapper();    // 响应业务状态    private Integer status;    // 响应消息    private String msg;    // 响应中的数据    private Object data;    ...}

                完整的类代码请大家去看源码,不方便在这里粘贴全部代码,只提供类中的属性供大家参考,大家可以参考对应的实现思路去封装自己的结果集,我们使用这样统一的结果类便可以在返回数据的同时,返回请求状态码给前端,提高接口可读性和稳定性。

                接口测试

                    当我们第一个接口编写完成后,我们使用PostMan进行接口测试,postman是一款开源免费的接口调试工具,可以模拟客户端发出请求,是后端开发必备工具:

                我们可以看到,我们的请求是成功的,当然图示中,我请求的是我的生产服务器接口,大家在本机调试的时候URL应该是localhost开头的,我们可以看到请求结果的响应也是我们封装的结果集的响应,有响应码和数据体组成,大家可以认识更换请求数据,测试接口功能的完整性。

                用户注册

                完成了第一个判断用户名是否存在的接口后,我们着手开始进行用户注册的逻辑编写,首先我们在注册的时候,依然是操作UserMapper,所以数据层是已经准备好的,我们在UserService中,定义第二个创建用户的方法:

                • /** * 创建用户 * @param userBO * @return */public Users createUser(UserBO userBO);

                  这个方法会接收一个表单数据,数据包中包含密码,用户名,甚至更多的信息,如果我们在后端一个一个的接收,显然是不合理的,当请求参数过多时,我们便将请求参数封装成一个请求的实体类,在这里我们封装一个UserBO:

                  • public class UserBO {    @ApiModelProperty(value = "用户名",name = "username",example ="张三",required =true)    private String username;    @ApiModelProperty(value = "密码",name = "password",example ="123456",required =true)    private String password;    @ApiModelProperty(value = "确认密码",name = "confirmPassword",example ="123456",required =false)    private String confirmPassword;    ...}

                    get/set方法大家自行生成,方法定义好后,我们去实现类中,实现他:

                    • @Transactional(propagation = Propagation.REQUIRED)@Overridepublic Users createUser(UserBO userBO) {    //使用工具类生成唯一id    String userId = sid.nextShort();    Users user = new Users();    user.setId(userId);    user.setUsername(userBO.getUsername());    try {        user.setPassword(MD5Utils.getMD5Str(userBO.getPassword()));    } catch (Exception e) {        e.printStackTrace();    }    //默认用户昵称同用户名    user.setNickname(userBO.getUsername());    //默认头像    user.setFace(USER_FACE);    //默认生日    user.setBirthday(DateUtil.stringToDate("1970-01-01"));    //设置性别(使用枚举操作)默认为:保密    user.setSex(Sex.secret.type);    user.setCreatedTime(new Date());    user.setUpdatedTime(new Date());    usersMapper.insert(user);    return user;}

                      我们在这里存储密码时,使用了MD5加密机制,防止数据库资源泄露,导致用户数据泄露,保证数据的安全性,MD5的工具类大家可以在源码中获取,我就不贴在这里了;同时使用的工具类还有日期格式化工具类,同样的,大家在源码中获取;我们在新建用户设置性别时,我们可以使用枚举的形式去定义用户的性别,增强代码的可读性:

                      • /** * @Desc:性别枚举 */public enum Sex {    woman(0,"女"),    man(1,"男"),    secret(2,"保密");    public final Integer type;    public final String value;    Sex(Integer type, String value) {        this.type = type;        this.value = value;    }}

                        我们在生成唯一ID的时候,我们也会使用工具类,注入Sid对象,使用org.n3r.idworker中的方法为了使用其他包中的方法,我们需要SpringBoot在启动时,扫描到idworker,我们需要在Application中配置:

                        • //扫描所有包,以及相关组件包@ComponentScan(basePackages = {"com.imooc","org.n3r.idworker"})

                          接口实现

                          写完Service,我们回到PassportController,因为是一个保存数据的方法,我们使用Post的方式:

                          • @ApiOperation(value = "用户注册",notes ="用户注册",httpMethod = "POST")@PostMapping("/regist")public IMOOCJSONResult regist(@RequestBody UserBO userBO,                              HttpServletRequest request,                              HttpServletResponse response){    String username = userBO.getUsername();    String password = userBO.getPassword();    String confirmPwd = userBO.getConfirmPassword();    System.out.println(username);    System.out.println(password);    System.out.println(confirmPwd);    // 判断用户名和密码必须不为空    if (StringUtils.isBlank(username) ||        StringUtils.isBlank(password) ||        StringUtils.isBlank(confirmPwd)) {        return IMOOCJSONResult.errorMsg("用户名及密码不能为空");    }    // 查询用户名是否存在    boolean isExist = userService.queryUsernameIsExist(username);    if (isExist) {        return IMOOCJSONResult.errorMsg("用户名已经存在");    }    // 密码长度不能小于6位    if (password.length()  

                            Controller的实现的没有什么注重的点,我们接收到前端传来的数据包,解析数据包中的属性,进行校验,校验通过,调用Service层的方法,实现注册;同样的,对于这个方法,我们使用PostMan进行调试。

上一篇:紫鸟怎么登服务器?

下一篇:宝塔面板怎么修改支付?