programing

Spring MVC의 @RequestParam에 대한 사용자 지정 변환기

goodsources 2023. 8. 4. 23:02
반응형

Spring MVC의 @RequestParam에 대한 사용자 지정 변환기

Spring rest 컨트롤러 메서드에 암호화된 String as Query 매개 변수를 가져오는 중입니다.

나는 문자열이 어떤 주석을 기반으로 메소드에 도달하기 전에 해독하고 싶었습니다.@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.
   ...
}

사용자 정의Formatter이 사용 사례에서 올바른 접근 방식?

아니면 사용자 정의를 사용해야 합니까?HandlerMethodArgumentResolver?

의 사용자 정의 구현org.springframework.format.Formatter는 이 사용 사례에 대한 유효한 접근 방식입니다.이것이 Spring 자체가 날짜, 통화, 숫자 스타일 등에 대한 형식을 구현하는 방법입니다.

단계:

  1. 주석 선언:Decrypt:

    import java.lang.annotation.*;
    
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
    public @interface Decrypt {
    
    }
    
  2. 선언 anAnnotationFormatterFactory새 주석을 사용합니다.

    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();
                }
            };
        }
    }
    
  3. 이 포맷터 공장을 웹 컨텍스트에 등록합니다.

    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());
        }
    }
    
  4. 바로 그겁니다.

위와 같은 조건 하에서, 모든 사용은@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"));
    }
}

이 점에서 HandlerMethodArgumentResolver가 가장 좋습니다.

  1. 주석을 작성합니다.

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Decrypt {
    String value();
}
  1. 사용자 지정 처리기 메서드 인수 확인기 만들기:

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;
    }
}
  1. 해결 프로그램을 등록합니다.

@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());
    }
}
  1. Voila, 암호 해독된 매개 변수가 있습니다.더 이상 @RequestParam을 사용할 필요가 없습니다.

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

다음을 추가하여 시도할 수 있습니다.CharacterEncodingFilter와 함께init-param encoding UTF-8web.xml파일. 이 예제를 확인하십시오.

그래도 작동하지 않으면 아래 매개 변수를 위에 추가하여 인코딩을 강제로 적용할 수 있습니다.init-param.

<init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
</init-param>

그게 당신에게 효과가 있는지 알려주세요.

암호 해독된 데이터를 데이터 전송 개체로 래핑하는 경우 Spring's Converter 프레임워크를 사용할 수 있습니다.

public class Decrypted { // data transfer object

    private final String value;

    public Decrypted(String value){
        this.value = value;
    }

    public String get(){
        return value;
    }
}

인터페이스 구현org.springframework.core.convert.converter.Converter추가합니다.@Component주석

@Component
public class DecryptConverter implements Converter<String, Decrypted> {
    @Override
    public Decrypted convert(String value) {
        return new Decrypted(decrypt(value)); // you implement "decrypt"
    }
}

등록합니다.

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DecryptConverter());
    }
}

그런 다음 다음 매개 변수에 래퍼 유형(암호 해독됨)을 사용합니다.

@RequestMapping(value = "/customer", method = RequestMethod.GET)
public String getAppointmentsForDay(@RequestParam("secret") Decrypted customerSecret) {
    System.out.println(customerSecret.get());  // decrypted value
}

https://www.baeldung.com/spring-enum-request-param 도 참조하십시오.

언급URL : https://stackoverflow.com/questions/46728972/custom-converter-for-requestparam-in-spring-mvc

반응형