java Spring MVC:如何读取和更改@PathVariable值

whitzsjs  于 2023-01-11  发布在  Java
关注(0)|答案(3)|浏览(160)

这个问题和这个问题很相似,但是我不知道从哪里开始。
假设我有这样一个动作:

@GetMapping("/foo/{id}")
public Collection<Foo> listById(@PathVariable("id") string id) {
    return null;
}

如何截取listById方法并更改id的值(例如:连接字符串、用零填充等)?
我的场景是大多数ID都是用零填充的(长度不同),我不想把这个留给我 AJAX 调用。
预期解决方案:

@GetMapping("/foo/{id}")
public Collection<Foo> listById(@PathVariablePad("id", 4) string id) {
    // id would be "0004" on "/foo/4" calls
    return null;
}
t1qtbnec

t1qtbnec1#

好吧,我是这么做的。
由于我们不能继承注解,因此@PathVariable的目标只是参数,我们必须创建一个新的注解,如下所示:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface PathVariablePad {

    int zeros() default 0;

    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

}

现在我们需要创建一个HandlerMethodArgumentResolver,在本例中,由于我只需要在@PathVariable中左填充0,我们将继承PathVariableMethodArgumentResolver,如下所示:

public class PathVariablePadderMethodArgumentResolver extends PathVariableMethodArgumentResolver {

    private String leftPadWithZeros(Object target, int zeros) {
        return String.format("%1$" + zeros + "s", target.toString()).replace(' ', '0'); // Eeeewwwwwwwwwwww!
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(PathVariablePad.class);
    }

    @Override
    protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
        PathVariablePad pvp = parameter.getParameterAnnotation(PathVariablePad.class);

        return new NamedValueInfo(pvp.name(), pvp.required(), leftPadWithZeros("", pvp.zeros()));
    }

    @Override
    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        PathVariablePad pvp = parameter.getParameterAnnotation(PathVariablePad.class);

        return leftPadWithZeros(super.resolveName(name, parameter, request), pvp.zeros());
    }

}

最后,让我们注册方法参数解析器(xml):

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="my.package.PathVariablePadderMethodArgumentResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>

用法非常简单,下面是如何做到这一点:

@GetMapping("/ten/{id}")
public void ten(@PathVariablePad(zeros = 10) String id) {
    // id would be "0000000001" on "/ten/1" calls
}

@GetMapping("/five/{id}")
public void five(@PathVariablePad(zeros = 5) String id) {
    // id would be "00001" on "/five/1" calls
}
fnx2tebb

fnx2tebb2#

Spring @InitBinder注解和WebDataBinder类将帮助您在控制器方法调用之前拦截参数并处理其值。
文件:

完整代码模式:

@RestController
public class FooController {

    @InitBinder
    private void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                super.setValue("000" + text);
            }
        } );
    }

    @GetMapping(value = "/foo/{id}")
    public Foo sayHello(
            @PathVariable(value = "id") String id
    ) {
        return new Foo(id);
    }

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Foo {
        @XmlElement(name = "id")
        private String id;

        public Foo(String id) {
            this.id = id;
        }

        public Foo() {
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }
    }
}

和用法:

curl http://localhost:8080/foo/10 | xmllint --format -

回复:

<foo>
<id>00010</id>
</foo>
hrysbysz

hrysbysz3#

这非常相似,但用于解码@PathVariable值,如@yanefedor所带来的,但应用于应用程序中的所有控制器:

@org.springframework.web.bind.annotation.ControllerAdvice
public class ControllerAdvice {

    /**
     * Just to decode the data parsed into the Controller's methods parameters annotated with @PathVariable.
     *
     * @param binder
     */
    @InitBinder
    private void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                if (text == null) {
                    super.setValue(null);
                } else {
                    super.setValue(UriUtils.decode(text, Charset.defaultCharset()));
                }
            }
        });
    }
}

相关问题