普通视图

发现新文章,点击刷新页面。
昨天 — 2024年7月17日大雄日记
昨天以前大雄日记

彻底关闭 Win10 系统自动更新【四大步骤】

2024年4月12日 00:20

Windows 10 的自动更新非常顽固,多用户在网上试了各种关闭win10自动更新的方法,刚开始看着好像是关闭更新了,可没过多久系统就又开始自动更新了。今天笔者就来教大家如何彻底关闭win10自动更新,该方法亲测有效。

一、禁用 Windows Update 服务

1、同时按下键盘 Win + R,打开运行对话框,然后输入命令 services.msc ,点击下方的“确定”打开服务。

2、找到 Windows Update 这一项,并双击打开。

1.png

3、双击打开它,点击“停止”,把启动类型选为“禁用”,最后点击应用。

4、接下再切换到“恢复”选项,将默认的“重新启动服务”改为“无操作”,然后点击“应用”再点击“确定”。

二、在组策略里关闭 Win10 自动更新相关服务

1、同时按下 Win + R 组合快捷键打开运行命令操作框,然后输入gpedit.msc,点击确定。

2、在组策略编辑器中,依次展开 计算机配置 -> 管理模板 -> Windows组件 -> Windows更新

2.png

3、然后在右侧“配置自动更新”设置中,将其设置为“已禁用”并点击下方的“应用”然后“确定”。

4、之后还需要再找到“删除使用所有Windows更新功能的访问权限”,双击,选择“已启用”,完成设置后,点击“应用”然后“确定”。

3.png

三、禁用任务计划里边的Win10自动更新

1、同时按下 Win + R 组合快捷键打开““运行”窗口,然后输入taskschd.msc,并点击下方的“确定”打开任务计划程序。

4.png

5.png

2、在任务计划程序的设置界面,依次展开 任务计划程序库 -> Microsoft -> Windows -> WindowsUpdate,把里面的项目都设置为 [ 禁用 ] 就可以了。(我这里边只有一个任务,你的电脑里可能会有2个或者更多,全部禁用就行了)

四、在注册表中关闭 Win10 自动更新

1、同时按下 Win + R 组合快捷键,打开运行对话框,然后输入命名 regedit,然后点击下方的「 确定 」打开注册表。

2、在注册表设置中,找到并定位 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\UsoSvc]。然后在右侧找到 “ Start ” 键。

3、点击修改,把 start 值改成 16 进制,值改为“4”,然后点击「 确定 」保存数据。

6.png

4、继续在右侧找到 “FailureActions” 键,右键点击修改该键的二进制数据,将 “0010”、“0018” 行的左起第5个数值由原来的 “01” 改为 “00”,完成后,点击下方的 “确定” 即可。

7.png

至此彻底关闭win10自动更新的操作步骤就全部完成了。

之所以很多用户按照网上提供的方法设置后依然无法彻底关闭win10自动更新,就是因为顾了头没顾到脚,我们要从Windows Update服务、组策略、计划任务、注册表这四个方面入手来设置,这样才能一劳永逸,彻底关闭 win10自动更新。@上官海岚

SpringBoot统一结果返回,统一异常处理。

2024年4月11日 16:48

引言

在开发Spring Boot应用时,我们经常面临着不同的控制器方法需要处理各种不同类型的响应结果,以及在代码中分散处理异常可能导致项目难以维护的问题。你是否曾经遇到过在不同地方编写相似的返回格式,或者在处理异常时感到有些混乱?这些看似小问题的积累,实际上可能对项目产生深远的影响。统一结果返回和统一异常处理并非只是为了规范代码,更是为了提高团队的协作效率、降低项目维护的难度,并使代码更易于理解和扩展。

本文的目的是帮助你更好地理解和应用Spring Boot中的统一结果返回和统一异常处理。通过详细的讨论和实例演示,我们将为你提供一套清晰的指南,让你能够在自己的项目中轻松应用这些技术,提高代码质量,减轻开发压力。

