SoFunction
Updated on 2025-04-09

Detailed explanation of pagination and parameter verification examples in Java Web development

Preface

In Java Web development, paging and parameter verification are two very important functions. This article will focus onPagination designandParameter verificationConduct discussion, including how to design reasonable paging query parameters and how to use themJava AnnotationsImplement parameter verification.

Pagination design

Why do you need pagination?

When the data volume of database table is large, if you directly query all data, it may causeSlow query, and even causedMemory overflow (OOM). Pagination is a common optimization method that canReduce database loadandImprove front-end rendering speed

How to design paging query parameters?

Pagination usually contains the following core parameters:

  • pageNo: The current page number, default is1
  • pageSize: The number of records returned per page, default is20
  • sortBy: Sort fields, such asidcreate_time
  • isAsc: Whether to ascending order, the default istrue

We can design a public parent classPageQueryTo help provide default parameters, we will also use mybatisplus in development to provide a method to convert it into a page object

@Data
@ApiModel(description = "Pagination Request Parameters")
@Accessors(chain = true)
public class PageQuery {
    public static final Integer DEFAULT_PAGE_SIZE = 20;
    public static final Integer DEFAULT_PAGE_NUM = 1;

    @ApiModelProperty(value = "page number", example = "1")
    @Min(value = 1, message = "The page number cannot be less than 1")
    private Integer pageNo = DEFAULT_PAGE_NUM;

    @ApiModelProperty(value = "Page size per page", example = "5")
    @Min(value = 1, message = "The number of queries per page cannot be less than 1")
    private Integer pageSize = DEFAULT_PAGE_SIZE;

    @ApiModelProperty(value = "Ascending order", example = "true")
    private Boolean isAsc = true;

    @ApiModelProperty(value = "Sorting Fields", example = "id")
    private String sortBy;

    public int from(){
        return (pageNo - 1) * pageSize;
    }

    public <T> Page<T> toMpPage(OrderItem ... orderItems) {
        Page<T> page = new Page<>(pageNo, pageSize);
        // Whether to manually specify the sorting method        if (orderItems != null &&  > 0) {
            for (OrderItem orderItem : orderItems) {
                (orderItem);
            }
            return page;
        }
        // Is there any sorted fields in the front end        if ((sortBy)){
            OrderItem orderItem = new OrderItem();
            (isAsc);
            (sortBy);
            (orderItem);
        }
        return page;
    }

    public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc) {
        if ((sortBy)){
            sortBy = defaultSortBy;
             = isAsc;
        }
        Page<T> page = new Page<>(pageNo, pageSize);
        OrderItem orderItem = new OrderItem();
        ();
        (sortBy);
        (orderItem);
        return page;
    }
    public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
        return toMpPage(Constant.DATA_FIELD_NAME_CREATE_TIME, false);
    }
}

Design Advantages

  • Default paging parameters, even if the front-end does not pass the page parameters, there will be no error.
  • Support sorting, can be passed according to the front endsortByandisAscSort.
  • Compatible with MyBatis-Plus, directly convert toPage<T>, reduce duplicate code.

How to use

In actual development, we can call it at the Service layertoMpPage()Method,PageQueryConvert to MyBatis-PlusPage<T>Object.

public Page<User> getUserList(PageQuery query) {
    Page<User> page = ();
    return (page, new QueryWrapper<>());
}

The art of parameter verification: from basic verification to deep defense

Why is parameter verification the first line of defense for system security?

In actual development, we often encounter such problems:

  • User enters mobile phone number as "1381234abcd"
  • Negative order amount
  • Illegal value is passed in the status field
  • The interface is attacked by maliciously constructed exception parameters

Parameter verificationLike the system guard, responsible for:

  • Intercept more than 80% of conventional attacks
  • Ensure the effectiveness of business data
  • Improve code readability and robustness
  • Reduce the verification pressure of downstream services

The core arsenal of JSR 380 specifications

Basic verification practice

