开发规范
安全开发
商城前端要对传到后端的敏感信息进行加密,后端要注意解密
注意事项
- 在查询实体类列表时要添加逻辑删除标记。
- 在 Controller 层要对参数进行判空。
- 在 ServiceImpl 层对参数进行权限校验,通过缓存获取当前登陆人信息,判断当前登陆人是否有查询相关内容的权限(防止水平越权),同时也要在 GateWay 网关中添加防止水平越权的配置信息(兜底)。
- 禁止在 for 循环中更新数据库,避免在 for 循环中查询数据库,如果需要查询和更新的条数较多,建议直接在 Mapper 层写 Sql 语句。
- 在功能已经完成的代码中添加代码时要添加注释,方便快速定位问题。如果其中包含对外接口(对外接口也要有成功的日志),要进行异常捕获。
- 涉及到前后端交互,在传递参数中,如果存在年龄列表,并要对其中部分年龄做特殊处理。如
代码块1 所示,如果 获取年龄列表 中有 投保年龄+1 对应的值,前端在显示时要将年龄列表中的值替换为 投保年龄+1 字符串;可以将年龄列表替换为键值对的形式;这样可以节省一个参数,方便后序调用。
- 如果遇到感到奇怪的问题,比如:在校验规则列表中显示了这个规则,但实际上并没有进行校验,那么很可能是中间出现 Exception ,而这个异常又被捕获掉了,要打印上下多行日志进行查找。
代码块1
1 2 3 4 5 6 7 8 9 10 11 12
| "getAgeOptions": [ "62", "65" ] "insuredAgeAdd": "62"
"getAgeOptions": [ "62":"投保年龄+1", "65":"" ]
|
异常日志
异常信息应该包括两类信息:案发现场信息 e.getMessage() 和异常堆栈信息 e,至少应该包括异常堆栈信息 e
1
| logger.error(各类参数或者对象toString + "_" + e.getMessage(), e);
|
调用外部API接口
在调用外部API接口时要加上对返回结果异常判断
开发时出现的问题
创建包 package & 创建目录 Directory
在 src/main/java 目录下创建包直接用 com.test 即可,不使用 com/test
创建目录如下:下面的 / 和 \ 只是用 . 创建出的目录的举例
不要将引用变量定义为 final
Spring 中的 Bean 默认都是单例的。整个容器只有1个实例,容器启动时创建,容器关闭时销毁
final修饰的filledFieldCodes一直会被该实例引用,所以一直不会被垃圾回收,从而一直在添加新数据,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Component public class DeepSeekSuggestionBOImpl implements DeepSeekSuggestionBO { private final Logger logger = LoggerFactory.getLogger(getClass()); private final Set<String> filledFieldCodes = new HashSet<>(); private String buildMissingFieldsText(String customerNo) throws Exception { List<FieldMetadata> allFields = getAllGridFields(); if (CollectionUtil.isEmpty(allFields)) { return ""; }
List<CustomerOtherInfo> filledFields = getFilledFields(customerNo);
if (CollectionUtil.isNotEmpty(filledFields)) { filledFieldCodes.addAll(filledFields.stream() .map(CustomerOtherInfo::getFieldCode) .collect(Collectors.toSet())); }
} }
|
判断非null也要判断非空
防止前端落表传入为空字符串或者防止查出数据库中为空字符串的脏数据。
1 2 3 4 5 6 7 8 9
| private List<CustomerOtherInfo> getFilledFields(String customerNo) { CustomerOtherInfoExample example = new CustomerOtherInfoExample(); example.createCriteria() .andCustomerNoEqualTo(customerNo) .andFieldValueIsNotNull() .andIsDeleteEqualTo(0); return customerOtherInfoDAO.selectByExample(example); }
|
Controller返回内容 result 为对象/列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| { "code": 200, "message": "成功", "data": { "id": 1, "name": "张三", "age": 25 } }
{ "code": 200, "message": "成功", "data": [ {"id": 1, "name": "张三", "age": 25}, {"id": 2, "name": "李四", "age": 30} ] }
@GetMapping("/dashboard") public Map<String, Object> getDashboard() { Map<String, Object> result = new HashMap<>(); result.put("totalUsers", 100); result.put("userList", userService.getAllUsers()); result.put("avgAge", 28.5); return result; }
{ "totalUsers": 100, "userList": [ { "id": 1, "name": "张三", "age": 25 }, { "id": 2, "name": "李四", "age": 30 } ], "avgAge": 28.5 }
|
参考书
阿里巴巴Java开发手册 1.3.1
https://pan.baidu.com/share/init?surl=kYxn40FpCUpBd0lhoy192A&pwd=29d7