统一结果返回

统一结果返回是一种通过定义通用的返回格式,使所有的响应结果都符合同一标准的方法。这有助于提高代码的一致性,减少重复代码的编写,以及使客户端更容易理解和处理API的响应。统一结果返回不仅规范了代码结构,还能提高团队协作效率,降低项目维护的难度。

接下来让我们一起看看在SpringBoot中如何实现统一结果返回。

1. 定义通用的响应对象

当实现统一结果返回时,需要创建一个通用的响应对象,定义成功和失败的返回情况,并确保在接口中使用这个通用返回对象。

@Setter  
@Getter  
public class ResultResponse<T> implements Serializable {  
    private static final long serialVersionUID = -1133637474601003587L;  

    /**  
     * 接口响应状态码  
     */  
    private Integer code;  

    /**  
     * 接口响应信息  
     */  
    private String msg;  

    /**  
     * 接口响应的数据  
     */  
    private T data;
}    

2. 定义接口响应状态码

统一结果返回的关键之一是规定一套通用的状态码。这有助于客户端更容易地理解和处理 API 的响应,同时也为开发者提供了一致的标准。通常,一些 HTTP 状态码已经被广泛接受,如:

  • 200 OK:表示成功处理请求。
  • 201 Created:表示成功创建资源。
  • 204 No Content:表示成功处理请求,但没有返回任何内容。

对于错误情况,也可以使用常见的 HTTP 状态码,如:

  • 400 Bad Request:客户端请求错误。
  • 401 Unauthorized:未授权访问。
  • 404 Not Found:请求资源不存在。
  • 500 Internal Server Error:服务器内部错误。

除了 HTTP 状态码外,你还可以定义自己的应用程序特定状态码,以表示更具体的情况。确保文档中清晰地说明了每个状态码所代表的含义,使开发者能够正确地解释和处理它们。

public enum StatusEnum {  
    SUCCESS(200 ,"请求处理成功"),  
    UNAUTHORIZED(401 ,"用户认证失败"),  
    FORBIDDEN(403 ,"权限不足"),  
    SERVICE_ERROR(500, "服务器去旅行了,请稍后重试"),  
    PARAM_INVALID(1000, "无效的参数"),  
    ;  
    public final Integer code;  

    public final String message;  

    StatusEnum(Integer code, String message) {  
        this.code = code;  
        this.message = message;  
    }  

}

3. 定义统一的成功和失败的处理方法

定义统一的成功和失败的响应方法有助于保持代码一致性和规范性,简化控制器逻辑,提高代码复用性,降低维护成本,提高可读性,促进团队协作,以及更便于进行测试。

/**  
 * 封装成功响应的方法  
 * @param data 响应数据  
 * @return reponse  
 * @param <T> 响应数据类型  
 */  
public static <T> ResultResponse<T> success(T data) {  

    ResultResponse<T> response = new ResultResponse<>();  
    response.setData(data);  
    response.setCode(StatusEnum.SUCCESS.code);  
    return response;  
}  

/**  
 * 封装error的响应  
 * @param statusEnum error响应的状态值  
 * @return  
 * @param <T>  
 */  
public static <T> ResultResponse<T> error(StatusEnum statusEnum) {  
   return error(statusEnum, statusEnum.message);  
}  

/**  
 * 封装error的响应  可自定义错误信息
 * @param statusEnum error响应的状态值  
 * @return  
 * @param <T>  
 */  
public static <T> ResultResponse<T> error(StatusEnum statusEnum, String errorMsg) {  
    ResultResponse<T> response = new ResultResponse<>();  
    response.setCode(statusEnum.code);  
    response.setMsg(errorMsg);  
    return response;  
}

4. web层统一响应结果

在web层使用统一结果返回的目的是将业务逻辑的处理结果按照预定的通用格式进行封装,以提高代码的一致性和可读性。

@RestController  
@RequestMapping("user")  
@Validated  
@Slf4j  
public class UserController {  

