简体   繁体   中英

Convert @RequestParam to custom Object

Have a problem with optimizing search request. I have search method that accepts parameters in url query like:

http://localhost:8080/api?code.<type>=<value>&name=Test

Example: http://localhost:8080/api?code.phone=9999999999&name=Test

Defined SearchDto:

public class SearchDto {

    String name;    
    List<Code> code;

}

Defined Code class:

public class Code {

    String type;    
    String value;

}

Currently I'm using Map<String,String> as incoming parameter for the method:

@GetMapping("/search")
public ResponseEntity<?> search(final @RequestParam Map<String, String> searchParams) {
  return service.search(searchParams);
}

Then manually converting map values for SearchDto class. Is it possible to get rid of Map<String,String> and pass SearchDto directly as argument in controller method?

Passing a json in querystring is actually a bad practice, since it decrease the security and sets limits on the number of parameters you can send to your endpoint.

Technically speaking, you could make everything work by using your DTO as a controller's parameter, then URL encoding the json before you send it to the backend.

The best option, in your case, is to serve an endpoint that listen to a POST request: it is not an error, neither a bad practise, to use POST when performing a search.

you can customize a HandlerMethodArgumentResolver to implement it.

but, if you want a object receive incoming parameter. why not use POST

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Example {
}
public class ExampleArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Example requestParam = parameter.getParameterAnnotation(Example.class);
        return requestParam != null;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

        ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);

        Map<String, String[]> parameterMap = webRequest.getParameterMap();
        Map<String, String> result = CollectionUtils.newLinkedHashMap(parameterMap.size());
        parameterMap.forEach((key, values) -> {
            if (values.length > 0) {
                result.put(key, values[0]);
            }
        });

        //here will return a map object.  then you convert map to your object, I don't know how to convert , but you have achieve it.
        return o;
    }

}

add to container

@Configuration
@EnableWebMvc
public class ExampleMvcConfiguration implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new ExampleArgumentResolver());
    }
}

usage

@RestController
public class TestCtrl {


    @GetMapping("api")
    public Object gg(@Example SearchDto searchDto) {
        System.out.println(searchDto);
        return "1";
    }

    @Data
    public static class SearchDto {
        String name;
        List<Code> code;
    }

    @Data
    public static class Code {
        String type;
        String value;
    }
}

Here is a demo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM