İstekteki parametrelerin bizim metodumuza göre çözümlenmesini sağlar. Normalde spring zaten HTTP isteğini Rest parametre tipine çevirir, ancak burada bizim istediğimiz, HTTP isteğindeki bir header alanını metoda parametre olarak geçmek.
Örnek
Controller sınıfı şöyle olsun
@RestController@RequestMapping("/api")public class ExampleController {@GetMapping("/context")public ContextInformation getApplicationContext(ContextInformation contextInformation) {return contextInformation;}}
Http isteği şöyle olsun
GET /api/context HTTP/1.1Accept: */*Accept-Encoding: gzip, deflateConnection: keep-aliveHost: localhost:8080User-Agent: HTTPie/2.2.0X-App-Context: {"parentId":1000,"profile":"ADMIN","userId":1}
Bu isteği kendi RestController sınıfına yönlendirmek için şöyle yaparız
HandlerArgumentResolver sınıfını Spring'e eklemek için şöyle yaparız@Componentpublic class ContextInformationResolver implements HandlerMethodArgumentResolver {private final ObjectMapper objectMapper;public ContextInformationResolver(ObjectMapper objectMapper) {this.objectMapper = objectMapper;}@Overridepublic boolean supportsParameter(MethodParameter methodParameter) {return methodParameter.getParameterType().equals(ContextInformation.class);}@Overridepublic Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer,NativeWebRequest nativeWebRequest,
WebDataBinderFactory webDataBinderFactory)
throws Exception {String jsonContext = nativeWebRequest.getHeader("X-App-Context");return objectMapper.readValue(jsonContext, ContextInformation.class);}}
@Configuration@EnableWebMvcclass WebMvcContext extends WebMvcConfigurerAdapter {@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {argumentResolvers.add(new ContextInformationResolver ());}}
Diğer
Alternatif 1
Bu sınıfa bir diğer alternatif ise, OncePerRequestFilter kullanarak Http isteği içindeki header alanını HttpServletRequest içindeki attribute map'ine yerleştirmek
Örnek
Elimizde şöyle bir filtre olsun
@Componentpublic class HeaderProcessorFilter extends OncePerRequestFilter {private final RequestUtils requestUtils;public HeaderProcessorFilter(RequestUtils requestUtils) {this.requestUtils = requestUtils;}@Overridepublic void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws IOException, ServletException {
requestUtils.storeContextInformationAsRequestAttribute(request);filterChain.doFilter(request, response);}}
Header değerini attribute değerine atamak için şöyle yaparız
@Componentpublic class RequestUtils {private final ObjectMapper objectMapper;private static final String APP_CONTEXT_HEADER = "X-App-Context";private static final String REQUEST_ATTRIBUTE_APP_CONTEXT = "appContext";public RequestUtils(ObjectMapper objectMapper) {this.objectMapper = objectMapper;}public void storeContextInformationAsRequestAttribute(HttpServletRequest request)
throws IOException {String jsonHeader = request.getHeader(APP_CONTEXT_HEADER);if (jsonHeader != null) {request.setAttribute(REQUEST_ATTRIBUTE_APP_CONTEXT,objectMapper.readValue(jsonHeader, ContextInformation.class));}}}
Alternatif 2
OncePerRequestFilter kullanarak Http isteği içindeki header alanını HttpServletRequest içindeki attribute map'ine yerleştirilir. Daha bir AOP @Before kullanılarak bir aspect yazılır ve aspect içinde ContextInformation ile bir işlem yapılıyor.
Bu yöntemi kulllanınca Controller'ın metodunda da ContextInformation parametresine gerek kalmıyor.
Hiç yorum yok:
Yorum Gönder