    private IUserService userService;  

    /**  
     * 创建用户  
     * @param requestVO  
     * @return  
     */  
    @PostMapping("create")  
    public ResultResponse<Void> createUser(@Validated @RequestBody UserCreateRequestVO requestVO){  
        return ResultResponse.success(null);  
    }

    /**  
     * 根据用户ID获取用户信息  
     * @param userId 用户id  
     * @return 用户信息  
     */  
    @GetMapping("info")  
    public ResultResponse<UserInfoResponseVO> getUser(@NotBlank(message = "请选择用户") String userId){  
        final UserInfoResponseVO responseVO = userService.getUserInfoById(userId);  
        return ResultResponse.success(responseVO);  
    }  

    @Autowired  
    public void setUserService(IUserService userService) {  
        this.userService = userService;  
    }  
}

调用接口,响应的信息统一为:

{
    "code": 200,
    "msg": null,
    "data": null
}

{
    "code": 200,
    "msg": null,
    "data": {
        "userId": "121",
        "userName": "码农Academy"
    }
}

统一结果返回通过定义通用的返回格式、成功和失败的返回情况,以及在控制器中使用这一模式,旨在提高代码的一致性、可读性和可维护性。采用统一的响应格式简化了业务逻辑处理流程,使得开发者更容易处理成功和失败的情况,同时客户端也更容易理解和处理 API 的响应。这一实践有助于降低维护成本、提高团队协作效率,并促进代码的规范化。

统一异常处理

统一异常处理的必要性体现在保持代码的一致性、提供更清晰的错误信息、以及更容易排查问题。通过定义统一的异常处理方式,确保在整个应用中对异常的处理保持一致,减少了重复编写相似异常处理逻辑的工作,同时提供友好的错误信息帮助开发者和维护人员更快地定位和解决问题,最终提高了应用的可维护性和可读性。

1.定义统一的异常类

我们需要定义服务中可能抛出的自定义异常类。这些异常类可以继承自RuntimeException,并携带有关异常的相关信息。即可理解为局部异常,用于特定的业务处理中异常。手动埋点抛出。

@Getter  
public class ServiceException extends RuntimeException{  

    private static final long serialVersionUID = -3303518302920463234L;  

    private final StatusEnum status;  

    public ServiceException(StatusEnum status, String message) {  
        super(message);  
        this.status = status;  
    }  

    public ServiceException(StatusEnum status) {  
        this(status, status.message);  
    }  
}

2.异常处理器

创建一个全局的异常处理器,使用@ControllerAdvice 或者 @RestControllerAdvice注解和@ExceptionHandler注解来捕获不同类型的异常,并定义处理逻辑。

2.1 @ControllerAdvice注解

用于声明一个全局控制器建言(Advice),相当于把@ExceptionHandler@InitBinder@ModelAttribute注解的方法集中到一个地方。常放在一个特定的类上,这个类被认为是全局异常处理器,可以跨足多个控制器。

当时用@ControllerAdvice时,我们需要在异常处理方法上加上@ResponseBody,同理我们的web接口。但是如果我们使用@RestControllerAdvice 就可以不用加,同理也是web定义的接口

2.2 @ExceptionHandler注解

用于定义异常处理方法,处理特定类型的异常。放在全局异常处理器类中的具体方法上。

通过这两个注解的配合,可以实现全局的异常处理。当控制器中抛出异常时,Spring Boot会自动调用匹配的@ExceptionHandler方法来处理异常,并返回定义的响应。

@Slf4j  
@ControllerAdvice  
public class ExceptionAdvice {  

    /**  
     * 处理ServiceException  
     * @param serviceException ServiceException  
     * @param request 请求参数  
     * @return 接口响应  
     */  
    @ExceptionHandler(ServiceException.class)  
    @ResponseBody  
    public ResultResponse<Void> handleServiceException(ServiceException serviceException, HttpServletRequest request) {  
        log.warn("request {} throw ServiceException \n", request, serviceException);  
        return ResultResponse.error(serviceException.getStatus(), serviceException.getMessage());  
    }  

