Все еще используете HttpUtil? Новый HTTP-клиент SpringBoot 3 уже здесь, и он достаточно элегантен в использовании!
Все еще используете HttpUtil? Новый HTTP-клиент SpringBoot 3 уже здесь, и он достаточно элегантен в использовании!

Когда мы обычно разрабатываем проекты,Часто необходимо удаленно вызвать интерфейс, предоставленный другими Служить,Поэтому мы будем использовать некоторые классы HTTP-инструментов, такие как HttpUtil, предоставляемые Hutool. SpringBoot 3.0Из одногоHttp Interfaceновые возможности,Это позволяет нам вызывать удаленный интерфейс способом декларативных вызовов.,Сегодня мы поговорим о его использовании!

Введение

Http Interfaceпозволяет вам определить что-то вродеJavaинтерфейсопределил такHTTPСлужить,И использование точно такое же, как вы обычно пишете Controller. Он автоматически сгенерирует классы реализации прокси для этих HTTP.,Нижний уровень реализован на основе WebClient Webflux.

Использовать Декларативный вызов Служить действительно достаточно элегантен.,Вот абзациспользоватьHttp InterfaceзаявилHttpСлужитькод。

использовать

В SpringBoot 3.0серединаиспользоватьHttp Interfaceэто очень просто,Давайте испытаем это ниже.

Зависит от интеграции

  • Прежде всего в проектеpom.xmlсерединачетко определенныйSpringBootВерсия3.0.0
Язык кода:javascript
копировать
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
  • потому чтоSpringBootМинимальное требованиеJava 17,Сначала нам нужно установить JDK 17,После завершения установки настройте проектSDKВерсияJava 17,Адрес загрузки JDK: https://www.oracle.com/cn/java/technologies/downloads/
  • потому чтоHttp Interfaceнужно зависеть отwebfluxосознать,Нам также необходимо добавить его зависимости.
Язык кода:javascript
копировать
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

Это может быть полезный для вас проект с открытым исходным кодом.,Проект торгового центра представляет собой комплекс SpringBoot + Vue + uni-app выполнитьиз Система электронной коммерции(Звезда Github 60 тыс.),Развертывание с использованием Docker-контейнеров,Бэкэнд поддерживает многомодульную и микро-архитектуру. Включая внешний проект торгового центра и внутреннюю систему управления.,Может поддерживать полную Заказпроцесс!Охватываемая продукция、Заказ、корзина、Разрешения、Купон、член、Оплата и другие функции!

  • Bootпроект:https://github.com/macrozheng/mall
  • Cloudпроект:https://github.com/macrozheng/mall-swarm
  • Видеоурок:https://www.macrozheng.com/video/

Демонстрация проекта:

Базовыйиспользовать

Для звонка нижеmall-tiny-swaggerсерединаизинтерфейс Например,Давайте испытаем этоHttp Interfaceиз Базовыйиспользовать。

  • Сначала мы готовим Служить для облегчения удаленных звонков.,использоватьпредыдущегоmall-tiny-swaggerэтотDemo,Откройте Swagger и посмотрите.,Существует интерфейс входа в систему и интерфейс CRUD торговой марки, требующий аутентификации при входе.,Адрес проекта: https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-swagger
  • первыйapplication.ymlсередина Настроенmall-tiny-swaggerиз Служитьадрес;
Язык кода:javascript
копировать
remote:
  baseUrl: http://localhost:8088/
  • пройти еще раз@HttpExchangeобъявитьHttpСлужить,использовать@PostExchangeАннотация указывает на прогрессPOSTпросить;
Язык кода:javascript
копировать
/**
 * Определить Httpинтерфейс, используемый для удаленного вызова UmsAdminСлужить
 * Created by macro on 2022/1/19.
 */
@HttpExchange
public interface UmsAdminApi {

    @PostExchange("admin/login")
    CommonResult<LoginInfo> login(@RequestParam("username") String username, @RequestParam("password") String password);
}
  • Создайте бренд удаленного вызова. Служить интерфейс, аннотации параметров использовать — это те, которые мы обычно используем при написании методов контроллера;
Язык кода:javascript
копировать
/**
 * Определить Httpинтерфейс, используемый для удаленного вызова PmsBrandСлужить
 * Created by macro on 2022/1/19.
 */
@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);
}
  • Для облегчения последующих вызовов требуется аутентификация при входе.,я создалTokenHolderэтотдобрый,Сохраните токен в сеансе;
Язык кода:javascript
копировать
/**
 * Хранение токена входа (в сеансе)
 * Created by macro on 2022/1/19.
 */
