主頁 >  其他 > 搞定SpringBoot難題!設計優秀的后端介面?輕松解決

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

2020-11-10 07:18:58 其他

1 概述

本篇文章以Spring Boot為基礎,從以下三個方向講述了如何設計一個優秀的后端介面體系:

  • 引數校驗:涉及Hibernate Validator的各種注解,快速失敗模式,分組,組序列以及自定義注解/Validator
  • 例外處理:涉及ControllerAdvice/@RestControllerAdvice以及@ExceptionHandler
  • 資料回應:涉及如何設計一個回應體以及如何包裝回應體

有了一個優秀的后端介面體系,不僅有了規范,同時擴展新的介面也很容易,本文演示了如何從零一步步構建一個優秀的后端介面體系,

2 新建工程

打開熟悉的IDEA,選擇依賴:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

首先創建如下檔案:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

TestController.java:

@RestController
@RequestMapping("/")
@CrossOrigin(value = "http://localhost:3000")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {
    private final TestService service;
    @PostMapping("test")
    public String test(@RequestBody User user)
    {
        return service.test(user);
    }

使用了@RequiredArgsConstructor代替@Autowired,由于筆者使用Postwoman測驗,因此需要加上跨域注解@CrossOrigin,默認3000埠(Postwoman埠),

TestService.java:

@Service
public class TestService {
    public String test(User user)
    {
        if(StringUtils.isEmpty(user.getEmail()))
            return "郵箱不能為空";
        if(StringUtils.isEmpty(user.getPassword()))
            return "密碼不能為空";
        if(StringUtils.isEmpty(user.getPhone()))
            return "電話不能為空";
//        持久化操作
        return "success";
    }
}

業務層首先進行了引數校驗,這里省略了持久化操作,

User.java:

@Data
public class User {
    private String phone;
    private String password;
    private String email;
}

3 引數校驗

首先來看一下引數校驗,上面的例子中在業務層完成引數校驗,這是沒有問題的,但是,還沒進行業務操作就需要進行這么多的校驗顯然這不是很好,更好的做法是,使用Hibernate Validator,

3.1 Hibernate Validator

3.1.1 介紹

JSR是Java Specification Requests的縮寫,意思是Java規范提案,是指向JCP(Java Community Process)提出新增一個標準化技術規范的正式請求,JSR-303是Java EE6中的一項子規范,叫作Bean Validation,Hibernate Validator是Bean Validator的參考實作,除了實作所有JSR-303規范中的內置constraint實作,還有附加的constraint,詳細如下:

  • @Null:被注解元素必須為null(為了節省篇幅下面用“元素”代表“被注解元素必須為”)
  • @NotNull:元素不為null
  • @AssertTrue:元素為true
  • @AssertFalse:元素為false
  • @Min(value):元素大于或等于指定值
  • @Max(value):元素小于或等于指定值
  • @DecimalMin(value):元素大于指定值
  • @DecimalMax(value):元素小于指定值
  • @Size(max,min):元素大小在給定范圍內
  • @Digits(integer,fraction):元素字串中的整數位數規定最大integer位,小數位數規定最大fraction位
  • @Past:元素是一個過去日期
  • @Future:元素是將來日期
  • @Pattern:元素需要符合正則運算式

其中Hibernate Validator附加的constraint如下:

  • @Eamil:元素為郵箱
  • @Length:字串大小在指定范圍內
  • @NotEmpty:字串必須非空(目前最新的6.1.5版本已棄用,建議使用標準的@NotEmpty)
  • @Range:數字在指定范圍內

而在Spring中,對Hibernate Validation進行了二次封裝,添加了自動校驗,并且校驗資訊封裝進了特定的BindingResult中,下面看看如何使用,

3.1.2 使用

在各個欄位加上@NotEmpty,并且郵箱加上@Email,電話加上11位限制,并且在各個注解加上message,表示對應的提示資訊:

@Data
public class User {
    @NotEmpty(message = "電話不能為空")
    @Length(min = 11,max = 11,message = "電話號碼必須11位")
    private String phone;
    @NotEmpty(message = "密碼不能為空")
    @Length(min = 6,max = 20,message = "密碼必須為6-20位")
    private String password;
    @NotEmpty(message = "郵箱不能為空")
    @Email(message = "郵箱格式不正確")
    private String email;
}

對于String來說有時候會使用@NotNull或@NotBlank,它們的區別如下:

  • @NotEmpty:不能為null并且長度必須大于0,除了String外,對于Collection/Map/陣列也適用
  • @NotBlank:只用于String,不能為null,并且呼叫trim()后,長度必須大于0,也就是必須有除空格外的實際字符
  • @NotNull:不能為null

接著把業務層的引數校驗操作洗掉,并把控制層修改如下:

@PostMapping("test")
public String test(@RequestBody @Valid User user, BindingResult bindingResult)
{
    if(bindingResult.hasErrors())
    {
        for(ObjectError error:bindingResult.getAllErrors())
            return error.getDefaultMessage();
    }
    return service.test(user);
}

在需要校驗的物件上加上@Valid,并且加上BindingResult引數,可以從中獲取錯誤資訊并回傳,

3.1.3 測驗

全部都使用錯誤的引數設定,回傳”郵箱格式不正確“:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

第二次測驗中除了密碼都使用正確的引數,回傳”密碼必須為6-20位“:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

第三次測驗全部使用正確的引數,回傳”success“:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

3.2 校驗模式設定

Hibernate Validator有兩種校驗模式:

  • 普通模式:默認模式,會校驗所有屬性,然后回傳所有的驗證失敗資訊
  • 快速失敗模式:只要有一個驗證失敗就回傳

使用快速失敗模式需要通過HibernateValidateConfiguration以及ValidateFactory創建Validator,并且使用Validator.validate()進行手動驗證,

首先添加一個生成Validator的類:

@Configuration
public class FailFastValidator<T> {
    private final Validator validator;
    public FailFastValidator()
    {
        validator = Validation
        .byProvider(HibernateValidator.class).configure()
        .failFast(true).buildValidatorFactory()
        .getValidator();
    }

    public Set<ConstraintViolation<T>> validate(T user)
    {
        return validator.validate(user);
    }

修改控制層的代碼,通過@RequiredArgsConstructor注入FailFastValidator<User>,并把原來的在User上的@Valid去掉,在方法體進行手動驗證:

@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {
    private final TestService service;
    private final FailFastValidator<User> validator;
    @PostMapping("test")
    public String test(@RequestBody User user, BindingResult bindingResult)
    {
        Set<ConstraintViolation<User>> message = validator.validate(user);
        message.forEach(t-> System.out.println(t.getMessage()));
//        if(bindingResult.hasErrors())
//        {
//            bindingResult.getAllErrors().forEach(t->System.out.println(t.getDefaultMessage()));
//            for(ObjectError error:bindingResult.getAllErrors())
//                return error.getDefaultMessage();
//        }
        return service.test(user);
    }
}

測驗(連續三次校驗的結果):

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

如果是普通模式(修改.failFast(false)),一次校驗便會連續輸出三個資訊:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

3.3 @Valid與@Validated

@Valid是javax.validation包里面的,而@Validated是org.springframework.validation.annotation里面的,是@Valid的一次封裝,相當于是@Valid的增強版,供Spring提供的校驗機制使用,相比起@Valid,@Validated提供了分組以及組序列的功能,下面分別進行介紹,

3.4 分組

當需要在不同的情況下使用不同的校驗方式時,可以使用分組校驗,比如在注冊時不需要校驗id,修改資訊時需要校驗id,但是默認的校驗方式在兩種情況下全部都校驗,這時就需要使用分組校驗,

下面以不同的組別校驗電話號碼長度的不同進行說明,修改User類如下:

@Data
public class User {
    @NotEmpty(message = "電話不能為空")
    @Length(min = 11,max = 11,message = "電話號碼必須11位",groups = {GroupA.class})
    @Length(min = 12,max = 12,message = "電話號碼必須12位",groups = {GroupB.class})
    private String phone;
    @NotEmpty(message = "密碼不能為空")
    @Length(min = 6,max = 20,message = "密碼必須為6-20位")
    private String password;
    @NotEmpty(message = "郵箱不能為空")
    @Email(message = "郵箱格式不正確")
    private String email;

    public interface GroupA{}
    public interface GroupB{}
}

在@Length中加入了組別,GroupA表示電話需要為11位,GroupB表示電話需要為12位,GroupA/GroupB是User中的兩個空介面,然后修改控制層:

public String test(@RequestBody @Validated({User.GroupB.class}) User user, BindingResult bindingResult)
{
    if(bindingResult.hasErrors())
    {
        bindingResult.getAllErrors().forEach(t->System.out.println(t.getDefaultMessage()));
        for(ObjectError error:bindingResult.getAllErrors())
            return error.getDefaultMessage();
    }
    return service.test(user);
}

在@Validated中指定為GroupB,電話需要為12位,測驗如下:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

3.5 組序列

默認情況下,不同組別的約束驗證的無序的,也就是說,對于下面的User類:

@Data
public class User {
    @NotEmpty(message = "電話不能為空")
    @Length(min = 11,max = 11,message = "電話號碼必須11位")
    private String phone;
    @NotEmpty(message = "密碼不能為空")
    @Length(min = 6,max = 20,message = "密碼必須為6-20位")
    private String password;
    @NotEmpty(message = "郵箱不能為空")
    @Email(message = "郵箱格式不正確")
    private String email;
}

每次進行校驗的順序不同,三次測驗結果如下:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

有些時候順序并不重要,而有些時候順序很重要,比如:

  • 第二個組中的約束驗證依賴于一個穩定狀態運行,而這個穩定狀態由第一個組來進行驗證
  • 某個組的驗證比較耗時,CPU和記憶體的使用率相對較大,最優的選擇是將其放在最后進行驗證

因此在進行組驗證的時候需要提供一種有序的驗證方式,一個組可以定義為其他組的序列,這樣就可以固定每次驗證的順序而不是隨機順序,另外如果驗證組序列中,前面的組驗證失敗,則后面的組不會驗證,

例子如下,首先修改User類并定義組序列:

@Data
public class User {
    @NotEmpty(message = "電話不能為空",groups = {First.class})
    @Length(min = 11,max = 11,message = "電話號碼必須11位",groups = {Second.class})
    private String phone;
    @NotEmpty(message = "密碼不能為空",groups = {First.class})
    @Length(min = 6,max = 20,message = "密碼必須為6-20位",groups = {Second.class})
    private String password;
    @NotEmpty(message = "郵箱不能為空",groups = {First.class})
    @Email(message = "郵箱格式不正確",groups = {Second.class})
    private String email;

    public interface First{}
    public interface Second{}
    @GroupSequence({First.class,Second.class})
    public interface Group{}
}

定義了兩個空介面First和Second表示順序,同時在Group中使用@GroupSequence指定了順序,

接著修改控制層,在@Validated中定義組:

 

這樣就能按照固定的順序進行引數校驗了,

3.6 自定義校驗

盡管Hibernate Validator中的注解適用情況很廣了,但是有時候需要特定的校驗規則,比如密碼強度,人為判定弱密碼還是強密碼,也就是說,此時需要添加自定義校驗的方式,有兩種處理方法:

  • 自定義注解
  • 自定義Validator

首先來看一下自定義注解的方法,

3.6.1 自定義注解

這里添加一個判定弱密碼的注解WeakPassword:

@Documented
@Constraint(validatedBy = WeakPasswordValidator.class)
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface WeakPassword{
    String message() default "請使用更加強壯的密碼";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

同時添加一個實作了ConstraintValidator<A,T>的WeakPasswordValidator,當密碼長度大于10位時才符合條件,否則回傳false表示校驗不通過:

public class WeakPasswordValidator implements ConstraintValidator<WeakPassword,String> {
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        return s.length() > 10;
    }
    @Override
    public void initialize(WeakPassword constraintAnnotation) {}
}

接著可以修改User如下,在對應的欄位加上自定義注解@WeakPassword:

@Data
public class User {
    //...
    @WeakPassword(groups = {Second.class})
    private String password;
    //...
}

測驗如下:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

3.6.2 自定義Validator

除了自定義注解之外,還可以自定義Validator來實作自定義的引數校驗,需要實作Validator介面:

@Component
public class WeakPasswordValidator implements Validator{
    @Override
    public boolean supports(Class<?> aClass) {
        return User.class.equals(aClass);
    }

    @Override
    public void validate(Object o, Errors errors) {
        ValidationUtils.rejectIfEmpty(errors,"password","password.empty");
        User user = (User)o;
        if(user.getPassword().length() <= 10)
            errors.rejectValue("password","Password is not strong enough!");
    }
}

實作其中的supports以及validate:

  • support:可以驗證該類是否是某個類的實體
  • validate:當supports回傳true后,驗證給定物件o,當出現錯誤時,向errors注冊錯誤

ValidationUtils.rejectIfEmpty校驗當物件o中某個欄位屬性為空時,向其中的errors注冊錯誤,注意并不會中斷陳述句的運行,也就是即使password為空,user.getPassword()還是會運行,這時會拋出空指標例外,下面的errors.rejectValue同樣道理,并不會中斷陳述句的運行,只是注冊了錯誤資訊,中斷的話需要手動拋出例外,

修改控制層中的回傳值,改為getCode():

if(bindingResult.hasErrors())
{
    bindingResult.getAllErrors().forEach(t-> System.out.println(t.getCode()));
    for(ObjectError error:bindingResult.getAllErrors())
        return error.getCode();
}
return service.test(user);

測驗:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

4 例外處理

到這里引數校驗就完成了,下一步是處理例外,

如果將引數校驗中的BindingResult去掉,就會將整個后端例外回傳給前端:

//public String test(@RequestBody @Validated({User.Group.class}) User user, BindingResult bindingResult)
public String test(@RequestBody @Validated({User.Group.class}) User user)
復制代碼

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

這樣雖然后端是方便了,不需要每一個介面都加上BindingResult,但是前端不好處理,整個例外都回傳了,因此后端需要捕捉這些例外,但是,不能手動去捕捉每一個,這樣還不如之前使用BindingResult,這種情況下就需要用到全域的例外處理,

4.1 基本使用

處理全域例外的步驟如下:

  • 創建全域例外處理的類:加上@ControllerAdvice/@RestControllerAdvice注解(取決于控制層用的是@Controller/@RestController,@Controller可以跳轉到相應頁面,回傳JSON等加上@ResponseBody即可,而@RestController相當于@Controller+@ResponseBody,回傳JSON無需加上@ResponseBody,但是視圖決議器無法決議jsp以及html頁面)
  • 創建例外處理方法:加上@ExceptionHandler指定想要處理的例外型別
  • 處理例外:在對應的處理例外方法中處理例外

這里增加一個全域例外處理類GlobalExceptionHandler:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e)
    {
        ObjectError error = e.getBindingResult().getAllErrors().get(0);
        return error.getDefaultMessage();
    }
}

