统一Controller层命名规则与编码习惯:提升Spring Boot项目开发效率与可维护性

背景:

关于基类控制层的改造实践,网上其实有很多不同的通用controller层的模块,在实际开发过程,会遇到各种各样的问题,还是在Service层的通用改造案例。后台代码使用的若依Spring Boot、Spring Cloud & Alibaba架构搭建。内置了一些基础的核心功能模块。

在实际的开发过程中,开发人员编码习惯,思考方式各不相同,导致controller控制层常用的增删查改命名规则各不相同,增加前后端开发人员,交流和阅读难度。在此环境下,统一常用方法的命名规则和编码习惯,形成统一的代码风格。便于后续人员的开发和理解。

统一命名规则

  1. 方法命名:为了保证一致性,可以约定使用动词+名词的方式来进行方法命名,例如addUser, deleteUser, updateUser, getUserById等。这样不仅可以让API更加直观易懂,同时也方便前端开发人员快速定位和调用接口。

  2. 参数传递:定义一套通用的请求参数规范,比如所有的查询条件都封装在一个名为query的对象中,更新操作的参数则使用updateInfo这样的命名模式。

  3. 响应格式:统一响应的数据格式,例如返回一个包含状态码(status)、消息(message)以及数据(data)的JSON对象。这有助于减少前端解析数据的工作量,并且在出现错误时能够快速定位问题。

编码习惯

  1. 注释规范:确保每个控制器方法都有适当的注释说明其功能、输入输出参数以及可能抛出的异常。这有助于新加入团队的成员更快地理解业务逻辑。

  2. 异常处理:为所有可能产生异常的操作提供统一的异常处理机制。可以在基类控制器中实现全局异常处理器,捕获并统一格式化异常信息。

  3. 分层设计:坚持分层架构原则,确保Controller层只负责接收请求和返回响应,具体的业务逻辑应该交给Service层来处理。这样可以保持控制器的简洁性,并且易于测试。

团队沟通

  • 定期组织代码审查会议,鼓励团队成员分享最佳实践,讨论存在的问题并提出改进措施。

  • 创建文档或Wiki页面记录编码规范,让每位开发者都能随时查阅。

技术体系:

基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构。
后端采用Spring Boot、Spring Cloud & Alibaba。

问题现象:

 第一步:创建一个web层通用数据处理controller-BaseController


import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sunward.common.i18n.utils.I18nUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import javax.servlet.http.HttpServletRequest;

/**
 * web层通用数据处理
 * 
 * @author sunward
 */
public class BaseController
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 将前台传递过来的日期格式的字符串,自动转化为Date类型
     */
    @InitBinder
    public void initBinder(WebDataBinder binder)
    {
        // Date 类型转换
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
        {
            @Override
            public void setAsText(String text)
            {
                setValue(DateUtils.parseDate(text));
            }
        });
    }

    /**
     * 响应请求分页数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected TableDataInfo getDataTable(IPage<?> list)
    {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(list.getRecords());
        rspData.setMsg(I18nUtil.getMessage("query.success"));
        rspData.setTotal(list.getTotal());
        return rspData;
    }

    /**
     * 返回成功
     */
    public AjaxResult success()
    {
        return AjaxResult.success();
    }

    /**
     * 返回成功消息
     */
    public AjaxResult success(String message)
    {
        return AjaxResult.success(message);
    }

    /**
     * 返回成功消息
     */
    public AjaxResult success(Object data)
    {
        return AjaxResult.success(data);
    }

    /**
     * 返回失败消息
     */
    public AjaxResult error()
    {
        return AjaxResult.error();
    }

    /**
     * 返回失败消息
     */
    public AjaxResult error(String message)
    {
        return AjaxResult.error(message);
    }

    /**
     * 返回警告消息
     */
    public AjaxResult warn(String message)
    {
        return AjaxResult.warn(message);
    }

    /**
     * 响应返回结果
     * 
     * @param rows 影响行数
     * @return 操作结果
     */
    protected AjaxResult toAjax(int rows)
    {
        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 响应返回结果
     * 
     * @param result 结果
     * @return 操作结果
     */
    protected AjaxResult toAjax(boolean result)
    {
        return result ? success() : error();
    }
}

