# 아직도 HttpUtil ? SpringBoot 3.0의 HTTP Client Util 을 사용해보라

```markup
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
```

springboot 3.0 부터는 JDK 17를 기본으로 하고 있다. 꼭 JDK 17로 업그레이드 되었는지 확인 보라!

<figure><img src="/files/R9Dn6j5mW8cxYiI8RLrz" alt=""><figcaption></figcaption></figure>

그리고 http interface 는 webflux (비동기) 로 구현된것이므로 pom.xml 에 webflux도 추가해주자!

```markup
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
```

application.yml

```yaml
remote:
  baseUrl: http://localhost:8088/
```

interface 만든다.

```java
/**
 * Http interface 정의
 * Created by blake on 2022/01/09.
 */
@HttpExchange
public interface UmsAdminApi {

    @PostExchange("admin/login")
    CommonResult<LoginInfo> login(@RequestParam("username") String username, @RequestParam("password") String password);
}
```

```java
/**
 * Http interface 정의
 * Created by blake on 2022/01/09.
 */
@HttpExchange
public interface PmsBrandApi {
    @GetExchange("brand/list")
    CommonResult<CommonPage<PmsBrand>> list(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize);

    @GetExchange("brand/{id}")
    CommonResult<PmsBrand> detail(@PathVariable("id") Long id);

    @PostExchange("brand/create")
    CommonResult create(@RequestBody PmsBrand pmsBrand);

    @PostExchange("brand/update/{id}")
    CommonResult update(@PathVariable("id") Long id, @RequestBody PmsBrand pmsBrand);

    @GetExchange("brand/delete/{id}")
    CommonResult delete(@PathVariable("id") Long id);
}
```

```java
/**
 * Session 안에 login token 저장
 * Created by blake on 2022/01/09.
 */
@Component
public class TokenHolder {
    /**
     * token 추가
     */
    public void putToken(String token) {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        request.getSession().setAttribute("token", token);
    }

    /**
     * token 획득
     */
    public String getToken() {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        Object token = request.getSession().getAttribute("token");
        if(token!=null){
            return (String) token;
        }
        return null;
    }

}
```

config

```java
/**
 * config 정의
 * Created by blake on 2022/01/09.
 */
@Configuration
public class HttpInterfaceConfig {

    @Value("${remote.baseUrl}")
    private String baseUrl;
    @Autowired
    private TokenHolder tokenHolder;

    @Bean
    WebClient webClient() {
        return WebClient.builder()
                .defaultHeader("source", "http-interface")
                .filter((request, next) -> {
                    ClientRequest filtered = ClientRequest.from(request)
                            .header("Authorization", tokenHolder.getToken())
                            .build();
                    return next.exchange(filtered);
                })
                .baseUrl(baseUrl).build();
    }

    @Bean
    UmsAdminApi umsAdminApi(WebClient client) {
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
        return factory.createClient(UmsAdminApi.class);
    }

    @Bean
    PmsBrandApi pmsBrandApi(WebClient client) {
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
        return factory.createClient(PmsBrandApi.class);
    }
}
```

Controller 에서 Http 객체를 주입받는다. &#x20;

```java
/**
 * HttpInterface 테스트 interface
 * Created by macro on 2022/1/19.
 */
@RestController
@Api(tags = "HttpInterfaceController")
@Tag(name = "HttpInterfaceController", description = "HttpInterface테트스")
@RequestMapping("/remote")
public class HttpInterfaceController {

    @Autowired
    private UmsAdminApi umsAdminApi;
    @Autowired
    private PmsBrandApi pmsBrandApi;
    @Autowired
    private TokenHolder tokenHolder;

    @ApiOperation(value = "토큰획득")
    @PostMapping(value = "/admin/login")
    public CommonResult<LoginInfo> login(@RequestParam String username, @RequestParam String password) {
        CommonResult<LoginInfo> result = umsAdminApi.login(username, password);
        LoginInfo loginInfo = result.getData();
        if (result.getData() != null) {
            tokenHolder.putToken(loginInfo.getTokenHead() + " " + loginInfo.getToken());
        }
        return result;
    }

    @ApiOperation("목록,페이징호출")
    @GetMapping(value = "/brand/list")
    public CommonResult<CommonPage<PmsBrand>> listBrand(@RequestParam(value = "pageNum", defaultValue = "1")
                                                        @ApiParam("페이지번호") Integer pageNum,
                                                        @RequestParam(value = "페이지사이즈", defaultValue = "3")
                                                        @ApiParam("페이지당노출데이터") Integer pageSize) {
        return pmsBrandApi.list(pageNum, pageSize);
    }

    @ApiOperation("브랜드id기준 상세조회")
    @GetMapping(value = "/brand/{id}")
    public CommonResult<PmsBrand> brand(@PathVariable("id") Long id) {
        return pmsBrandApi.detail(id);
    }

    @ApiOperation("브랜드추가")
    @PostMapping(value = "/brand/create")
    public CommonResult createBrand(@RequestBody PmsBrand pmsBrand) {
        return pmsBrandApi.create(pmsBrand);
    }

    @ApiOperation("브랜드수정")
    @PostMapping(value = "/brand/update/{id}")
    public CommonResult updateBrand(@PathVariable("id") Long id, @RequestBody PmsBrand pmsBrand) {
        return pmsBrandApi.update(id,pmsBrand);
    }

    @ApiOperation("브랜드삭제")
    @GetMapping(value = "/delete/{id}")
    public CommonResult deleteBrand(@PathVariable("id") Long id) {
        return  pmsBrandApi.delete(id);
    }
}
```

참고 : <https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blakes-organization.gitbook.io/rainsister/spring/httputil-springboot-3.0-http-client-util.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