首先加上@RestControllerAdvice,并在例外處理方法上加上@ExceptionHandler,

接著修改控制層,去掉其中的BindingResult:

@PostMapping("test")
public String test(@RequestBody @Validated({User.Group.class}) User user)
{
    return service.test(user);
}

然后就可以進行測驗了:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

全域例外處理相比起原來的每一個介面都加上BindingResult方便很多,而且可以集中處理所有例外,

4.2 自定義例外

很多時候都會用到自定義例外,這里新增一個測驗例外TestException:

@Data
public class TestException extends RuntimeException{
    private int code;
    private String msg;

    public TestException(int code,String msg)
    {
        super(msg);
        this.code = code;
        this.msg = msg;
    }

    public TestException()
    {
        this(111,"測驗例外");
    }

    public TestException(String msg)
    {
        this(111,msg);
    }
}

接著在剛才的全域例外處理類中添加一個處理該例外的方法:

@ExceptionHandler(TestException.class)
public String testExceptionHandler(TestException e)
{
    return e.getMsg();
}

在控制層進行測驗:

@PostMapping("test")
public String test(@RequestBody @Validated({User.Group.class}) User user)
{
    throw new TestException("出現例外");
//        return service.test(user);
}

結果如下:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

5 資料回應

在處理好了引數校驗以及例外處理之后,下一步就是要設定統一的規范化的回應資料,一般來說無論回應成功還是失敗都會有一個狀態碼,回應成功還會攜帶回應資料,回應失敗則攜帶相應的失敗資訊,因此,第一步是設計一個統一的回應體,

