[Spring MVC] Implement dynamic parameters included in URL without using Optional (~ Java7)

I'm currently building a web system based on Java 7. There are various reasons why I don't use Java 8 In exchange for that reason, the problem was that Optional could not be used.

Implement using Optional (for Java 8 or later)

Optional is "I don't know if the argument will have a value, but I'll try to receive it!" However, in Spring MVC, it is used to get the URL parameter expressed in REST format.

For example, suppose you define the controller as follows:

SampleController.java


@Controller
@RequestMapping("page")
public class SampleController {

  @RequestMapping({"", "{num}"})
  public ModelAndView getMessages(@PathVariable("num") Optional<String> num) {
    if (num.ifPresent()) {
      //If the parameter is present
    } else {
      //If the parameter does not exist
    }
    return new ModelAndView("index");
  }

}

It is an implementation that wants to process the same action method with or without parameter values. This time, we assume the URLs http: // localhost / page / 1 and http: // localhost / page.

When the former is requested, the character string after the second slash (** 1 **) is judged as a parameter, so ** 1 ** is entered in the argument num, and the result of ```ifPresent ()` `` to determine if there was an input is ** true **. Here, since the type variable is * \ <String > *, it is possible to get the value with num.get () as a character string type.

If the latter URL is requested, it is determined that the parameter value does not exist and no ** value is entered in the argument num **. Therefore, the judgment result of ```ifPresent () `` `is ** false **.

In Java8 or later, the above implementation is sufficient. Up to this point, it is a common method that is also introduced on external sites and within Qiita.

Implement without using Optional

However, since Optional is a class newly implemented in Java8, the above program cannot be used as it is until Java7. I also thought "Is it possible to set the argument type to * String * and get it with * null *?", But I throw a ** NullPointerException **.

You can implement it by splitting the action method, but I don't really want to do that because I feel like I've lost. (I didn't want to have at least two of the same source in the same class, or implement a private method to avoid the former. If you do, I want to use the same source. )

Implementation method

Then, what to do is to create a class that can be used like Optional (hereinafter, ** parameter class **) and use it as an alternative.

SampleParameter.java


public class SampleParameter {
  private String num;

  //If you do not use lombok you need:
  // pubric String getNum() { return num; }
  // pubric String setNum(String num) { this.num = num; }

  boolean ifPresent() {
    return num != null;
  }
}

SampleController.java


@Controller
@RequestMapping("page")
public class SampleController {

  @RequestMapping({"", "{num}"})
  public ModelAndView getMessages(@PathVariable("num") SampleParameter num) {
    if (num.ifPresent()) {
      //If the parameter is present
    } else {
      //If the parameter does not exist
    }
    return new ModelAndView("index");
  }

}

Yes, it looks like this. As with `` `@ ModelAttribute, it looks like you're making something like a form class. In fact, if the parameter class does not have the parameter name specified by @ RequestMapping```, Be careful as it throws a ** NullPointerException **.

Benefits and implementation precautions

merit

At first glance, it looks like we are reinventing the wheel, but it is also a fairly convenient class.

  1. The getter / setter method can be modified.
    This is the greatest merit. In fact, when I defined the parameter class, I didn't use lombok
    I put the ** decryption process ** of the parameters encrypted with AES-128 + Base64 in the getter.
  2. You can add your favorite method / you can add your favorite method.
    You can do whatever you want. (However, it is necessary to prepare a getter corresponding to the parameter name)
  3. You can freely extend / implement.
    It doesn't mean that Optional is not possible, but it is an original class, so
    It can be inherited / implemented freely.

Implementation notes

On the contrary, the following points should be noted when considering the implementation.

  1. It is necessary to prepare a setter method in the parameter class that matches the parameter name of ** @ RequestMapping **.
    For example, you need the `setNum (Object) ``` method for @ RequestMapping ({"", "{num}"}) `` .
    You may not be very aware of it when creating setter methods with lombok.
  2. It is also necessary to match the argument name of the action method.
    It's a big deal if you have proper rules, but it's awkward if you don't.
    (There may be a workaround here)

Recommended Posts

[Spring MVC] Implement dynamic parameters included in URL without using Optional (~ Java7)
Implement reCAPTCHA v3 in Java / Spring
Map without using an array in java
Implement share button in Rails 6 without using Gem
Implement test doubles in JUnit without using external libraries
Test field-injected class in Spring boot test without using Spring container
Implement Thread in Java and try using anonymous class, lambda
Authenticate 3 or more parameters in JSON format using Spring Security
How to control transactions in Spring Boot without using @Transactional
Try using RocksDB in Java
Java Config with Spring MVC
Implement two-step verification in Java
Implement Basic authentication in Java
Implement math combinations in Java
2 Implement simple parsing in Java
Using Mapper with Java (Spring)
Implement Email Sending in Java
Implement functional quicksort in Java
Implement rm -rf in Java.
Implement XML signature in Java
[Java] Get data from DB using singleton service in Spring (Boot)
Uploading and downloading files using Ajax in Spring Boot (without JQuery)