with mvc another java spring-mvc spring-boot resttemplate

java - another - spring mvc redirect with parameters



Spring mvc rest service redirigir/reenviar/proxy (4)

Construí una aplicación web usando spring mvc framework para publicar servicios REST. Por ejemplo:

@Controller @RequestMapping("/movie") public class MovieController { @RequestMapping(value = "/{id}", method = RequestMethod.GET) public @ResponseBody Movie getMovie(@PathVariable String id, @RequestBody user) { return dataProvider.getMovieById(user,id); }

Ahora necesito implementar mi aplicación, pero tengo el siguiente problema: los clientes no tienen acceso directo a la computadora en la que reside la aplicación (hay un firewall). Por lo tanto, necesito una capa de redirección en una máquina proxy (accesible por los clientes) que llama al servicio de descanso real.

Intenté hacer una nueva llamada usando RestTemplate: Por ejemplo:

@Controller @RequestMapping("/movieProxy") public class MovieProxyController { private String address= "http://xxx.xxx.xxx.xxx:xx/MyApp"; @RequestMapping(value = "/{id}", method = RequestMethod.GET) public @ResponseBody Movie getMovie(@PathVariable String id,@RequestBody user,final HttpServletResponse response,final HttpServletRequest request) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); return restTemplate.exchange( address+ request.getPathInfo(), request.getMethod(), new HttpEntity<T>(user, headers), Movie.class); }

Esto está bien, pero necesito reescribir cada método en el controlador para usar el resto de la plantilla. Además, esto causa una serialización / deserialización redundante en la máquina proxy.

Intenté escribir una función genérica utilizando restemplate, pero no funcionó:

@Controller @RequestMapping("/movieProxy") public class MovieProxyController { private String address= "http://xxx.xxx.xxx.xxx:xx/MyApp"; @RequestMapping(value = "/**") public ? redirect(final HttpServletResponse response,final HttpServletRequest request) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); return restTemplate.exchange( address+ request.getPathInfo(), request.getMethod(), ? , ?); }

No pude encontrar un método de resttemplate que funcione con los objetos de solicitud y respuesta.

También intenté redirigir y reenviar la primavera. Pero el redireccionamiento no cambia la dirección IP del cliente de la solicitud, por lo que creo que es inútil en este caso. No pude reenviar a otra URL tampoco.

¿Hay una manera más apropiada de lograr esto? Gracias por adelantado.


Aquí está mi versión modificada de la respuesta original, que difiere en tres puntos:

  1. No hace que el cuerpo de la solicitud sea obligatorio, y como tal no permite que las solicitudes GET fallen.
  2. Copia todos los encabezados presentes en la solicitud original. Si está utilizando otro proxy / servidor web, esto puede causar problemas debido a la compresión del contenido / gzip. Limite los encabezados a los que realmente necesita.
  3. No vuelve a codificar los parámetros de consulta o la ruta. Esperamos que estén codificados de todos modos. Tenga en cuenta que otras partes de su URL también pueden estar codificadas. Si ese es el caso para usted, aproveche todo el potencial de UriComponentsBuilder .

@RequestMapping("/**") public ResponseEntity mirrorRest(@RequestBody(required = false) String body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) throws URISyntaxException { String requestUrl = request.getRequestURI(); URI uri = new URI("http", null, server, port, null, null, null); uri = UriComponentsBuilder.fromUri(uri).path(requestUrl) .query(request.getQueryString()).build(true).toUri(); HttpHeaders headers = new HttpHeaders(); Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); headers.set(headerName, request.getHeader(headerName)); } HttpEntity<String> httpEntity = new HttpEntity<>(body, headers); RestTemplate restTemplate = new RestTemplate(); return restTemplate.exchange(uri, method, httpEntity, String.class); }


Puede reflejar / proxy todas las solicitudes con esto:

private String server = "localhost"; private int port = 8080; @RequestMapping("/**") @ResponseBody public String mirrorRest(@RequestBody String body, HttpMethod method, HttpServletRequest request) throws URISyntaxException { URI uri = new URI("http", null, server, port, request.getRequestURI(), request.getQueryString(), null); ResponseEntity<String> responseEntity = restTemplate.exchange(uri, method, new HttpEntity<String>(body), String.class); return responseEntity.getBody(); }

Esto no reflejará ningún encabezado.


Puede usar Netflix Zuul para enrutar las solicitudes que llegan a una aplicación de primavera a otra aplicación de primavera.

Digamos que tiene dos aplicaciones: 1.songs-app, 2.api-gateway

En la aplicación api-gateway, primero agregue la dependencia de zuul, luego puede simplemente definir su regla de enrutamiento en application.yml de la siguiente manera:

pom.xml

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> <version>LATEST</version> </dependency>

application.yml

server: port: 8080 zuul: routes: foos: path: /api/songs/** url: http://localhost:8081/songs/

y finalmente ejecutar la aplicación api-gateway como:

@EnableZuulProxy @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

Ahora, la puerta de enlace enrutará todas las /api/songs/ requests a http://localhost:8081/songs/ .

Un ejemplo de trabajo está aquí: https://github.com/muatik/spring-playground/tree/master/spring-api-gateway

Otro recurso: http://www.baeldung.com/spring-rest-with-zuul-proxy