    /**  
     * 其他异常拦截  
     * @param ex 异常  
     * @param request 请求参数  
     * @return 接口响应  
     */  
    @ExceptionHandler(Exception.class)  
    @ResponseBody  
    public ResultResponse<Void> handleException(Exception ex, HttpServletRequest request) {  
        log.error("request {} throw unExpectException \n", request, ex);  
        return ResultResponse.error(StatusEnum.SERVICE_ERROR);  
    }
}    

3.异常统一处理使用

在业务开发过程中,我们可以在service层处理业务时,可以手动抛出业务异常。由全局异常处理器进行统一处理。

@Service  
@Slf4j  
public class UserServiceImpl implements IUserService {  

    private IUserManager userManager;

    /**  
     * 创建用户  
     *  
     * @param requestVO 请求参数  
     */  
    @Override  
    public void createUser(UserCreateRequestVO requestVO) {  
        final UserDO userDO = userManager.selectUserByName(requestVO.getUserName());  
        if (userDO != null){  
            throw new ServiceException(StatusEnum.PARAM_INVALID, "用户名已存在");  
        }  
    }

    @Autowired  
    public void setUserManager(IUserManager userManager) {  
        this.userManager = userManager;  
    }  
}

@RestController  
@RequestMapping("user")  
@Validated  
@Slf4j  
public class UserController {  

    private IUserService userService;  

    /**  
     * 创建用户  
     * @param requestVO  
     * @return  
     */  
    @PostMapping("create")  
    public ResultResponse<Void> createUser(@Validated @RequestBody UserCreateRequestVO requestVO){  
        userService.createUser(requestVO);  
        return ResultResponse.success(null);  
    }

    @Autowired  
    public void setUserService(IUserService userService) {  
        this.userService = userService;  
    }  
}

当我们请求接口时,假如用户名称已存在,接口就会响应:

{
    "code": 1000,
    "msg": "用户名已存在",
    "data": null
}

统一异常处理带来的好处包括提供一致的异常响应格式,简化异常处理逻辑,记录更好的错误日志,以及更容易排查和解决问题。通过统一处理异常,我们确保在整个应用中对异常的处理方式一致,减少了重复性代码的编写,提高了代码的规范性。简化的异常处理逻辑降低了开发者的工作负担,而更好的错误日志有助于更迅速地定位和解决问题,最终提高了应用的可维护性和稳定性。

其他类型的异常处理

在项目开发过程中,我们还有一些常见的特定异常类型,比如MethodArgumentNotValidExceptionUnexpectedTypeException等,并为它们定义相应的异常处理逻辑。这些特定异常可能由于请求参数校验失败或意外的数据类型问题而引起,因此有必要为它们单独处理,以提供更具体和友好的异常响应。

1.MethodArgumentNotValidException

由于请求参数校验失败引起的异常,通常涉及到使用@Valid注解或者@Validated进行请求参数校验。我们可以在异常处理器中编写@ExceptionHandler方法,捕获并处理MethodArgumentNotValidException,提取校验错误信息,并返回详细的错误响应。

/**  
 * 参数非法校验  
 * @param ex  
 * @return  
 */  
@ExceptionHandler(MethodArgumentNotValidException.class)  
@ResponseBody  
public ResultResponse<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {  
    try {  
        List<ObjectError> errors = ex.getBindingResult().getAllErrors();  
        String message = errors.stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","));  
        log.error("param illegal: {}", message);  
        return ResultResponse.error(StatusEnum.PARAM_INVALID, message);  
    } catch (Exception e) {  
        return ResultResponse.error(StatusEnum.SERVICE_ERROR);  
    }  
}

当我们使用@Valid注解或者@Validated进行请求参数校验不通过时,响应结果为:

{
    "code": 1000,
    "msg": "请输入地址信息,用户年龄必须小于60岁,请输入你的兴趣爱好",
    "data": null
}

关于@Valid注解或者@Validated进行参数校验的功能请参考:SpringBoot优雅校验参数

2.UnexpectedTypeException

意外的数据类型异常,通常表示程序运行时发生了不符合预期的数据类型问题。一个常见的使用场景是在数据转换或类型处理的过程中。例如,在使用 Spring 表单绑定或数据绑定时,如果尝试将一个不符合预期类型的值转换为目标类型,就可能抛出 UnexpectedTypeException。这通常会发生在将字符串转换为数字、日期等类型时,如果字符串的格式不符合目标类型的要求。

我们可以在异常处理器中编写@ExceptionHandler方法,捕获并处理UnexpectedTypeException,提供适当的处理方式,例如记录错误日志,并返回合适的错误响应。

@ExceptionHandler(UnexpectedTypeException.class)  
@ResponseBody  
public ResultResponse<Void> handleUnexpectedTypeException(UnexpectedTypeException ex,  
                                                        HttpServletRequest request) {  
    log.error("catch UnexpectedTypeException, errorMessage: \n", ex);  
    return ResultResponse.error(StatusEnum.PARAM_INVALID, ex.getMessage());  
}

当发生异常时,接口会响应:

{
    "code": 500,
    "msg": "服务器去旅行了,请稍后重试",
    "data": null
}

3.ConstraintViolationException

javax.validation.ConstraintViolationException 是 Java Bean Validation(JSR 380)中的一种异常。它通常在使用 Bean Validation 进行数据校验时,如果校验失败就会抛出这个异常。即我们在使用自定义校验注解时,如果不满足校验规则,就会抛出这个错误。

@ExceptionHandler(ConstraintViolationException.class)  
@ResponseBody  
public ResultResponse<Void> handlerConstraintViolationException(ConstraintViolationException ex, HttpServletRequest request) {  
    log.error("request {} throw ConstraintViolationException \n", request, ex);  
    return ResultResponse.error(StatusEnum.PARAM_INVALID, ex.getMessage());  
}

案例请参考:SpringBoot优雅校验参数,注册ConstraintValidator示例中的@UniqueUser校验。

4.HttpMessageNotReadableException

表示无法读取HTTP消息的异常,通常由于请求体不合法或不可解析。

@ResponseBody  
@ResponseStatus(HttpStatus.BAD_REQUEST)  
@ExceptionHandler(HttpMessageNotReadableException.class)  
public ResultResponse<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex,  
HttpServletRequest request) {  
    log.error("request {} throw ucManagerException \n", request, ex);  
    return ResultResponse.error(StatusEnum.SERVICE_ERROR);  
}

5.HttpRequestMethodNotSupportedException

Spring Framework 中的异常类,表示请求的 HTTP 方法不受支持。当客户端发送了一个使用不被服务器支持的 HTTP 方法(如 GET、POST、PUT、DELETE等)的请求时,可能会抛出这个异常。

@ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class})  
@ResponseBody  
public ResultResponse<Void> handleMethodNotSupportedException(Exception ex) {  
    log.error("HttpRequestMethodNotSupportedException \n", ex);  
    return ResultResponse.error(StatusEnum.HTTP_METHOD_NOT_SUPPORT);  
}

全局异常处理与局部异常处理在Spring Boot应用开发中扮演不同角色。全局异常处理通过统一的异常处理器确保了整个应用对异常的处理一致性,减少了冗余代码,提高了代码的整洁度。然而,这种方式可能在灵活性上略显不足,无法满足每个具体控制器或业务场景的个性化需求。

相比之下,局部异常处理能够为每个控制器或业务场景提供更具体、灵活的异常处理逻辑,允许定制化的异常响应。这使得在复杂的项目中更容易处理特定的异常情况,同时提供更详细的错误信息。然而,局部异常处理可能带来代码冗余和维护难度的问题,特别是在大型项目中。