@PostMapping("/create")
public Result createCoupon(@Valid @RequestBody CouponFormDTO dto) {
    // Business logic}

@Data
public class CouponFormDTO {
    @NotNull(message = "Coupon type cannot be empty")
    private Integer couponType;
    
    @Range(min=1, max=10, message="The number of limited numbers exceeds the range")
    private Integer limitCount;
    
    @EnumValid(enumeration = {0,1}, message="Illegal way of receiving")
    private ReceiveEnums receiveType;
}

Common annotation matrix:

annotation Applicable Type Applicable scenarios
@NotNull Any object Make sure the field cannot be empty
@NotBlank String Make sure the string cannot be empty
@NotEmpty Collection/array Make sure the list has data
@Size String/Collection Limit length or number of elements
@Min/@Max Numerical type Limit minimum/maximum value
@Pattern String Regular expression verification
@Email String Email format verification
@Future Date Time must be future time
@Past Date Time must be the past time
@Digits Numerical type Limit integer and decimal places

Deep analysis parameter verification principle

JSR 380 verification process

  • HTTP requests enter the Controller layer, bind parameters to DTO object.
  • **@Valid** Trigger verification mechanism, call Hibernate Validator.
  • Execute verification logic, iterate through the DTO field and check the annotation rules.
  • Verification failed thrown **MethodArgumentNotValidException**
  • Global exception handler catches exceptions, encapsulate and return an error message.

@Valid vs. @Validated Difference

characteristic @Valid @Validated
Range of action Single DTO DTO + Group Verification
Grouping support Not supported support
Applicable scenarios Basic verification Complex business scenarios
@PostMapping("/update")
public Result update(@Validated() @RequestBody UserDTO userDTO) {
    // Business logic processing}

Black technology for custom enumeration verification

The hidden pain of database design

When designing databases, we usually use a certain number to represent a certain state, such as:

CREATE TABLE coupon (
    status TINYINT COMMENT '0-not activated 1-effective 2-expired'
)

Traditional verification methods:

if (!(0,1,2).contains(status)) {
    throw new IllegalArgumentException();
}

defect

  • Verification logic dispersion
  • Poor maintenance
  • Cannot be reused

Custom annotation solutions

Define enumeration verification annotation

@Target()
@Retention()
@Constraint(validatedBy = )
public @interface EnumValid {
    int[] value() default {};
    String message() default "Illegal enum value";
    Class&lt;?&gt;[] groups() default {};
    Class&lt;? extends Payload&gt;[] payload() default {};
}

Implement verification logic

public class EnumValidator implements ConstraintValidator<EnumValid, Integer> {
    private Set<Integer> allowedValues = new HashSet<>();

    @Override
    public void initialize(EnumValid constraintAnnotation) {
        (())
              .forEach(allowedValues::add);
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        if (value == null) return true;
        return (value);
    }
}

In-depth analysis of the principle

ConstraintValidator life cycle

  • Initialization: Read the annotation configuration
  • During verification: Execute isValid method
  • Result processing: Returns the boolean value

Key points of implementation of JSR 380 specification

  • Verifier discovery mechanism: SPI loading
  • Cascade verification: Supports object nested verification
  • Group verification: Implement verification rules for different scenarios

The ultimate solution for complex verification

Sometimes, relying solely on our verification is more complicated, and we may need to write the verification logic ourselves.

We can help us achieve it through custom annotations + AOP

/**
  * After implementation, if the interface implements this interface when accessing the interface
  * Will be checked automatically by the self-interface
  **/
public interface Checker&lt;T&gt; {

    /**
      * Used to implement data logic that cannot be verified by validation
      */
    default void check(){

    }

    default void check(T data){
    }
}

Example of usage

Data
@ApiModel(description = "chapter")
public class CataSaveDTO implements Checker {
    @ApiModelProperty("Chapter, section, practice id")
    private Long id;
    @ApiModelProperty("Catalog Type 1: Chapter 2: Section 3: Test")
    @NotNull(message = "")
    private Integer type;
    @ApiModelProperty("Chapter Practice Name")
    private String name;
    @ApiModelProperty("Sorting chapters, chapters must be passed on, and subsections and exercises do not need to be passed on.")
    private Integer index;

    @ApiModelProperty("Subsection or exercise in the current chapter")
    @Size(min = 1, message = "No empty chapters")
    private List&lt;CataSaveDTO&gt; sections;

    @Override
    public void check() {
        //The name is empty check        if(type ==  &amp;&amp; (name)) {
            throw new BadRequestException(.COURSE_CATAS_SAVE_NAME_NULL);
        }else if((name)){
            throw new BadRequestException(.COURSE_CATAS_SAVE_NAME_NULL2);
        }
        //Name length issue        if (type ==  &amp;&amp; () &gt; 30){
            throw new BadRequestException(.COURSE_CATAS_SAVE_NAME_SIZE);
        }else if(() &gt; 30) {
            throw new BadRequestException(.COURSE_CATAS_SAVE_NAME_SIZE2);
        }
        if((sections)){
            throw new BadRequestException("No empty chapters");
        }

    }
}

Interface method parameter verification device

/**
  * Interface method parameter verification device
  **/
@Retention()
@Target()
public @interface ParamChecker {
}

Define a facet class

@Aspect
@Slf4j
@SuppressWarnings("all")
public class CheckerAspect {

    @Before("@annotation(paramChecker)")
    public void before(JoinPoint joinPoint, ParamChecker paramChecker) {
        Object[] args = ();
        if((args)){
            //Transaction method parameters, whether the parameters implement the Checker interface            for (Object arg : args){
                if(arg instanceof Checker) {
                    //Calling the check method to verify the business logic                    ((Checker)arg).check();
                }else if(arg instanceof List){
                    //If the parameters are a set, check it                    ((List) arg);
                }
            }
        }
    }
}

Tools and methods

    /**
      * Set verification logic
      *
      * @param data Collection to be verified
      * @param checker
      * @param <T> Collection element type
      */
    public static  &lt;T&gt; void  check(List&lt;T&gt; data, Checker&lt;T&gt; checker){
        if(data == null){
            return;
        }
        for (T t : data){
            (t);
        }
    }

    /**
      * Set verification logic
      *
      * @param data Collection to be verified
      * @param <T> Collection element type
      */
    public static  &lt;T extends Checker&lt;T&gt;&gt; void  check(List&lt;T&gt; data){
        if(data == null){
            return;
        }
        for (T t : data){
            ();
        }
    }

Annotation usage

  @PostMapping("baseInfo/save")
    @ApiOperation("Save basic course information")
    @ParamChecker
    //Check fields that are not business restricted    public CourseSaveVO save(@RequestBody @Validated() CourseBaseInfoSaveDTO courseBaseInfoSaveDTO) {
        return (courseBaseInfoSaveDTO);
    }

Note: The section class is not included in the IOC container management. If it is a single project and the component annotation is enough. If it is a multi-module project, use the automatic assembly function.

Summarize

This is the end of this article about detailed explanations of pagination and parameter verification in Java Web development. For more related Java Web pagination and parameter verification content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!