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

上传到网站去的文档乱码一个电信ip做网站卡不卡

上传到网站去的文档乱码,一个电信ip做网站卡不卡,wordpress中文免费主题,跨境电商开发软件系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 本文参考项目源码地址#xff1a;summo-springboot-interface-demo 前言 大家好#xff01;…系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 本文参考项目源码地址summo-springboot-interface-demo 前言 大家好我是sum墨一个一线的底层码农平时喜欢研究和思考一些技术相关的问题并整理成文限于本人水平如果文章和代码有表述不当之处还请不吝赐教。 作为一名从业已达六年的老码农我的工作主要是开发后端Java业务系统包括各种管理后台和小程序等。在这些项目中我设计过单/多租户体系系统对接过许多开放平台也搞过消息中心这类较为复杂的应用但幸运的是我至今还没有遇到过线上系统由于代码崩溃导致资损的情况。这其中的原因有三点一是业务系统本身并不复杂二是我一直遵循某大厂代码规约在开发过程中尽可能按规约编写代码三是经过多年的开发经验积累我成为了一名熟练工掌握了一些实用的技巧。 BUG对于程序员来说实在是不陌生当代码出现BUG时异常也会随之出现但BUG并不等于异常BUG只是导致异常出现的一个原因。导致异常发生的原因非常多本篇文章我也主要只讲一下接口相关的异常怎么处理。 一、接口异常的分类 在接口设计中应该尽量避免使用异常来进行控制流程。接口应该尽可能返回明确的错误码和错误信息而不是直接抛出异常。 1. 业务异常Business Exception 这是接口处理过程中可能出现的业务逻辑错误例如参数校验失败、权限不足等。这些异常通常是预期的并且可以提供相应的错误码和错误信息给调用方。 2. 系统异常System Exception 这是接口处理过程中可能出现的非预期错误例如数据库异常、网络异常等。这些异常通常是未知的并且可能导致接口无法正常响应。这种错误不仅需要记录异常信息通知系统管理员处理还需要封装起来做好提示不能直接把错误返回给用户。 3. 客户端异常Client Exception 这是调用方在使用接口时可能出现的错误例如请求参数错误、请求超时等。这些异常通常是由于调用方的错误导致的接口本身没有问题。可以根据具体情况选择是否返回错误信息给调用方。 二、接口异常的常见处理办法 1. 异常捕获和处理 在接口的实现代码中可以使用try-catch语句捕获异常并进行相应的处理。可以选择将异常转化为合适的错误码和错误信息然后返回给调用方。或者根据具体情况选择是否记录异常日志并通知系统管理员进行处理。 2. 统一异常处理器 可以使用统一的异常处理器来统一处理接口异常。在Spring Boot中可以使用ControllerAdvice和ExceptionHandler注解来定义一个全局的异常处理器。这样可以将所有接口抛出的异常统一处理例如转化为特定的错误码和错误信息并返回给调用方。 3. 抛出自定义异常 可以根据业务需求定义一些自定义的异常类继承RuntimeException或其他合适的异常类并在接口中抛出这些异常。这样可以在异常发生时直接抛出异常由上层调用方进行捕获和处理。 4. 返回错误码和错误信息 可以在接口中定义一套错误码和错误信息的规范当发生异常时返回对应的错误码和错误信息给调用方。这样调用方可以根据错误码进行相应的处理例如展示错误信息给用户或者进行相应的逻辑处理。 例如这样的弹窗提示 5. 跳转到指定错误页 比如遇到401、404、500等错误时SpringBoot框架会返回自带的错误页在这里我们其实可以自己重写一些更美观、更友好的错误提示页最好还能引导用户回到正确的操作上来例如这样 而不是下面这样 三、接口异常的统一处理 通过前面两段我们可以发现造成异常的原因很多出现异常的地方很多异常的处理手段也很多。基于以上三多的情况我们需要一个地方来统一接收异常、统一处理异常上面提到SpringBoot的ControllerAdvice注解作为一个全局的异常处理器来统一处理异常。但ControllerAdvice注解不是万能的它有一个问题 对于ControllerAdvice注解来说它主要用于处理Controller层的异常情况即在控制器方法中发生的异常。因为它是基于Spring MVC的控制器层的异常处理机制。 而Filter层是位于控制器之前的一层过滤器它可以用于对请求进行预处理和后处理。当请求进入Filter时还没有进入到Controller层所以ControllerAdvice注解无法直接处理Filter层中的异常。 所以对于Filter中的异常我们需要单独处理。 1. ControllerAdvice全局异常处理器的使用 (1)自定义业务异常 由于SpringBoot框架并没有定义业务相关的错误码所以我们需要自定义业务错误码。该错误码可以根据业务复杂程度进行分类每个错误码对应一个具体的异常情况。这样前后端统一处理异常时可以根据错误码进行具体的处理逻辑提高异常处理的准确性和效率。同时定义错误码还可以方便进行异常监控和日志记录便于排查和修复问题。 a、定义常见的异常状态码 ResponseCodeEnum.java package com.summo.demo.model.response;public enum ResponseCodeEnum {/*** 请求成功*/SUCCESS(0000, ErrorLevels.DEFAULT, ErrorTypes.SYSTEM, 请求成功),/*** 登录相关异常*/LOGIN_USER_INFO_CHECK(LOGIN-0001, ErrorLevels.INFO, ErrorTypes.BIZ, 用户信息错误),/*** 权限相关异常*/NO_PERMISSIONS(PERM-0001, ErrorLevels.INFO, ErrorTypes.BIZ, 用户无权限),/*** 业务相关异常*/BIZ_CHECK_FAIL(BIZ-0001, ErrorLevels.INFO, ErrorTypes.BIZ, 业务检查异常),BIZ_STATUS_ILLEGAL(BIZ-0002, ErrorLevels.INFO, ErrorTypes.BIZ, 业务状态非法),BIZ_QUERY_EMPTY(BIZ-0003, ErrorLevels.INFO, ErrorTypes.BIZ, 查询信息为空),/*** 系统出错*/SYSTEM_EXCEPTION(SYS-0001, ErrorLevels.ERROR, ErrorTypes.SYSTEM, 系统出错啦请稍后重试),;/*** 枚举编码*/private final String code;/*** 错误级别*/private final String errorLevel;/*** 错误类型*/private final String errorType;/*** 描述说明*/private final String description;ResponseCodeEnum(String code, String errorLevel, String errorType, String description) {this.code code;this.errorLevel errorLevel;this.errorType errorType;this.description description;}public String getCode() {return code;}public String getErrorLevel() {return errorLevel;}public String getErrorType() {return errorType;}public String getDescription() {return description;}public static ResponseCodeEnum getByCode(Integer code) {for (ResponseCodeEnum value : values()) {if (value.getCode().equals(code)) {return value;}}return SYSTEM_EXCEPTION;}} b、自定义业务异常类 BizException.java package com.summo.demo.exception.biz;import com.summo.demo.model.response.ResponseCodeEnum; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString;Data AllArgsConstructor NoArgsConstructor ToString public class BizException extends RuntimeException {/*** 错误码*/private ResponseCodeEnum errorCode;/*** 自定义错误信息*/private String errorMsg;} (2) 全局异常处理器 BizGlobalExceptionHandler package com.summo.demo.exception.handler;import javax.servlet.http.HttpServletResponse;import com.summo.demo.exception.biz.BizException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.ModelAndView;RestControllerAdvice(basePackages {com.summo.demo.controller, com.summo.demo.service}) public class BizGlobalExceptionHandler {ExceptionHandler(BizException.class)public ModelAndView handler(BizException ex, HttpServletResponse response) {ModelAndView modelAndView new ModelAndView();switch (ex.getErrorCode()) {case LOGIN_USER_INFO_CHECK:// 重定向到登录页modelAndView.setViewName(redirect:/login);break;case NO_PERMISSIONS:// 设置错误信息和错误码modelAndView.addObject(errorMsg, ex.getErrorMsg());modelAndView.addObject(errorCode, ex.getErrorCode().getCode());modelAndView.setViewName(403);break;case BIZ_CHECK_FAIL:case BIZ_STATUS_ILLEGAL:case BIZ_QUERY_EMPTY:case SYSTEM_EXCEPTION:default:// 设置错误信息和错误码modelAndView.addObject(errorMsg, ex.getErrorMsg());modelAndView.addObject(errorCode, ex.getErrorCode().getCode());modelAndView.setViewName(error);}return modelAndView;} } (3) 测试效果 RestControllerAdvice和ExceptionHandler使用起来很简单下面我们来测试一下(由于不写界面截图是在太丑我麻烦ChatGPT帮我写了一套简单的界面)。 a、普通业务异常捕获 第一步、打开登录页 访问链接http://localhost:8080/login 输入账号、密码点击登录进入首页 第二步、登录进入首页 第三步、调用一个会报错的接口 再服务启动之前我写了一个根据用户名查询用户的方法如果查询不到用户的话我会抛出一个异常代码如下 public ResponseEntityString query(String userName) {//根据名称查询用户ListUserDO list userRepository.list(new QueryWrapperUserDO().lambda().like(UserDO::getUserName, userName));if (CollectionUtils.isEmpty(list)) {throw new BizException(ResponseCodeEnum.BIZ_QUERY_EMPTY, 根据用户名称查询用户为空);}//返回数据return ResponseEntity.ok(JSONObject.toJSONString(list)); }这时我们查询一个不存在的用户 访问接口http://localhost:8080/user/query?userNamesss 因为数据库中没有用户名为sss的这个用户会抛出一个异常 b、403权限不足异常捕获 第一步、打开登录页 访问链接http://localhost:8080/login 登录界面使用小B的账号登录 第二步、登录进入首页 第三步、调用删除用户的接口 调用接口http://localhost:8080/user/delete?userId2 由于小B的账号只有查询权限没有删除权限所以返回403错误页 注意在调试之前需要在application.yml或application.properties配置文件中增加一个配置server.error.whitelabel.enabledfalse 这个配置的意思是是否启用默认的错误页面这里我们自己写了一套错误页所以不需要框架自带的配置了。 2. 自定义Filter中异常的处理 由于ControllerAdvice注解无法捕获自定义Filter中抛出的异常这里我们就需要使用另外一种方法进行处理ErrorController接口。 (1) 原理解释 Spring Boot的ErrorController是一个接口用于定义处理应用程序中发生的错误的自定义逻辑。它允许开发人员以更灵活的方式处理和响应异常而不是依赖于默认的错误处理机制。 定制错误页面通过实现ErrorController接口可以自定义应用程序的错误页面以提供更好的用户体验。可以根据不同的异常类型和HTTP状态码提供不同的错误页面或错误信息。记录错误日志ErrorController可以用于捕获和记录应用程序中的异常并将其记录到日志中。这对于问题追踪和排查非常有帮助可以了解应用程序中发生的错误和异常的详细信息。重定向或转发请求通过ErrorController可以根据错误的类型或其他条件将请求重定向到不同的URL或转发到其他控制器方法。这对于根据错误情况做出不同的处理非常有用例如重定向到自定义的错误页面或执行特定的错误处理逻辑。 (2) 使用方法 使用方法直接看看我的代码就知道了。 CustomErrorController.java package com.summo.demo.controller;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang3.StringUtils; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView;Controller public class CustomErrorController implements ErrorController {RequestMapping(/error)public ModelAndView handleError(HttpServletRequest request, HttpServletResponse response) {//获取当前响应返回的状态码int statusCode response.getStatus();//如果响应头中存在statusCode则默认使用这个statusCodeif (StringUtils.isNotBlank(response.getHeader(statusCode))) {statusCode Integer.valueOf(response.getHeader(statusCode));}if (statusCode HttpServletResponse.SC_FOUND) {// 获取Location响应头的值进行重定向String redirectLocation response.getHeader(Location);return new ModelAndView(redirect: redirectLocation);} else if (statusCode HttpServletResponse.SC_UNAUTHORIZED) {// 重定向到登录页return new ModelAndView(redirect:/login);} else if (statusCode HttpServletResponse.SC_FORBIDDEN) {// 返回403页面return new ModelAndView(403);} else if (statusCode HttpServletResponse.SC_NOT_FOUND) {// 返回404页面return new ModelAndView(404);} else if (statusCode HttpServletResponse.SC_INTERNAL_SERVER_ERROR) {// 返回500页面并传递errorMsg和errorCode到模板ModelAndView modelAndView new ModelAndView(500);modelAndView.addObject(errorMsg, response.getHeader(errorMsg));modelAndView.addObject(errorCode, response.getHeader(errorCode));return modelAndView;} else {// 返回其他错误页面return new ModelAndView(error);}}}细心的读者可能会看到statusCode来自于两个地方第一个是response.getStatus()第二个是response.getHeader(“statusCode”)。这两者的区别是第一个是框架自动设置的第二个则是我根据业务逻辑设置的。 原因是在WebFilter中一旦抛出了异常response.getStatus()一定会是500即使这个异常是因为用户身份失效导致的。但异常又不得不抛出所以我通过自定义response的header的方式设置了错误码传递到/error接口。 (3) 测试效果 a、404错误页接口找不到 第一步、打开登录页 访问链接http://localhost:8080/login 输入账号、密码点击登录进入首页 第二步、登录进入首页 第三步、访问一个不存在的页面 访问链接http://localhost:8080/xxxx 由于xxxx接口没有被定义过界面会返回404 b、401错误用户身份标识为空或无效 这里我做的处理是如果用户身份标识为空或无效那么我会默认跳转到登录页。 测试方法是打开一个无痕界面随便输入一个链接http://localhost:8080/user/query 由于Cookie中token不存在所以我不管访问的是哪个链接直接将状态码改为401而CustomErrorController遇到401的错误会默认重定向到登录页。 四、优化无痕窗口下的重新登录体验 Filter异常的全局处理除了ErrorController之外还可以通过自定义拦截器的方式实现这两个东西会一个就行了。这里我再说一个高级一点的东西举个例子 我在一个无痕窗口调用接口http://localhost:8080/user/query?userName小B 因为当前窗口的Cookie中是没有token的按照401错误的处理方式我会重定向到登录页去。 但这个有一个问题重新登录之后进入的是首页不是调用user/query接口我还得重新去找这个接口重新输入参数。而且这要是一个分享页那就尴尬了登陆完不知道对方分享了啥用户体验会很差那么有办法优化这个问题吗答案是有如何做继续看。 1. 在WebFilter中获取当前请求的全路径 所谓全路径就是“http://localhost:8080/user/query?userName小B” 如何获取可以用我这个方法 /*** 获取完整的路径URL包括参数** param httpServletRequest* return 路径URL */ private String getRequestURL(HttpServletRequest httpServletRequest) {String url httpServletRequest.getRequestURL().toString();String query httpServletRequest.getQueryString();if (query ! null) {url ? query;}return url; }2. 在WebFilter抛出401错误的地方设置httpServletResponse的header 如下 httpServletResponse.setHeader(redirectURL,URLEncoder.encode(getRequestURL(httpServletRequest), utf-8));因为参数有可能是中文这里需要用URLEncoder转下义。 3. 在CustomErrorController中获取到这个跳转链接 // 重定向到登录页或指定页面if (StringUtils.isNotBlank(response.getHeader(redirectURL))) {return new ModelAndView(redirect:/login?redirectURL response.getHeader(redirectURL));}效果如下 可以看到我们在login后面携带了一个redirectURL参数 4. 登录提交时将redirectURL参数一并提交 PostMapping(/login) public void userLogin(RequestParam(required true) String userName,RequestParam(required true) String password,RequestParam(required false) String redirectURL,HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) {userService.login(userName, password, redirectURL, httpServletRequest, httpServletResponse); }5. 验证通过后重定向到redirectURL try {//如果跳转路径不为空则直接重定向到跳转路径if (StringUtils.isNotBlank(redirectURL)) {httpServletResponse.sendRedirect(redirectURL);return;}//跳转到登录页httpServletResponse.sendRedirect(/index);} catch (IOException e) {log.error(重定向发生异常, e); }以上就是这个问题的解决方案了具体代码大家可以看我的demosummo-springboot-interface-demo
http://www.zqtcl.cn/news/572890/

