1.自定义模块引入依赖冲突 在原先的时候,我使用的是Ruoyi的框架进行的部分代码的开发,后来我换成了 jeecg-boot,结果在移植代码的时候,发现我以前写的工具类好像有点问题。Annotation-specified bean name ‘redisService’ for bean class [org.jeecg.modules.monitor.service.RedisService] conflicts with existing, non-compatible bean definition of same name and class
这个问题还是因为基础不牢吧。
【解决方案】 在启动类上,将 MapperScan 扫描的路径进行修改。
1 2 3 4 5 @MapperScan(basePackages = {"com.openmap.disaster.*","org.jeecg.*"}) @MapperScan(basePackages = {"com.openmap.disaster.mapper"})
2.tinymce is not defined 我在macos上开发的时候,没有问题,可是到了 windows 进行安装配置之后,打开页面出现了:tinymce is not defined,这个问题。但是我明明就已经安装了 tinymce 了,为什么还是出现报错呢?
【尝试方案】 (1) 我尝试了使用 yarn 进行重新安装和运行,也还是不行。 (2) 尝试:“ yarn add @tinymce/tinymce-vue” 结果也还是不行。 (3) 尝试重新用英文命名文件夹,及其父路径,结果不行。 (4) 尝试找官方,结果没有人理会。 (5) 尝试重新git clone ,发现还是自己的某一个部分的代码有问题,因为官方的代码并没有什么问题。
【解决方案】最后其实没有定位到问题到底出在哪里 我就重新的下载了官方的代码,然后在官方的基础上重新创建了一个分支,把自己的代码从另外一个目录中,重新拷贝复制,将代码进行了替换。竟然奇迹般的好了,但是问题到底出在哪里,还是不知道。
后来我发现在 src\components\Tinymce\src\Editor.vue 这个文件中使用了 tinymce 这个路径的引用,如果报错的话,可以看看这个路径里面有没有这几个资源,这是一个马后炮了。
1 2 3 4 { language_url : publicPath + 'resource/tinymce/langs/' + langName.value + '.js' , skin_url : publicPath + 'resource/tinymce/skins/ui/' + skinName.value ,
3.首屏优化 使用了vite4之后,好像真的变得快了。
4.打包部署 (1)后端
修改 jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml 配置文件,然后在根目录下执行
1 mvn clean package -Pprod
(2)前端 修改项目根路径下的 .env.production 文件,然后执行打包命令
5.扫码登录 我把二维码扫码登录进行了修改,通过集成钉钉的接口,实现了钉钉的二维码扫描登录。主要就是下面几步: (1) 创建一个二维码,前端实时监听二维码的扫码状态 (2) 用户扫码后跳转到二维码扫码接口回调,实现登录,并保存用户信息。 (3) 前端获取到了扫码后的 token,实现登录。
1.修改配置 1 2 3 4 5 6 7 8 9 10 11 12 third-app: enabled: false type: DINGTALK: enabled: true client-id: xx client-secret: xx agent-id: 2682671764
2.修改获取二维码的接口 修改前端获取二维码的地址接口 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java,返回新的二维码。
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 @ApiOperation(value = "登录二维码", notes = "登录二维码") @GetMapping("/getLoginQrcode") public Result<?> getLoginQrcode(HttpServletRequest request) throws Exception{ String qrcodeId = CommonConstant.LOGIN_QRCODE_PRE+IdWorker.getIdStr(); Map params = new HashMap (5 ); params.put("qrcodeId" , qrcodeId); ThirdAppTypeItemVo config = thirdAppConfig.getDingtalk(); StringBuilder builder = new StringBuilder (); builder.append("https://login.dingtalk.com/oauth2/auth" ); String redirectUri = "http://openmap.tech:10001/jeecg-boot/sys/thirdLogin/oauth2/dingtalk/scanlogin" ; builder.append("?redirect_uri=" ).append(URLEncoder.encode(redirectUri, "UTF-8" )); builder.append("&response_type=code" ); builder.append("&client_id=" ).append(config.getClientId()); builder.append("&scope=openid" ); String state = qrcodeId; builder.append("&state=" ).append(state); builder.append("&prompt=" ).append("consent" ); String url = builder.toString(); params.put("url" , url); redisUtil.set(CommonConstant.LOGIN_QRCODE + qrcodeId, qrcodeId, 30 ); return Result.OK(params); }
3.修改扫码登录回调 修改扫码登录后的回调方法,主要就是手机端展示的页面,同时保存用户扫码信息,文件路径:jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/ThirdLoginController.java
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 49 50 51 52 53 54 55 @GetMapping("/oauth2/{source}/scanlogin") public String scanLoginCallback ( @PathVariable("source") String source, // 企业微信返回的code @RequestParam(value = "code", required = false) String code, // 钉钉返回的code @RequestParam(value = "authCode", required = false) String authCode, @RequestParam("state") String state,ModelMap modelMap) { SysUser loginUser=null ; modelMap.addAttribute("message" ,"登陆中..." ); if (ThirdAppConfig.WECHAT_ENTERPRISE.equalsIgnoreCase(source)) { log.info("【企业微信】OAuth2登录进入callback:code=" + code + ", state=" + state); loginUser = thirdAppWechatEnterpriseService.oauth2Login(code); if (loginUser == null ) { modelMap.addAttribute("message" ,"用户不存在" ); } } else if (ThirdAppConfig.DINGTALK.equalsIgnoreCase(source)) { log.info("【钉钉】OAuth2登录进入callback:authCode=" + authCode + ", state=" + state); loginUser = thirdAppDingtalkService.oauth2Login(authCode); if (loginUser == null ) { modelMap.addAttribute("message" ,"用户不存在" ); } } else { modelMap.addAttribute("message" ,"不支持的source" ); } try { Object check = redisUtil.get(CommonConstant.LOGIN_QRCODE +state); if (oConvertUtils.isNotEmpty(check)) { String token = saveToken(loginUser); redisUtil.set(CommonConstant.LOGIN_QRCODE_TOKEN +state, token, 60 ); modelMap.addAttribute("message" ,"扫码登陆成功" ); } else { modelMap.addAttribute("message" ,"二维码已过期,请刷新后重试" ); } } catch (Exception e) { e.printStackTrace(); modelMap.addAttribute("message" ,"未知错误" ); } return "scanLogin" ; }
4.扫码后保存的 token 用户扫码后,会将token保存到内存中,供前端进行获取,前端获取到了相关的信息之后,就可以实现登录了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @ApiOperation(value = "获取用户扫码后保存的token", notes = "获取用户扫码后保存的token") @GetMapping("/getQrcodeToken") public Result getQrcodeToken (@RequestParam String qrcodeId) { Object token = redisUtil.get(CommonConstant.LOGIN_QRCODE_TOKEN + qrcodeId); Map result = new HashMap (5 ); Object qrcodeIdExpire = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId); if (oConvertUtils.isEmpty(qrcodeIdExpire)) { result.put("token" , "-2" ); return Result.OK(result); } if (oConvertUtils.isNotEmpty(token)) { result.put("success" , true ); result.put("token" , token); } else { result.put("token" , "-1" ); } return Result.OK(result); }
5.修改前端页面 前端使用的是 src/views/system/loginmini/MiniCodelogin.vue 中的文件,基本上不用动,根据上面的修改接口进行调整,修改获取 二维码的地址,以及定时获取后台二维码状态的接口。
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 function loadQrCode ( ) { state.value = '0' ; getLoginQrcode ().then ((res ) => { qrCodeUrl.value = res.url ; if (res.qrcodeId ) { openTimer (res.qrcodeId ); } }); } function watchQrcodeToken (qrcodeId ) { getQrcodeToken ({ qrcodeId : qrcodeId }).then ((res ) => { let token = res.token ; if (token == '-2' ) { loadQrCode (); clearInterval (timer); } if (res.success ) { state.value = '2' ; clearInterval (timer); setTimeout (() => { userStore.qrCodeLogin (token); }, 500 ); } }); }
问题 (1)Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream 这个问题应该不是 jeecg-boot 引起的,是我单独引入了 poi-ooxml 5.2.3 版本导致的。
【解决方法】 将common-io的版本进行升级
1 2 3 4 5 <dependency > <groupId > commons-io</groupId > <artifactId > commons-io</artifactId > <version > 2.11.0</version > </dependency >
(2) Invalid prop: type check failed for prop “value”. Expected String | Number | Symbol, got Array 在使用 CountdownInput.vue 的时候,在浏览器出现了这个警告,应该是说 input 本来应该绑定一个字符串,最后绑定的却是一个数组。应该是这个 CountdownInput 组件有问题。
主要就是在路径:src\components\CountDown\src\CountdownInput.vue,文件中的 state 上面。
6.定时任务 (1) 自定义job(实现类org.quartz.Job) (2) 在线配置定时任务 (3) 支持在线管理,启停
7.查询过滤器