第二步:创建一个抽象父类ObjectService<T1, T2>接口,让其他方法继承extends

备注:T1:前端传参给后台的交互实体,例如:***Param;T2:后台传参给前端的交互实体,例如:***Vo(这个规则,可以根据自己的项目要求,具体定义,没有强制要求)


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.util.List;

/**
 * Title: com.sunward.common.business.service.base
 * Description:基类Service
 * Copyright: Copyright (c) 2024
 * Company:
 *
 * @author :mingF
 * @version :3.2.9
 * @date :2024/09/4 09:11
 */
public interface ObjectService<T1, T2>  {
      /**
       * @description : 新增
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :int
       **/
      int save(T1 entity);

      /**
       * @description : 修改
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :int
       **/
      int update(T1 entity);

      /**
       * @description : 删除
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :int
       **/
      int delete(T1 entity);

      /**
       * @description : 查询单条
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :T
       **/
      T2 getOne(T1 entity);

      /**
       * @description : 根据id查询单条
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :T2
       **/
      T2 getOneById(Long id);
      /**
       * @description : 查询多条
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :List<T2>
       **/
      List<T2> getListById(Long id);

      /**
       * @description : 查询多条
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :List<T2>
       **/
      List<T2> getList(T1 entity);

      /**
       * @description : 分页查询多条
       * @author : mingF
       * @date : 2024/09/4 09:11
       * @return :IPage<T2>
       **/
      IPage<T2> getListByPage(Page page, T1 entity);

}

第三步:创建一个抽象父类ObjectController层,继承和实现上面编写的BaseController,ObjectService


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

/**
 * Title: com.sunward.common.core.web.controller
 * Description:父类控制层(继承该控制层,无需再编写增删查改方法 ,即可获得CRUD对应的方法)
 * Copyright: Copyright (c) 2024
 * Company:
 *
 * @author :mingF
 * @version :3.2.9
 * @date :2024/9/4 16:12
 */
public abstract class ObjectController<T1,T2,Service extends ObjectService<T1,T2>> extends BaseController {

    @Autowired
    Service service;

    /**
     * @description : 新增
     * @author : mingF
     * @date : 2024/9/4 16:12
     * @param t
     * @return :com.sunward.common.core.web.domain.AjaxResult
     **/
    @ApiOperation(value = "添加", notes = "添加")
    @Log(title = "添加", businessType = BusinessType.INSERT)
    @RequiresPermissions("add")
    @PostMapping(value = "/add")
    public AjaxResult add(@Validated @RequestBody T1 t) {
        return toAjax(service.save(t));
    }
    /**
     * @description : 删除
     * @author : mingF
     * @date : 2024/9/4 16:12
     * @param t
     * @return :com.sunward.common.core.web.domain.AjaxResult
     **/
    @ApiOperation(value = "删除", notes = "删除")
    @Log(title = "删除", businessType = BusinessType.DELETE)
    @RequiresPermissions("del")
    @PostMapping("/del")
    public AjaxResult remove(@Validated @RequestBody  T1 t) {
        return toAjax(service.delete(t));
    }