相关文章:

  • 妇科医院网站优化服务商品牌型网站设计推荐
  • 西安网站制作排名网站建设对企业的帮助
  • lamp网站开发 pdf纯html5 网站
  • 白云区同和网站建设购物网站怎么建立
  • 公司制作网站需要espcms易思企业网站管理系统
  • 开发一个网站需要哪些步骤广西建设主管部门网站
  • 网站建设培训西安制作微信小程序开发
  • delphi 做直播网站wordpress 商务
  • 各大网站的软文怎么做wordpress教程菜鸟教程
  • 破解php网站后台账号密码wordpress二维码 插件下载
  • 石家庄哪里可以做网站做网站用的pm是啥
  • 租服务器网站有趣的设计网站
  • 建设部监理网站官网信阳市两学一做网站
  • 网站被攻击会影响收录么微信网站 影楼
  • 社区网站开发search搜索引擎
  • 章丘做网站哪家强原阳网站建设
  • 做网站前期构架图中国建设银行手机银行网站
  • tp5企业网站开发百度云青岛vi设计公司
  • 网站建设实验原理建站之星 discuz
  • 购物网站如何备案建设部施工合同范本
  • 网站模板安装建站之星凡客
  • 有没有电脑做兼职的网站吗网站和域名区别
  • 免费html网页模板素材网站修改wordpress后台登陆
  • 男女做啊免费视频网站网站做全景图
  • 网站域名 安全网站开发语言一般是用什么
  • 麦包包的网站建设分析网站开发一般要用到哪些软件有哪些
  • 关于内网站建设的请示天津住房与城乡建设厅网站首页
  • 企业网站免费源码装修公司需要多少钱
  • 沈阳建设网站费用群晖wordpress打不开
  • jsp网站开发 pdf建设植绒衣架网站