5.1 統一回應體

統一回應體需要創建回應體類,一般來說,回應體需要包含:

  • 狀態碼:String/int
  • 回應資訊:String
  • 回應資料:Object/T(泛型)

這里簡單的定義一個統一回應體Result:

@Data
@AllArgsConstructor
public class Result<T> {
    private String code;
    private String message;
    private T data;
}

接著修改全域例外處理類:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e)
    {
        ObjectError error = e.getBindingResult().getAllErrors().get(0);
        return new Result<>(error.getCode(),"引數校驗失敗",error.getDefaultMessage());
    }

    @ExceptionHandler(TestException.class)
    public Result<String> testExceptionHandler(TestException e)
    {
        return new Result<>(e.getCode(),"失敗",e.getMsg());
    }

使用Result<String>封裝回傳值,測驗如下:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

可以看到回傳了一個比較友好的資訊,無論是回應成功還是回應失敗都會回傳同一個回應體,當需要回傳具體的用戶資料時,可以修改控制層介面直接回傳Result<User>:

@PostMapping("test")
public Result<User> test(@RequestBody @Validated({User.Group.class}) User user)
{
    return service.test(user);
}

測驗:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

5.2 回應碼列舉

通常來說可以把回應碼做成列舉類:

@Getter
public enum ResultCode {
    SUCCESS("111","成功"),FAILED("222","失敗");

