Spring MVC 中@RequestParam 的自定义转换器 [英] Custom converter for @RequestParam in Spring MVC

查看:60
本文介绍了Spring MVC 中@RequestParam 的自定义转换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在获取一个加密字符串作为 Spring rest 控制器方法的查询参数.

I am getting an encrypted String as Query parameter to a Spring rest controller method.

我想在字符串到达​​基于一些注释(比如@Decrypt)的方法之前解密字符串

I wanted to decrypt the string before it reaches the method based on some annotation (say @Decrypt) like below

@RequestMapping(value = "/customer", method = RequestMethod.GET)
public String getAppointmentsForDay(@RequestParam("secret") @Decrypt String customerSecret) {
    System.out.println(customerSecret);  // Needs to be a decrypted value.
   ...
}

自定义Formatter 在这个用例中是正确的方法吗?

Is a custom Formatter the right approach in this use case?

或者我应该使用自定义的HandlerMethodArgumentResolver?

Or should I use a custom HandlerMethodArgumentResolver?

推荐答案

org.springframework.format.Formatter 的自定义实现是此用例的有效方法.这就是 Spring 本身为日​​期、货币、数字样式等实现格式化程序的方式.

A custom implementation of org.springframework.format.Formatter is a valid approach for this use case. This is how Spring itself implements formatters for dates, currencies, number styles etc.

步骤:

  1. 声明一个注解:Decrypt:

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
public @interface Decrypt {

}

  • 声明一个使用新注解的AnnotationFormatterFactory:

    import org.springframework.context.support.EmbeddedValueResolutionSupport;
    import org.springframework.format.AnnotationFormatterFactory;
    import org.springframework.format.Formatter;
    import org.springframework.format.Parser;
    import org.springframework.format.Printer;
    
    import java.text.ParseException;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Locale;
    import java.util.Set;
    
    public class DecryptAnnotationFormatterFactory extends EmbeddedValueResolutionSupport
            implements AnnotationFormatterFactory<Decrypt> {
    
        @Override
        public Set<Class<?>> getFieldTypes() {
            Set<Class<?>> fieldTypes = new HashSet<>();
            fieldTypes.add(String.class);
            return Collections.unmodifiableSet(fieldTypes);
        }
    
        @Override
        public Printer<String> getPrinter(Decrypt annotation, Class<?> fieldType) {
            return configureFormatterFrom(annotation);
        }
    
        @Override
        public Parser<String> getParser(Decrypt annotation, Class<?> fieldType) {
            return configureFormatterFrom(annotation);
        }
    
        private Formatter<String> configureFormatterFrom(Decrypt annotation) {
            // you could model something on the Decrypt annotation for use in the decryption call
            // in this example the 'decryption' call is stubbed, it just reverses the given String
            // presumaby you implementaion of this Formatter will be different e.g. it will invoke your encryption routine
            return new Formatter<String>() {
                @Override
                public String print(String object, Locale locale) {
                    return object;
                }
    
                @Override
                public String parse(String text, Locale locale) throws ParseException {
                    return new StringBuilder(text).reverse().toString();
                }
            };
        }
    }
    

  • 在您的网络环境中注册这个格式化工厂:

  • Register this formatter factory with your web context:

    import org.springframework.context.annotation.Configuration;
    import org.springframework.format.FormatterRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    public class WebConfigurer extends WebMvcConfigurerAdapter {
        @Override
        public void addFormatters(FormatterRegistry registry) {
            super.addFormatters(registry);
            registry.addFormatterForFieldAnnotation(new DecryptAnnotationFormatterFactory());
        }
    }
    

  • 就是这样.

  • That's it.

    有了上述内容,所有使用 @Decrypt 限定的 @RequestParam 的用法都将通过 parse()DecryptAnnotationFormatterFactory 中声明的方法,以便您可以在那里实现您的解密调用.

    With the above in place, all usages of a @RequestParam which are qualified with @Decrypt will be passed through the parse() method declared in DecryptAnnotationFormatterFactory so you can implement your decryption call there.

    为了证明这一点,以下测试通过:

    To prove this, the following test passes:

    @RunWith(SpringRunner.class)
    @WebMvcTest(controllers = YourController.class)
    public class YourControllerTest {
        @Autowired
        private MockMvc mockMvc;
    
        @Test
        public void theSecretRequestParameterWillBeConverted() throws Exception {
            MvcResult mvcResult = mockMvc.perform(get("/customer?secret=abcdef")).andExpect(status().isOk()).andReturn();
    
            // the current implementation of the 'custom' endpoint returns the value if the secret request parameter and
            // the current decrypt implementation just reverses the given value ...
            assertThat(mvcResult.getResponse().getContentAsString(), is("fedcba"));
        }
    }
    

    这篇关于Spring MVC 中@RequestParam 的自定义转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