@Component
public class TokenHolder {
    /**
     * добавить токен
     */
    public void putToken(String token) {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        request.getSession().setAttribute("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;
    }

}
  • Создать конфигурацию Java,Просто настройте объекты клиентWebClient и HttpСлужить, используемые для запросов.,Так как бренду Служить необходимо добавить заголовок аутентификации для нормального доступа.,Поэтому фильтры добавляются равномерно;
Язык кода:javascript
копировать
@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);
    }
}
  • Затем внедрите объект HttpСлужить в контроллер и вызовите его;
Язык кода:javascript
копировать
/**
 * HttpInterfaceтестинтерфейс
 * 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 = "pageSize", defaultValue = "3")
                                                        @ApiParam("Количество на странице") Integer pageSize) {
        return pmsBrandApi.list(pageNum, pageSize);
    }

    @ApiOperation("Вызовите удаленный интерфейс, чтобы получить информацию о бренде с указанным идентификатором")
    @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);
    }
}

тест

  • Далее мы используем Postman для выполнения теста. Сначала мы вызываем интерфейс входа в систему, чтобы получить токен, возвращаемый удаленным Служить;
  • Затем вызовите список брендов, требующих аутентификации при входе, и обнаружите, что вы можете получить к нему обычный доступ.

Подвести итог

Http InterfaceДавайте просто определиминтерфейс,Выполнять удаленные вызовы HTTP без определения реализаций методов.,Действительно очень удобно! Но его реализация опирается на WebClient Webflux.,Это вызовет некоторые проблемы, если мы будем использовать SpringMVC.,Было бы лучше, если бы вы могли быть независимыми!

Ссылки

Официальная документация: https://docs.spring.io/spring-framework/reference/integration/rest-clients.html.

Адрес исходного кода проекта

https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-http-interface

boy illustration
Описание трех режимов жизненного цикла службы внедрения зависимостей Asp.net Core.
boy illustration
Java реализует пользовательские аннотации для доступа к интерфейсу без проверки токена.
boy illustration
Серверная часть Unity добавляет поддержку .net 8. Я еще думал об этом два дня назад, и это сбылось.
boy illustration
Проект с открытым исходным кодом | Самый элегантный метод подписки на публичные аккаунты WeChat на данный момент
boy illustration
Разрешения роли пользователя Gitlab Гость, Репортер, Разработчик, Мастер, Владелец
boy illustration
Spring Security 6.x подробно объясняет механизм управления аутентификацией сеанса в этой статье.
boy illustration
[Основные знания ASP.NET] — Аутентификация и авторизация — Использование удостоверений для аутентификации.
boy illustration
Соединение JDBC с базой данных MySQL в jsp [легко понять]
boy illustration
[Уровень няни] Полный процесс развертывания проекта Python (веб-страницы Flask) в Docker.
boy illustration
6 способов чтения файлов свойств, рекомендуем собрать!
boy illustration
Графическое объяснение этапа строительства проекта IDEA 2021 Spring Cloud (базовая версия)
boy illustration
Подробное объяснение технологии междоменного запроса данных JSONP.
boy illustration
Учебное пособие по SpringBoot (14) | SpringBoot интегрирует Redis (наиболее полный во всей сети)
boy illustration
Подробное объяснение механизма подтверждения выпуска сообщений RabbitMQ.
boy illustration
На этот раз полностью поймите протокол ZooKeeper.
boy illustration
Реализуйте загрузку файлов с использованием минимального WEB API.
boy illustration
Демо1 Laravel5.2 — генерация и хранение URL-адресов
boy illustration
Spring boot интегрирует Kafka и реализует отправку и потребление информации (действительно при личном тестировании)
boy illustration
Мысли о решениях по внутренней реализации сортировки методом перетаскивания
boy illustration
Междоменный доступ к конфигурации nginx не может вступить в силу. Междоменный доступ к странице_Page
boy illustration
Как написать текстовый контент на php
boy illustration
PHP добавляет текстовый водяной знак или водяной знак изображения к изображениям – метод инкапсуляции
boy illustration
Интерпретация быстрой таблицы (TLB)
boy illustration
Интерфейс WeChat API (полный) — оплата WeChat/красный конверт WeChat/купон WeChat/магазин WeChat/JSAPI
boy illustration
Преобразование Java-объекта в json string_complex json-строки в объект
boy illustration
Примените сегментацию слов jieba (версия Java) и предоставьте пакет jar
boy illustration
matinal: Самый подробный анализ управления разрешениями во всей сети SAP. Все управление разрешениями находится здесь.
boy illustration
Коротко расскажу обо всем процессе работы алгоритма сборки мусора G1 --- Теоретическая часть -- Часть 1
boy illustration
[Спецификация] Результаты и исключения возврата интерфейса SpringBoot обрабатываются единообразно, поэтому инкапсуляция является элегантной.
boy illustration
Интерпретация каталога веб-проекта Flask