    private final String code;
    private final String message;
    ResultCode(String code,String message)
    {
        this.code = code;
        this.message = message;
    }
}

列舉類封裝了狀態碼以及資訊,這樣在回傳結果時,只需要傳入對應的列舉值以及資料即可:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e)
    {
        ObjectError error = e.getBindingResult().getAllErrors().get(0);
        return new Result<>(ResultCode.FAILED,error.getDefaultMessage());
    }

    @ExceptionHandler(TestException.class)
    public Result<String> testExceptionHandler(TestException e)
    {
        return new Result<>(ResultCode.FAILED,e.getMsg());
    }
}

5.3 全域包裝回應體

統一回應體是個很好的想法,但是還可以再深入一步去優化,因為每次回傳之前都需要對回應體進行包裝,雖然只是一行代碼但是每個介面都需要包裝一下,這是個很麻煩的操作,為了更進一步“偷懶”,可以選擇實作ResponseBodyAdvice<T>來進行全域的回應體包裝,

修改原來的全域例外處理類如下:

@RestControllerAdvice
public class GlobalExceptionHandler implements ResponseBodyAdvice<Object> {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e)
    {
        ObjectError error = e.getBindingResult().getAllErrors().get(0);
        return new Result<>(ResultCode.FAILED,error.getDefaultMessage());
    }

    @ExceptionHandler(TestException.class)
    public Result<String> testExceptionHandler(TestException e)
    {
        return new Result<>(ResultCode.FAILED,e.getMsg());
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return !methodParameter.getParameterType().equals(Result.class);
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        return new Result<>(o);
    }
}

