2013-02-06 2 views
34

나는 봄 mvc 프레임 워크를 사용하여 REST 서비스를 게시하는 웹 애플리케이션을 빌드했다. 예를 들어 :스프링 mvc 휴식 서비스 리디렉션/전달/프록시

@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); 

} 
. 
. 
. 

지금 난 내 응용 프로그램을 배포해야하지만 난 다음 문제가 : 클라이언트가 응용 프로그램이 상주 (방화벽이)있는 컴퓨터에 직접 액세스 할 수 없습니다. 따라서 실제 휴식 서비스를 호출하는 프록시 시스템 (클라이언트가 액세스 가능)에서 리디렉션 계층이 필요합니다. 예를 들어 :

나는 RestTemplate을 사용하여 새 통화를 시도

@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); 

} 
. 
. 
. 

이 괜찮습니다하지만 난 resttemplate를 사용하는 컨트롤러에 각각의 방법을 다시 작성해야합니다. 또한 이로 인해 프록시 시스템에서 중복 직렬화/비 직렬화가 발생합니다.

나는 restemplate를 사용하여 일반 함수를 작성했지만, 그것은 작동하지 않았다

@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(), ? , ?); 

} 
. 
. 
. 

내가 요청 및 응답 객체와 함께 작동 resttemplate하는 방법을 찾을 수 없습니다.

스프링 리디렉션 및 전달을 시도했습니다. 하지만 리디렉션은 요청의 클라이언트 IP 주소를 변경하지 않으므로이 경우에는 쓸모가 없다고 생각합니다. 나도 다른 URL로 전달할 수 없습니다.

더 좋은 방법이 있나요? 미리 감사드립니다.

+2

가 왜 이렇게/mod_rewrite를 또는 mod_proxy를 승 아파치 같은 것을 사용하지 수 있을까? 기본적으로 방화벽 외부에 웹 서버 (일반적으로 우리는 이것을 DMZ라고 부름)를 설치하고 FW에 방화벽을 설치하여 서버가 방화벽 뒤에있는 서버와 통신 할 수있게합니다. 이것이 대부분의 회사가이 문제를 해결하는 방법입니다. – CodeChimp

+0

감사합니다. 우리의 경우 솔루션이 작동하는 경우 sys 관리자와상의하려고 노력할 것입니다. 한편 resttemplate을 사용하고 문자열에 json 데이터를 serialize/deserialize합니다. – nilgun

답변

39

당신은 미러링 할 수 있습니다/프록시이 모든 요청 :

private String server = "localhost"; 
private int port = 8080; 

@RequestMapping("/**") 
@ResponseBody 
public String mirrorRest(@RequestBody String body, HttpMethod method, HttpServletRequest request, 
    HttpServletResponse response) 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(); 
} 

이것은 어떤 헤더를 반영하지 않습니다.

+0

나는 너와 같은 대답을 기대하고 있었지만 오랜 시간이 걸렸으므로 더 이상 그 프로젝트에서 작업하지 않습니다. 불행히도 지금은 포괄적 인 테스트를 수행하고 코드를 바로 확인할 수 없습니다. – nilgun

+0

URL과 매개 변수는이 컨트롤러에 어떤 모양이됩니까? 올바른 URL을 호출했지만 "클라이언트가 보낸 요청이 구문 상 올바르지 않습니다"라는 메시지가 나타납니다. – WowBow

+0

내 원래 메소드 서명은 다음과 같습니다 (RequestBody 또는 HttpMethod가 전혀 없습니다) @RequestMapping ("/ getProduct") public CustomMessage getCompanyResults (@RequestParam ("search") 문자열 검색, @RequestParam (value = "id", required = false) String rfgId, @RequestParam (value = "rowBegin", required = false) 문자열) – WowBow

4

Netflix Zuul을 사용하여 스프링 응용 프로그램으로 들어오는 요청을 다른 스프링 응용 프로그램으로 라우팅 할 수 있습니다.

의이 두 응용 프로그램이 있다고 가정 해 봅시다 : 먼저 당신은 단순히 응용 프로그램에서 라우팅 규칙을 정의 할 수 있으며, zuul 실행 종속을 추가, 1.songs - 앱 2.api 게이트웨이는 API 게이트웨이 응용 프로그램에서

합니다. YML는 다음과 같이

의 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/ 

그리고 마지막으로 같은 API 게이트웨이 응용 프로그램 실행 : 이제

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

를, 게이트웨이 경로 http://localhost:8081/songs/에 모든 /api/songs/ 요청 것이다.

동작하는 예제는 여기에 있습니다 : https://github.com/muatik/spring-playground/tree/master/spring-api-gateway

또 다른 자원 : http://www.baeldung.com/spring-rest-with-zuul-proxy