在实际应用中,选择全局异常处理还是局部异常处理应根据项目规模和需求进行权衡。对于小型项目或简单场景,全局异常处理可能是一种更简单、合适的选择。而对于大型项目或需要个性化异常处理的复杂业务逻辑,局部异常处理则提供了更为灵活的方案。最佳实践是在项目中根据具体情况灵活使用这两种方式,以平衡一致性和个性化需求。

最佳实践与注意事项

1. 最佳实践

  • 统一响应格式: 在异常处理中,使用统一的响应格式有助于客户端更容易理解和处理错误。通常,返回一个包含错误码、错误信息和可能的详细信息的响应对象。
  • 详细错误日志: 在异常处理中记录详细的错误日志,包括异常类型、发生时间、请求信息等。这有助于快速定位和解决问题。
  • 使用HTTP状态码: 根据异常的性质,选择适当的HTTP状态码。例如,使用HttpStatus.NOT_FOUND表示资源未找到,HttpStatus.BAD_REQUEST表示客户端请求错误等。
  • 异常分类: 根据异常的种类,合理分类处理。可以定义不同的异常类来表示不同的异常情况,然后在异常处理中使用@ExceptionHandler分别处理。
  • 全局异常处理: 使用全局异常处理机制来捕获未被特定控制器处理的异常,以确保应用在整体上的健壮性。

2 注意事项

  • 不滥用异常: 异常应该用于表示真正的异常情况,而不是用作控制流程。滥用异常可能导致性能问题和代码可读性降低。
  • 不忽略异常: 避免在异常处理中忽略异常或仅仅打印日志而不进行适当的处理。这可能导致潜在的问题被掩盖,难以追踪和修复。
  • 避免空的catch块: 不要在catch块中什么都不做,这样会使得异常难以被发现。至少在catch块中记录日志,以便了解异常的发生。
  • 适时抛出异常: 不要过于吝啬地抛出异常,但也不要无谓地滥用。在必要的时候使用异常,例如表示无法继续执行的错误情况。
  • 测试异常场景: 编写单元测试时,确保覆盖异常场景,验证异常的正确抛出和处理。

总结

异常处理在应用开发中是至关重要的一环,它能够提高应用的健壮性、可读性和可维护性。全局异常处理和局部异常处理各有优劣,需要根据项目的规模和需求来灵活选择。通过采用统一的响应格式、详细的错误日志、适当的HTTP状态码等最佳实践,可以使异常处理更为有效和易于管理。同时,注意避免滥用异常、忽略异常、适时抛出异常等注意事项,有助于确保异常处理的质量。在开发过程中,持续关注和优化异常处理,将有助于提高应用的稳定性和用户体验。@码农Academy

0.5的男人

2024年4月8日 16:44

倘若你觉得活着就已经很艰难,

那么暂时与这个世界脱轨其实并无过错。

你可以沉寂在泥土里,期盼着下一个春天。

也可以蜗居在茧房里,等待着合适的契机。

那个契机被你找到的时刻也会早也会晚。

但它终归有一天会出现在你的面前。

而在你找到契机破茧而出之前;你只需要活着,就已经足够了。p2894049702.jpeg

安装Ubuntu server 22.04后,df -h只有100G,整个硬盘2T

2024年4月8日 16:26

Ubuntu server 默认使用LVM进行磁盘管理,安装后只使用了硬盘一部分空间。

要充分利用硬盘空间,需要扩展现有的逻辑卷。

如果添加新硬盘,需要将其添加到现有的卷组,然后扩展逻辑卷到新硬盘。

  1. 查看现有的卷组

sudo vgdisplay

截图是已经操作好扩展空间的了,如果不为0证明是可以操作的。

  1. 扩展现有的逻辑卷

sudo lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv

  1. 重新计算逻辑卷大小

sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

  1. 再次查看磁盘使用情况

df -h

至此,整个硬盘空间都可以使用了。

❌
❌