当前位置: 首页 > news >正文

临时造参数查全量数据

场景:

在开发的时候,需要查询全量数据,但是此时现有的接口需要管理员才有权限查询全量数据。我们用postman测试的时候,代码无误;但是将它作为定时任务放到xxl-job的时候,因为这个技术是没有携带任何参数的,即不是管理员权限,无法查询全量数据,并且在查询的时候,因为没有当前用户,而我们代码中又需要获取当前用户的属性,自然就报空指针异常了。解决方案如下:

方法一

代码在本地测试可以正常运行,但是将其放到定时任务调度中心xxl-job的时候,却一直报空指针异常;

原因是,在本地用Apipost测试的时候,是携带管理员参数的;但是xxl-job测试的时候,是不携带任何参数的,当代码运行到User user = userService.getById(bladeUser.getUserId());时,因为bladeUser.getUserId()中的bladeUser为null,所以报空指针异常。这个子方法是别人写的,按照部门id去查询当前部门下的所有数据,但是我们需要的是查询所有部门的信息,这就需要构建一个具备管理员权限的身份,即给bladeUser赋值,并且需要是管理员权限,才能不报空指针异常以及让方法查询符合我们的业务要求。

Apipost里接口测试是存在参数的,具有管理员权限,所以代码运行的时候在bladeUser.getUserId()中可以获取当前管理员下的用户id信息,即不会报空指针异常;但是如果是xxl-job调用这个接口的时候,因为xxl-job调用方法是不携带参数的,所以运行到此处时,会报空指针异常。在这在情况下,要么重新自己写一个方法查询数据;要么自己构建一个具备管理员权限的bladeUser对象,让其以参数的形式传递过来,这个值必须是管理员权限,因为我们的业务要求是查询所有部门的信息,只有管理员才有权限查询。

在参数管理模块新增一个参数,这个参数的值必须是从用户表里面可以查询出来的管理员;

上面的操作会把数据保存在数据库中参数表中

这一操作的代码是:

