SpringBoot 에서 사용자 정의 주 해 를 사용 하여 매개 변수 비 공 검 사 를 실현 하 는 예제 입 니 다.
16090 단어 매개 변수비공 식 검사SpringBoot사용자 정의 주석
프로젝트 를 작성 한 지 얼마 되 지 않 아 웹 배경 인 터 페 이 스 를 쓸 때 전단 에 들 어 오 는 매개 변 수 를 규칙 적 으로 검사 합 니 다.만약 에 가입 이 적 으 면 검사 해 야 할 매개 변수 가 비교적 많 으 면 if 검 사 를 사용 하면 대량의 중복 작업 을 가 져 올 수 있 고 코드 를 보면 매우 지루 할 수 있 습 니 다.그래서 저 는 먼저 몇 가지 수단 을 통 해 이 점 을 개선 할 수 있 는 지 생각 합 니 다.컨트롤 러 층 으로 하여 금 파라미터 검사 의 불필요 한 코드 를 줄 이 고 코드 의 읽 을 수 있 도록 합 니 다.
다른 사람의 코드 를 읽 어 보 니 annotation 주 해 를 사용 하 는 것 이 비교적 편리 한 수단 임 을 알 수 있 습 니 다.SpringBoot 가 자체 적 으로 가지 고 있 는@RequestParam 주 해 는 요청 에 있 는 이 매개 변수 가 존재 하 는 지 확인 할 수 있 습 니 다.그러나 이 매개 변 수 는 null 이 아니 라 비어 있 지 않 으 면 판단 할 수 없 기 때문에 요청 매개 변수 에 있 는 주 해 를 강화 해 볼 수 있 습 니 다.
준비 작업
앞의 생각 이 있 으 면 우 리 는 먼저 틀 을 세 워 나 가자.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.bestzuo</groupId>
<artifactId>springboot-annotation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-annotation</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
그 중에서 aspectjweaver 는 AOP 와 관련 된 주 해 를 도입 하 는 데 사 용 됩 니 다.예 를 들 어@Aspect,@Pointcut 등 입 니 다.사용자 정의 주 해 를 사용 하여 비 어 있 는 검 사 를 통일 합 니 다.
전체적인 사고:주 해 를 사용자 정의 하고 필요 한 매개 변수 에 이 주 해 를 추가 한 다음 절단면 을 정의 하여 이 매개 변수 가 비어 있 는 지 확인 합 니 다.비어 있 으 면 사용자 정의 이상 을 던 집 니 다.이 이상 은 사용자 정의 이상 프로세서 에 의 해 캡 처 된 다음 에 해당 하 는 오류 정 보 를 되 돌려 줍 니 다.
1.사용자 정의 주석
Param Check 이라는 주 해 를 만 듭 니 다.코드 는 다음 과 같 습 니 다.
package cn.bestzuo.springbootannotation.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* ,
*
* @author zuoxiang
* @since 2020-11-11
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamCheck {
/**
* ,
*/
boolean notNull() default true;
}
그 중에서@Target
주해 중의ElementType.PARAMETER
는 이 주해 의 작용 범 위 를 나타 낸다.우 리 는 소스 코드 를 보면 주해 의 작용 범위 정의 가 비교적 광범 위 하고 방법,파라미터,구조 방법,현지 변수,매 거 등에 작용 할 수 있다.
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
물론,우리 가 정의 한 주 해 는 확장 할 수 있 습 니 다.매개 변수 가 비어 있 는 지 확인 하 는 것 뿐만 아니 라,예 를 들 어 문자열 의 길 이 를 늘 릴 수 있 습 니 다.2.사용자 정의 이상 클래스
사용자 정의 주석 에 맞 춰 사용 하기 위해 서 입 니 다.사용자 정의 주석 규격 에 맞지 않 는 인 자 를 검사 하면 사용자 정의 이상 을 던 져 서 되 돌 릴 수 있 습 니 다.코드 는 다음 과 같 습 니 다:
package cn.bestzuo.springbootannotation.exception;
public class ParamIsNullException extends RuntimeException {
private final String parameterName;
private final String parameterType;
public ParamIsNullException(String parameterName, String parameterType) {
super("");
this.parameterName = parameterName;
this.parameterType = parameterType;
}
/**
*
*
* @return
*/
@Override
public String getMessage() {
return "Required " + this.parameterType + " parameter \'" + this.parameterName + "\' must be not null !";
}
public final String getParameterName() {
return this.parameterName;
}
public final String getParameterType() {
return this.parameterType;
}
}
이 이상 계승RuntimeException
은 두 멤버 의 속성,재 작성getMessage()
방법 을 정의 했다.기 존
org.springframework.web.bind.MissingServletRequestParameterException
클래스 대신 이 이상 을 사용자 정의 하 는 이 유 는 MissingServletRequestParameterException Checked
이상 으로 동적 에이전트 과정 에서java.lang.reflect.UndeclaredThrowableException
이상 을 일 으 키 기 쉽 기 때문이다.3.사용자 정의 AOP
코드 는 다음 과 같 습 니 다:
package cn.bestzuo.springbootannotation.aop;
import cn.bestzuo.springbootannotation.annotation.ParamCheck;
import cn.bestzuo.springbootannotation.exception.ParamIsNullException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@Component
@Aspect
public class ParamCheckAop {
private static final Logger LOGGER = LoggerFactory.getLogger(ParamCheckAop.class);
/**
* , controller
*/
@Pointcut("execution(public * cn.bestzuo.controller..*.*(..))")
public void checkParam() {
}
@Before("checkParam()")
public void doBefore(JoinPoint joinPoint) {
}
/**
*
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("checkParam()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = ((MethodSignature) pjp.getSignature());
//
Method method = signature.getMethod();
// ,
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations.length == 0) {
return pjp.proceed();
}
//
String[] paramNames = signature.getParameterNames();
//
Object[] paramValues = pjp.getArgs();
//
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterAnnotations.length; i++) {
for (int j = 0; j < parameterAnnotations[i].length; j++) {
// ParamCheck , notNull()=true,
if (parameterAnnotations[i][j] != null && parameterAnnotations[i][j] instanceof ParamCheck && ((ParamCheck) parameterAnnotations[i][j]).notNull()) {
paramIsNull(paramNames[i], paramValues[i], parameterTypes[i] == null ? null : parameterTypes[i].getName());
break;
}
}
}
return pjp.proceed();
}
/**
* return ( )
*
* @param joinPoint
*/
@AfterReturning("checkParam()")
public void doAfterReturning(JoinPoint joinPoint) {
}
/**
* , , ParamIsNullException
*
* @param paramName
* @param value
* @param parameterType
*/
private void paramIsNull(String paramName, Object value, String parameterType) {
if (value == null || "".equals(value.toString().trim())) {
throw new ParamIsNullException(paramName, parameterType);
}
}
}
4.전역 이상 프로세서이 이상 처리 장 치 는 ParamCheckAop 클래스 에서 던 진 ParamIsNullException 이상 을 포착 하여 처리 합 니 다.코드 는 다음 과 같 습 니 다.
import cn.bestzuo.springbootannotation.common.Result;
import cn.bestzuo.springbootannotation.enums.EnumResultCode;
import cn.bestzuo.springbootannotation.utils.ResponseMsgUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
public class GlobalExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
*
*
* @param ex
* @return
*/
@ExceptionHandler({MissingServletRequestParameterException.class, ParamIsNullException.class})
public Result<String> requestMissingServletRequest(Exception ex) {
LOGGER.error("request Exception:", ex);
return ResponseMsgUtil.builderResponse(EnumResultCode.FAIL.getCode(), ex.getMessage(), null);
}
/**
* : ,
*
* @param request
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
public Result<String> errorHandler(HttpServletRequest request, Exception e) {
LOGGER.error("request Exception:", e);
return ResponseMsgUtil.exception();
}
}
5.테스트먼저 컨트롤 러 를 정의 하여 테스트 를 진행 합 니 다:
@RestController
public class HelloController {
/**
* @RequestParam
*
* @param name
* @return
*/
@GetMapping("/hello1")
public Result<String> hello1(@RequestParam String name) {
return ResponseMsgUtil.builderResponse(EnumResultCode.SUCCESS.getCode(), " ", "Hello," + name);
}
/**
* @ParamCheck
*
* @param name
* @return
*/
@GetMapping("/hello2")
public Result<String> hello2(@ParamCheck String name) {
return ResponseMsgUtil.builderResponse(EnumResultCode.SUCCESS.getCode(), " ", "Hello," + name);
}
/**
* @ParamCheck @RequestParam
*
* @param name
* @return
*/
@GetMapping("/hello3")
public Result<String> hello3(@ParamCheck @RequestParam String name) {
return ResponseMsgUtil.builderResponse(EnumResultCode.SUCCESS.getCode(), " ", "Hello," + name);
}
}
테스트 액세스http://localhost:8080/hello1이 때@RequestParam 주석 만 있 습 니 다.name 인 자 를 추가 하지 않 으 면 이상 을 요청 합 니 다.또한 콘 솔 에 서 는 MissingServletRequestParameter 예외:Required String parameter'name'is not present]이상 을 알 립 니 다.
하면,만약,만약...http://localhost:8080/hello2?name=,이 때 는 사용자 정의@Param Check 주 해 를 사용 합 니 다.이 때 는 인자 입력 이 없 으 면 입력 의 이상 도 캡 처 합 니 다.
하면,만약,만약...http://localhost:8080/hello3?name=,이 때 는 매개 변수 가 검증 되 어 있 고 사용자 정의 Param Check 가 비어 있 지 않 기 때문에 이 때 는 매개 변 수 를 추가 하지 않 으 면 이상 을 던 집 니 다.
콘 솔 에서 사용자 정의 이상 던 지기:
테스트 요약:
매개 변수 이름 이 비어 있 을 때 두 개의 주 해 를 추가 하 는 인 터 페 이 스 는 모두 매개 변수 가 비어 있 으 면 안 된다 는 것 을 알려 줍 니 다.
매개 변수 이름 이 비어 있 지 않 고 값 이 비어 있 을 때@RequestParam 주 해 는 잘못 되 지 않 지만@Param Check 주 해 는 매개 변수'name'의 값 이 비어 있 습 니 다.
6.총화
7.코드 부록
위 에서 사용 한 코드:
package cn.bestzuo.springbootannotation.common;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Result<T> {
private Integer resCode;
private String resMsg;
private T data;
}
package cn.bestzuo.springbootannotation.enums;
/**
*
*
* @author zuoxiang
* @since 2020-11-11
*/
public enum EnumResultCode {
SUCCESS(200),
FAIL(400),
UNAUTHORIZED(401),
NOT_FOUND(404),
INTERNAL_SERVER_ERROR(500);
private final int code;
EnumResultCode(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
package cn.bestzuo.springbootannotation.utils;
import cn.bestzuo.springbootannotation.common.Result;
import cn.bestzuo.springbootannotation.enums.EnumResultCode;
public class ResponseMsgUtil {
/**
*
*
* @param code
* @param msg
* @param data
* @param <T>
* @return
*/
public static <T> Result<T> builderResponse(int code, String msg, T data) {
Result<T> res = new Result<>();
res.setResCode(code);
res.setResMsg(msg);
res.setData(data);
return res;
}
/**
*
*
* @param <T>
* @return
*/
public static <T> Result<T> exception() {
return builderResponse(EnumResultCode.INTERNAL_SERVER_ERROR.getCode(), " ", null);
}
}
이상 은 SpringBoot 에서 매개 변수 비 공 검 사 를 실현 하 는 예제 에 대한 상세 한 내용 입 니 다.SpringBoot 매개 변수 비 공 검 사 를 위 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
MyBatis 매개변수 유형이 String일 때 자주 발생하는 문제 및 해결 방법1. 매개변수가 String일 때 보간 문제 다음 Dao 인터페이스 방법이 있다고 가정해 보세요. 대응하는 마퍼.xml 일반적으로 우리는 이런 식으로 쓰는데 다른 유형에 대해서는 맞지만 String을 위해 던지는 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.