實作了ResponseBodyAdvice<Object>:

  • supports方法:判斷是否支持控制器回傳方法型別,可以通過supports判斷哪些型別需要包裝,哪些不需要包裝直接回傳
  • beforeBodyWrite方法:當supports回傳true后,對資料進行包裝,這樣在回傳資料時就無需使用Result<User>手動包裝,而是直接回傳User即可

接著修改控制層,直接回傳物體類User而不是回應體包裝類Result<User>:

@PostMapping("test")
public User test(@RequestBody @Validated({User.Group.class}) User user)
{
    return service.test(user);
}

測驗輸出如下:

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

5.4 繞過全域包裝

雖然按照上面的方式可以使后端的資料全部按照統一的形式回傳給前端,但是有時候并不是回傳給前端而是回傳給其他第三方,這時候不需要code以及msg等資訊,只是需要資料,這樣的話,可以提供一個在方法上的注解來繞過全域的回應體包裝,

比如添加一個@NotResponseBody注解:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface NotResponseBody {
}

接著需要在處理全域包裝的類中,在supports中進行判斷:

@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
    return !(
        methodParameter.getParameterType().equals(Result.class) 
        ||
        methodParameter.hasMethodAnnotation(NotResponseBody.class)
    );
}

最后修改控制層,在需要繞過的方法上添加自定義注解@NotResponseBody即可:

@PostMapping("test")
@NotResponseBody
public User test(@RequestBody @Validated({User.Group.class}) User user)

6 總結

搞定SpringBoot難題!設計優秀的后端介面?輕松解決

7 原始碼

直接clone下來使用IDEA打開即可,每一次優化都做了一次提交,可以看到優化的程序,喜歡的話歡迎給個star:

  • Github
  • 碼云


作者:氷泠
鏈接:https://juejin.im/post/6860404263143604232
來源:掘金

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/208910.html

標籤:其他

上一篇:假設認識Java的第二天

下一篇:自增變數--自增自減運算子

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more