INSERT INTO `yourong_loan_test`.`blade_param` ( `id`, `param_name`, `param_key`, `param_value`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted` )
VALUES( 1957315979501801474, '管理员账号', 'managerAccount', 'admin', NULL, 1123598821738675201, 1123598813738675201, '2025-08-18 13:37:49', 1123598821738675201, '2025-08-18 13:41:54', 1, 0 );

接下来就是对自己的代码改造,

思路是:

先通过参数服务获取预配置的管理员账号,若未配置则抛出异常提示,接着根据该账号查询对应的用户信息,若用户不存在也抛出异常,然后将查询到的用户信息复制到 BladeUser 对象并设置用户 ID,最后使用这个具备管理员权限的 BladeUser 对象调用下游的今日统计数据查询方法,以确保能获取所有数据。(取值的过程),这一就解决了xxl-job调用该接口,因为没有携带管理员参数而导致的空指针异常的问题。

然后,在xxl-job中测试,

调用一次测试:

图片中的信息可知,在对我们自己创建的bladeUser对象设置用户id的时候,成功的把值设置进去了;

下游方法通过bladeUser.getUserId()也可以正常的取值,并且取得的这个用户id是在数据库中存在的具备管理员权限的用户id,这样,就解决了xxl-job调度接口的时候无法携带参数的问题,避免了空指针问题,也成功复用了之前就已经存在的方法,这对于自己重新写一个方法而言,简单了很多。

在这里,贴一下参数服务的代码:

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.yourong.swagger.SwaggerVersion;
import com.yourong.swagger.SwaggerVersionEnum;
import io.swagger.annotations.*;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.system.dto.MonthOption;
import org.springblade.modules.system.dto.RateOption;
import org.springblade.modules.system.dto.RentType;
import org.springblade.modules.system.entity.Param;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IParamService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;import static org.springblade.core.cache.constant.CacheConstant.PARAM_CACHE;/*** 控制器** @author Chill*/
@NonDS
@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_SYSTEM_NAME + "/param")
@Api(value = "参数配置", tags = "参数配置")
public class ParamController extends BladeController {private final IParamService paramService;private final IUserService iUserService;/*** 详情*/@GetMapping("/detail")@ApiOperationSupport(order = 1)@ApiOperation(value = "详情", notes = "传入param")public R<Param> detail(Param param) {Param detail = paramService.getOne(Condition.getQueryWrapper(param));return R.data(detail);}/*** 分页*/@GetMapping("/list")@ApiImplicitParams({@ApiImplicitParam(name = "paramName", value = "参数名称", paramType = "query", dataType = "string"),@ApiImplicitParam(name = "paramKey", value = "参数键名", paramType = "query", dataType = "string"),@ApiImplicitParam(name = "paramValue", value = "参数键值", paramType = "query", dataType = "string")})@ApiOperationSupport(order = 2)@ApiOperation(value = "分页", notes = "传入param")public R<IPage<Param>> list(@ApiIgnore @RequestParam Map<String, Object> param, Query query) {IPage<Param> pages = paramService.page(Condition.getPage(query), Condition.getQueryWrapper(param, Param.class).orderByDesc("create_time"));return R.data(pages);}/*** 新增或修改*/@PostMapping("/submit")@ApiOperationSupport(order = 3)@ApiOperation(value = "新增或修改", notes = "传入param")public R submit(@Valid @RequestBody Param param) {CacheUtil.clear(PARAM_CACHE);CacheUtil.clear(PARAM_CACHE, Boolean.FALSE);return R.status(paramService.saveOrUpdate(param));}/*** 删除*/@PostMapping("/remove")@ApiOperationSupport(order = 4)@ApiOperation(value = "逻辑删除", notes = "传入ids")public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {CacheUtil.clear(PARAM_CACHE);CacheUtil.clear(PARAM_CACHE, Boolean.FALSE);return R.status(paramService.deleteLogic(Func.toLongList(ids)));}@GetMapping("/basic-config")@SwaggerVersion(version = SwaggerVersionEnum.V2_1_2)@ApiOperationSupport(order = 5)public R<JSONObject> basicConfig(@RequestParam("key") String key , BladeUser bladeUser) {try {JSONObject entries = paramService.jsonValue(key, JSONObject.class);if(entries == null) {entries = new JSONObject();}//当传入的key为loan_type_basic_config时,判断当前用户是否为武汉分公司的用户,如果是则处理entries
//			if ("loan_type_basic_config".equals(key)) {
//				User byId = iUserService.getById(bladeUser.getUserId());
//				if (byId.getDeptId().equals("1587339567565905922")) {
//					disposeEntries(entries);
//				}
//			}return R.data(entries);} catch (Exception e) {return R.data(new JSONObject());}}public static void disposeEntries(JSONObject entries) {if (entries.containsKey("rentTypeList")) {List<RentType> rentTypeList = JSONUtil.toList(entries.getJSONArray("rentTypeList").toString(), RentType.class);//如果不存在36期,则新增36期数据,存在则将利率加入进去boolean flag = true;for (RentType rentType : rentTypeList) {if (Objects.equals(rentType.getValue(), 1)) {RateOption rateOption = new RateOption();rateOption.setLabel("0.88%");rateOption.setValue("0.88");for (MonthOption month : rentType.getMonth()) {//如果存在36期则将利率加上去if (Objects.equals(month.getValue(), 36)) {month.getRate().add(rateOption);flag = false;}}if (flag){MonthOption monthOption = new MonthOption();List<RateOption> rateOptions = new ArrayList<>();List<MonthOption> monthOptions = new ArrayList<>();monthOption.setLabel("36期");monthOption.setValue(36);rateOptions.add(rateOption);monthOption.setRate(rateOptions);monthOptions.add(monthOption);rentType.setMonth(monthOptions);}}}entries.set("rentTypeList", rentTypeList);}}
}
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.system.entity.Param;
import org.springblade.modules.system.mapper.ParamMapper;
import org.springblade.modules.system.service.IParamService;
import org.springframework.stereotype.Service;import java.util.Collections;
import java.util.List;
import java.util.Optional;/*** 服务实现类** @author Chill*/
@Service
public class ParamServiceImpl extends BaseServiceImpl<ParamMapper, Param> implements IParamService {@Overridepublic String getValue(String paramKey) {Param param = this.getOne(Wrappers.<Param>query().lambda().eq(Param::getParamKey, paramKey));if(param == null){return null;}return param.getParamValue();}@Overridepublic <T> T jsonValue(String paramKey, Class<T> clazz) {Param param = this.getOne(Wrappers.<Param>query().lambda().eq(Param::getParamKey, paramKey));return Optional.ofNullable(param).map(o -> JSONUtil.parse(o.getParamValue()).toBean(clazz)).orElse(null);}@Overridepublic <T> List<T> jsonListValue(String paramKey, Class<T> clazz) {Param param = this.getOne(Wrappers.<Param>query().lambda().eq(Param::getParamKey, paramKey));return Optional.ofNullable(param).map(o -> JSONUtil.toList(o.getParamValue(), clazz)).orElse(Collections.emptyList());}
}

分析:

这段代码是ParamServiceImpl服务实现类的具体实现,它继承自BaseServiceImpl并实现了IParamService接口,主要用于处理系统参数相关的操作。首先,getValue方法通过参数键查询对应的参数实体,若不存在则返回null,否则返回参数值;jsonValue方法则是在获取参数后,将参数值从JSON格式解析为指定类型的对象,若参数不存在则返回null;jsonListValue方法类似,但会将JSON格式的参数值解析为指定类型的列表,若参数不存在则返回空列表,整体通过MyBatis-Plus的查询方法和Hutool的JSON工具类实现了参数的获取与格式转换功能。

CREATE TABLE `blade_param` (`id` bigint DEFAULT NULL,`param_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,`param_key` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,`param_value` text,`remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,`create_user` bigint DEFAULT NULL,`create_dept` bigint DEFAULT NULL,`create_time` datetime DEFAULT NULL,`update_user` bigint DEFAULT NULL,`update_time` datetime DEFAULT NULL,`status` int DEFAULT NULL,`is_deleted` int DEFAULT NULL,PRIMARY KEY (`param_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;

方法二

因为下游方法需要的是bladeUser.getUserId(),我们只需要保证bladeUser不为空并且bladeUser.getUserId()的值在数据库中存在并且其对应的account是管理员权限,我们就可以解决这一问题并且符合我们要求的业务逻辑。另一种简单的方法就是,我们直接在自己的方法上构造一个对象,把下游方法中需要的bladeUser.getUserId()设置为一个常量值,这个常量值必须在数据库中存在并且其对应的的权限为管理员。将方法一的代码注释,然后新添加如下方法:

运行,测试:

从图中可得知,我们成功给当前构造的对象设置了用户id值,为1123598821738675201;

这个值在数据库中存在,并且其对应的是管理员权限,放行请求;

下游方法中也确实是收到了id值,代码运行正常。这在方法有点硬编码,必须的保证数据库中有这个值,并且这个值是管理员权限,除此之外,在后期系统维护的时候,这个值不能更改,否则代码依旧会存在空指针异常。

http://www.dtcms.com/a/453309.html

相关文章:

  • 国产能谱仪设计与验证核心经验教训简化表
  • 0.6 卷积神经网络
  • 架设网站flash不显示深圳网站自然优化
  • C++ ros2 debug
  • 深入解析:Object.prototype.toString.call() 的工作原理与实战应用
  • 浙江建设网站公司广告点击一次多少钱
  • 图表全能王 (ChartStudio) 新增多种图表支持,助力数据可视化
  • 网页制作免费网站网页制作工作总结
  • java快速复习
  • Day 24 - 文件、目录与路径 - Python学习笔记
  • 第9讲:函数递归——用“套娃”思维解决复杂问题
  • 东莞网站竞价推广运营百度云虚拟主机如何建设网站
  • 权限管理混乱微服务安全架构:OAuth2.0+JWT无感刷新方案非法请求拦截率
  • 北京理工大学网站开发与应用彩票网站开发彩票网站搭建
  • 网站建设公司重庆装修设计公司公司价格表
  • 厦门市建设局查询保障摇号网站首页系统开发板价格
  • 金溪网站建设制作电商系统开发公司
  • 直方图 vs 箱线图:两种看数据分布的思路差异
  • 构建AI智能体:五十六、从链到图:LangGraph解析--构建智能AI工作流的艺术工具
  • 【Spring】AOP的核心原理配方
  • 惠州建站平台建筑人才网招聘信息
  • 《Cargo 参考手册》第一章:清单
  • MVCC 多版本并发控制
  • 【AI智能体】Coze 打造AI数字人视频生成智能体实战详解:多模态情感计算与云边协同架构
  • 重庆网站建设培训机构学费重庆市官方网站
  • 关系建设的网站上海网站seo招聘
  • Vue router-view和router-link分开写在不同的组件中实现导航栏切换界面
  • Wan2.2-Animate V2版 - 一键替换视频角色,实现角色动作及表情同步迁移替换 支持50系显卡 ComfyUI工作流 一键整合包下载
  • Coordinate Attention for Efficient Mobile Network Design 学习笔记
  • 初识MYSQL —— 数据类型