    /**
     * @description :分页列表查询
     * @author : mingF
     * @date : 2024/9/4 16:12
     * @param page
     * @param t
     * @return :com.sunward.common.core.response.ServerResponseEntity<com.baomidou.mybatisplus.core.metadata.IPage<T>>
     **/
    @ApiOperation(value = "分页列表查询", notes = "分页列表查询")
    @RequiresPermissions("list")
    @GetMapping("/list")
    public ResponseEntity<ServerResponse<IPage<T2>>> list(Page page, T1 t) {
        return ResponseEntity.ok().body(ServerResponseEntity.success(service.getListByPage(page,t)));
    }
    /**
     * @description : 通过id查询
     * @author : mingF
     * @date : 2024/9/4 16:12
     * @param id
     * @return :org.springframework.http.ResponseEntity<com.sunward.common.core.response.ServerResponse<T>>
     **/
    @ApiOperation(value = "通过id查询", notes = "通过id查询")
    @GetMapping("/info/{id}")
    public ResponseEntity<ServerResponse<T2>> info(@PathVariable Long id) {
        return ResponseEntity.ok().body(ServerResponseEntity.success(service.getOneById(id)));
    }
    /**
     * @description : 通过id查询
     * @author : mingF
     * @date : 2024/9/4 16:12
     * @param id
     * @return :org.springframework.http.ResponseEntity<com.sunward.common.core.response.ServerResponse<T>>
     **/
    @ApiOperation(value = "通过id查询,返回List<T>对象", notes = "通过id查询,返回List<T>对象")
    @GetMapping("/info/list/{id}")
    public ResponseEntity<ServerResponse<List<T2>>> infoList(@PathVariable Long id) {
        return ResponseEntity.ok().body(ServerResponseEntity.success(service.getListById(id)));
    }
    /**
     * @description : 修改
     * @author : mingF
     * @date : 2024/9/4 16:12
     * @param t
     * @return :com.sunward.common.core.web.domain.AjaxResult
     **/
    @ApiOperation(value = "修改", notes = "修改")
    @Log(title = "修改", businessType = BusinessType.UPDATE)
    @RequiresPermissions("edit")
    @PostMapping("/edit")
    public AjaxResult edit(@Validated @RequestBody  T1 t) {
        return toAjax(service.update(t));
    }

以上为止,前期的准备工作都已经准备好,现在开始写,具体的功能

第四步:创建一个抽象***Service业务Service层,extends ObjectService<***Param,***Vo>


import java.util.List;

/**
 * Title: 
 * Description:业务service
 * Copyright: Copyright (c) 2024
 * Company:
 *
 * @author :mingF
 * @version :3.2.9
 * @date :2024/9/4 8:57
 */
public interface ***Service extends ObjectService<***Param,***Vo> {
    /**
     * @description : 这个方法,可以自己添加
     * @author : mingF
     * @date : 2024/9/5 10:04
     * @return :null
    **/
    int engineerCheck(***Param param);

}

第五步:创建一个抽象***ServiceImpl层,implements  第四步定义的抽象类***Service


import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Title: 
 * Description:业务逻辑Service层
 * Copyright: Copyright (c) 2024
 * Company:
 *
 * @author :mingF
 * @version :3.2.9
 * @date :2024/9/4 9:59
 */
@Service
@Slf4j
public class AfterSaleCheckServiceImpl implements AfterSaleCheckService {


    @Override
    public int save(***Param entity) {
        return 0;
    }

    @Override
    public int update(***Param entity) {
        return 0;
    }

    @Override
    public int delete(***Param entity) {
        return 0;
    }

    @Override
    public ***Vo getOne(***Param entity) {
        return null;
    }

    @Override
    public ***Vo getOneById(Long id) {
        
            return null;
        }
    }
     @Override
    public List<***Vo> getList(***Param param) {
        return null;
    }
    @Override
    public IPage<***Vo> getListByPage(Page page, ***Param param) {
            return null;
        }
    
 
     @Override
    public int engineerCheck(***Param param) {
         return 0;

        }

   
}

第六步:创建一个业务****Controller,extends ObjectController<***Param, ***Vo, ***Service>


import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * Title: 
 * Description:
 * Copyright: Copyright (c) 2024
 * Company:
 *
 * @author :mingF
 * @version :3.2.9
 * @date :2024/9/4 8:54
 */
@Api(tags = "说明")
@RestController
@RequiresPermissions("数据权限标识符")
@RequestMapping(请求路径")
public class ***Controller extends ObjectController<***Param, ***Vo, ***Service> {

}

效果:

常用的增删差改如下所示

 觉得写的不错的朋友,请点点赞!❤❤❤❤❤❤❤❤ 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值