Как я получаю HandlerMethod соответствует HttpServletRequest в фильтре

Я пишу прокси-приложение и хочу, чтобы отображаемый URL-адрес обрабатывался моим контроллером, но другой URL-адрес (включая ошибку) можно перенаправить на другой адрес. Поэтому я использую Filter а не HandlerInterceptorAdapter который не может быть вызван, если resourece не найден, потому что к нему обращается определенный «обработчик пути восстановления».

ожидание

http://localhost:8090/upload.html > Filter > http://localhost:8092/upload.html
http://localhost:8090/files/upload > Controller > http://localhost:8092/files/upload

Не

http://localhost:8090/upload.html > Filter > http://localhost:8092/upload.html
http://localhost:8090/files/upload > Controller > http://localhost:8092/files/upload

Или

http://localhost:8090/upload.html > Interceptor > http://localhost:8090/error Не найден http://localhost:8090/files/upload > Filter > http://localhost:8092/files/upload

демонстрация

Я настроил Filter в моем подклассе WebMvcConfigurerAdapter .

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Bean private javax.servlet.Filter proxyFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { System.out.println("[doFilterInternal]isCommitted=" + response.isCommitted() + ", URI = " + request.getRequestURI()); // if(!isRequestMappedInController(request, "my.pakcage")) httpProxyForward(request, response); } }; } // @Bean // private FilterRegistrationBean loggingFilterRegistration() { // FilterRegistrationBean registration = new FilterRegistrationBean(proxyFilter()); // registration.addUrlPatterns("/**"); // return registration; // } Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptorAdapter() { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // How I determine a controller has handled the request in my interceptor? if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = ((HandlerMethod) handler); if (handlerMethod.getMethod().getDeclaringClass().getName().startsWith("nxtcasb.casbproxy")) { System.out.println("[preHandle]dealt: request uri = " + request.getRequestURI() + ", HandlerMethod = " + ((HandlerMethod) handler).getMethod()); return true; } else { System.out.println("[preHandle]isCommitted=" + response.isCommitted() + ", HandlerMethod = " + ((HandlerMethod) handler).getMethod()); } } // act as an api-gateway System.out.println("[preHandle]undealt: request uri = " + request.getRequestURI() + ", handler = " + handler); //ModelAndView modelView = new ModelAndView("redirect: http://www.bing.com"); //throw new ModelAndViewDefiningException(modelView); httpProxyForward(request, response); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (handler instanceof HandlerMethod) { System.out.println("[postHandle]dealt: uri = " + request.getRequestURI() + ", handler = " + ((HandlerMethod) handler).getMethod()); } else { System.out.println("[postHandle]undealt uri = " + request.getRequestURI() + ", handler = " + handler); } } }).addPathPatterns("/**", "/error"); } /** * this is the same as <mvc:default-servlet-handler/> <!-- This tag allows for mapping the DispatcherServlet to "/" --> * * @param configurer */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //registry.addResourceHandler("/**").addResourceLocations("classpath:/public"); } protected void httpProxyForward(HttpServletRequest request, HttpServletResponse response) { HttpClient httpClient = CreateHttpClient(); HttpUriRequest targetRequest = null; HttpResponse targetResponse = null; try { targetRequest = createHttpUriRequest(request); targetResponse = httpClient.execute(targetRequest); } catch (IOException e) { e.printStackTrace(); } finally { // make sure the entire entity was consumed, so the connection is released if (targetResponse != null) { EntityUtils.consumeQuietly(targetResponse.getEntity()); // @since 4.2 //Note: Don't need to close servlet outputStream: // http://stackoverflow.com/questions/1159168/should-one-call-close-on-httpservletresponse-getoutputstream-getwriter } } } } 

Файл api url /files/upload :

 @RestController @RequestMapping(value = "/files") public class FileUploadProxyController { private static final Logger logger = LoggerFactory.getLogger(FileUploadProxyController.class); @RequestMapping(value = "/upload", method = RequestMethod.POST) public ResponseEntity upload(HttpServletResponse response, HttpServletRequest request) { try { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; Iterator<String> it = multipartRequest.getFileNames(); MultipartFile multipart = multipartRequest.getFile(it.next()); String fileName = multipart.getOriginalFilename(); File dir = new File("files", "proxy-uploaded"); dir.mkdirs(); logger.debug("current dir = {}, uploaded dir = {}", System.getProperty("user.dir"), dir.getAbsolutePath()); File file = new File(dir, fileName); Files.copy(multipart.getInputStream(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); //FileCopyUtils.copy(multipart.getInputStream()) // byte[] bytes = multipart.getBytes(); // BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream("upload" + fileName)); // stream.write(bytes); // stream.close(); RestTemplate restTemplate = new RestTemplate(); SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); //// if Spring version < 3.1, see https://jira.springsource.org/browse/SPR-7909 // requestFactory.setBufferRequestBody(false); restTemplate.setRequestFactory(requestFactory); String url = "http://localhost:8092/files/upload"; // [resttemplate multipart post](https://jira.spring.io/browse/SPR-13571) // [Spring RestTemplate - how to enable full debugging/logging of requests/responses?](https://stackoverflow.com/questions/7952154/spring-resttemplate-how-to-enable-full-debugging-logging-of-requests-responses?rq=1) MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("file", new FileSystemResource(file)); param.add("param1", fileName); param.add("param2", "Leo"); HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String,Object>>(param); ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class); //String string = restTemplate.postForObject(url, param, String.class); //ResponseEntity e = restTemplate.exchange(url, HttpMethod.POST, // new HttpEntity<Resource>(new FileSystemResource(file)), String.class); return responseEntity; } catch (Exception e) { e.printStackTrace(); return new ResponseEntity("Upload failed", HttpStatus.BAD_REQUEST); } } @RequestMapping("/hello") public String hello() { return "hello word"; } } 

Afer чтение Spring mvc autowire RequestMappingHandlerMapping или Получить контроллер назначения из HttpServletRequest

Следующий код работает:

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { // https://stackoverflow.com/questions/129207/getting-spring-application-context @Autowired private org.springframework.context.ApplicationContext appContext; private static final String MY_CONTROLLER_PACKAGE_NAME = "nxtcasb.casbproxy"; @Bean protected javax.servlet.Filter proxyFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HandlerMethod handlerMethod = null; try { RequestMappingHandlerMapping req2HandlerMapping = (RequestMappingHandlerMapping) appContext.getBean("requestMappingHandlerMapping"); // Map<RequestMappingInfo, HandlerMethod> handlerMethods = req2HandlerMapping.getHandlerMethods(); HandlerExecutionChain handlerExeChain = req2HandlerMapping.getHandler(request); if (Objects.nonNull(handlerExeChain)) { handlerMethod = (HandlerMethod) handlerExeChain.getHandler(); if (handlerMethod.getBeanType().getName().startsWith(MY_CONTROLLER_PACKAGE_NAME)) { filterChain.doFilter(request, response); return; } } } catch (Exception e) { logger.warn("Lookup the handler method", e); } finally { logger.debug("URI = " + request.getRequestURI() + ", handlerMethod = " + handlerMethod); } httpProxyForward(request, response); } }; } // @Bean // private FilterRegistrationBean loggingFilterRegistration() { // FilterRegistrationBean registration = new FilterRegistrationBean(proxyFilter()); // registration.addUrlPatterns("/**"); // return registration; // } /** * this is the same as <mvc:default-servlet-handler/> <!-- This tag allows for mapping the DispatcherServlet to "/" --> * * @param configurer */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //registry.addResourceHandler("/**").addResourceLocations("classpath:/public"); } protected void httpProxyForward(HttpServletRequest request, HttpServletResponse response) { HttpClient httpClient = CreateHttpClient(); HttpUriRequest targetRequest = null; HttpResponse targetResponse = null; try { targetRequest = createHttpUriRequest(request); targetResponse = httpClient.execute(targetRequest); } catch (IOException e) { e.printStackTrace(); } finally { // make sure the entire entity was consumed, so the connection is released if (targetResponse != null) { EntityUtils.consumeQuietly(targetResponse.getEntity()); // @since 4.2 //Note: Don't need to close servlet outputStream: // http://stackoverflow.com/questions/1159168/should-one-call-close-on-httpservletresponse-getoutputstream-getwriter } } } }