Pra*_*r D 9 spring spring-mvc spring-boot
我得到一个加密的String作为查询参数到Spring休息控制器方法.
我希望在它到达方法之前解密字符串,基于一些注释(@Decrypt比如下面的话)
@RequestMapping(value = "/customer", method = RequestMethod.GET)
public String getAppointmentsForDay(@RequestParam("secret") @Decrypt String customerSecret) {
System.out.println(customerSecret); // Needs to be a decrypted value.
...
}
Run Code Online (Sandbox Code Playgroud)
Formatter在这个用例中,自定义是正确的方法吗?
或者我应该使用自定义HandlerMethodArgumentResolver?
自定义实现org.springframework.format.Formatter是此用例的有效方法.这就是Spring本身如何为日期,货币,数字样式等实现格式化程序.
脚步:
声明注释Decrypt::
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
public @interface Decrypt {
}
Run Code Online (Sandbox Code Playgroud)声明一个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();
}
};
}
}
Run Code Online (Sandbox Code Playgroud)使用您的Web上下文注册此formatter工厂:
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());
}
}
Run Code Online (Sandbox Code Playgroud)而已.
有了上述内容,所有@RequestParam符合条件的用法都@Decrypt将通过parse()声明的方法传递,DecryptAnnotationFormatterFactory以便您可以在那里实现解密调用.
为了证明这一点,以下测试通过:
@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"));
}
}
Run Code Online (Sandbox Code Playgroud)
HandlerMethodArgumentResolver 在这方面是最好的。
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Decrypt {
String value();
}
Run Code Online (Sandbox Code Playgroud)
public class DecryptResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterAnnotation(Decrypt.class) != null;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
Decrypt attr = parameter.getParameterAnnotation(Decrypt.class);
String encrypted = webRequest.getParameter(attr.value());
String decrypted = decrypt(encrypted);
return decrypted;
}
private String decrypt(String encryptedString) {
// Your decryption logic here
return "decrypted - "+encryptedString;
}
}
Run Code Online (Sandbox Code Playgroud)
@Configuration
@EnableMvc // If you're not using Spring boot
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new DecryptResolver());
}
}
Run Code Online (Sandbox Code Playgroud)
@RequestMapping(value = "/customer", method = RequestMethod.GET)
public String getAppointmentsForDay(@Decrypt("secret") String customerSecret) {
System.out.println(customerSecret); // Needs to be a decrypted value.
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3416 次 |
| 最近记录: |