1,4 Вт слов! Позвольте мне познакомить вас с миром springmvc!

Оглавление

1. Предварительное понимание

1. Какая связь между котом и сервлетом?

2. Каким условиям должен соответствовать springmvc для веб-разработки?

2. Что такое SpringMVC

3. Создайте веб-проект на основе SpringMVC

① Создайте проект и выберите зависимости

 ②Настройте горячее развертывание (некоторые изменения кода могут вступить в силу без повторного запуска вручную)

4. Понять процесс разработки, разделяющий интерфейс и серверную часть.

5. SpringMVC реализует веб-разработку

1. Подробно объясните ответ, полученный от клиента.

@контроллер

@ResponseBody

перенаправление и переадресация

Вперед

перенаправить

Разница между переадресацией и перенаправлением: (M)

настраиваемый тип возврата

@RestController

@RequestMapping

 2. Подробно объясните, как сервер получает запрос клиента

2.1 О параметрах в пути запроса и заголовке запроса

@Pathvirable

Используйте postman для анализа результатов теста:

@RequestHeader

@CookieValue

@SessionAttribute

2.2 О параметрах запроса

Неаннотированные параметры запроса

@RequestParam

@RequestPart

@RequestBody

Задайте программные схемы конфигурации через классы конфигурации

Установите унифицированный префикс внутреннего пути

Установить перехватчик

Унифицированная обработка исключений

Единая обработка результатов:

О роли responseBodyAdvice


1. Предварительное понимание

Прежде чем мы действительно поговорим о springmvc, давайте проясним следующие два вопроса:

1. Какая связь между котом и сервлетом?

Все мы знаем, что сервлет — это технология для реализации динамических страниц, сервлет — это спецификация для веб-разработки, а tomcat — это контейнер сервлетов, который предоставляет веб-сервер и номер порта на основе соответствия спецификации сервлета и реализует унифицированное управление. сервлета; в то же время он может получить запрос пользователя, отправить запрос сервлету и отправить ответ клиенту после того, как сервлет даст ответ

2. Каким условиям должен соответствовать springmvc для веб-разработки?

Из приведенного выше обсуждения мы можем ясно понять, что tomcat соответствует спецификации сервлета и разрабатывает сеть на этой основе.Если Springmvc хочет реализовать веб-разработку, он также должен соответствовать спецификации сервлета.

2. Что такое SpringMVC

SpringMVC — это фреймворк для веб-разработки. Он также опирается на фреймворк springboot (springboot включает springmvc). Благодаря тому принципу, что соглашение больше, чем конфигурация в фреймворке springboot, путь к файлу springmvc настраивается по умолчанию в springboot, и многие настройки по умолчанию сделаны для конфигурации springmvc (нет необходимости в ручной настройке пользователем), springmvc имеет встроенный веб-сервер (эквивалент настроенного сервера), который соответствует спецификации сервлета (дальнейшая инкапсуляция сервлета), и если мы хотим использовать springmvc только для веб-разработки. Он должен соответствовать спецификации использования springmvc.

Цель использования springmvc для веб-разработки также очень ясна: сделать веб-разработку более удобной и повысить эффективность веб-разработки.

3. Создайте веб-проект на основе SpringMVC

① Создайте проект и выберите зависимости

 ②Настройте горячее развертывание (некоторые изменения кода могут вступить в силу без повторного запуска вручную)

 

③ Отключите JMX: Потому что, если это не исключено, при запуске проекта будет сообщено об ошибке.Хотя эта ошибка не влияет на реализацию нашего проекта, ради стандартизации мы все же добавляем

 ④ Отключите tomcat и замените его на undertow (не обязательная опция, потому что undertow немного более эффективен, чем tomcat)

⑤ Изменить набор кодов

4. Понять процесс разработки, разделяющий интерфейс и серверную часть.

MVC SpringMVC состоит из следующих трех частей: ①Model (модель)②View (представление) ③Controller (контроллер) 

Мы объединяем процесс веб-запроса и ответа, чтобы понять процесс разработки и три компонента springmc:

Пользователь отправляет HTTP-запрос, анализирует информацию запроса через уровень контроллера в сочетании со слоем модели и дает ответ, возвращает данные ответа на уровень представления и, наконец, дает HTTP-ответ через уровень представления.

В сочетании с конкретным методом выпуска для анализа:

На самом деле профессиональная логика должна быть такой:
 

Поток обработки
Поток обработки DispatcherServlet можно разделить на следующие этапы:

Получение клиентских запросов
        Когда клиент отправляет запрос, DispatcherServlet получает и обрабатывает запрос. Способ получения запросов зависит от конфигурации DispatcherServlet.Обычно он сопоставляет запрос с URL-адресом, а затем прослушивает запрос URL-адреса.

Создание объекта запроса
        DispatcherServlet создаст объект запроса в соответствии с запросом клиента, который содержит всю информацию, запрошенную клиентом, такую ​​как метод запроса, заголовок запроса, параметры запроса и т. д.

Сопоставление запроса на обработку
DispatcherServlet сопоставит запрос с соответствующим контроллером для обработки. Сопоставление запросов выполняется с помощью HandlerMapping, который отвечает за сопоставление запросов с одним или несколькими контроллерами, чтобы для обработки можно было выбрать наиболее подходящий контроллер.

Вызов контроллера
        DispatcherServlet вызовет соответствующий контроллер для обработки, и контроллер выполнит соответствующую обработку в соответствии с параметрами запроса и бизнес-логикой и вернет объект ModelAndView.

Визуализация представления
        DispatcherServlet передаст объект ModelAndView преобразователю представления (ViewResolver), а преобразователь представления разрешит соответствующий объект представления в соответствии с именем представления в ModelAndView. Затем DispatcherServlet передает данные модели в объект представления, чтобы визуализировать представление. Наконец, объект представления сгенерирует соответствующий результат ответа и вернет его клиенту.

 

5. SpringMVC реализует веб-разработку

1. Подробно объясните ответ, полученный от клиента.

@контроллер

@controller указывает, что класс, измененный этой аннотацией, является компонентом (обычно используется только для изменения класса), и этот компонент отвечает за обработку веб-запросов и ответов.

@ResponseBody

@ResponseBody указывает тело ответа, в котором указывается тип возвращаемого значения (его можно использовать для модификации как классов, так и методов. Модифицированный класс означает, что все методы задают тип возвращаемого значения, а модифицированный метод означает, что только этот метод указывает тип возвращаемого значения), @ResponseBody оговаривает, что возвращаемое значение модифицированного им метода возвращается в определенном формате данных, а форма возврата по умолчанию — json

перенаправление и переадресация

Если @ResponseBody не используется для указания формата типа возвращаемого значения, тип возвращаемого значения по умолчанию — String и представляет собой путь : этот путь обычно делится на два сценария приложения: пересылка и перенаправление.

Вперед

Формат синтаксиса: вперед:/+путь

Функции просмотра пакетов Capture:

①Ресурс только с одним запросом и ответом на него является html-страницей.

 

перенаправить

Формат грамматики: "перенаправить:/+путь"

Функции просмотра пакетов Capture:

Первый запрос: 

 Первый ответ:

Второй запрос:

Второй ответ:

Разница между переадресацией и перенаправлением: (M)

1. Дважды перенаправить доступ к серверу, один раз перенаправить доступ к серверу.

2. URL-адрес переадресованной страницы не изменится, но адрес перенаправления изменится

3. Переадресация может быть переадресована только вашему собственному веб-приложению, а перенаправление может быть переопределено на любой путь к ресурсу.

4. Переадресация эквивалентна переходу на сервер, который эквивалентен вызову метода.Во время выполнения текущего файла он обращается к выполнению целевого файла.Два файла (текущий файл и целевой файл) принадлежат одному и тому же запросу, а Передняя и задняя страницы имеют общий запрос. Вы можете использовать это, чтобы передать некоторые данные или информацию о сеансе, request.setAttribute() и request.getAttribute(). Перенаправление сгенерирует новый запрос, и информация о домене запроса и параметры запроса не могут быть переданы

5. Поскольку переадресация эквивалентна внутреннему вызову метода сервера, код переадресации все равно будет выполняться (не забудьте вернуть после переадресации), после выполнения кода перенаправления операция перенаправления выполняется после выполнения метода завершен, то есть доступ ко второму запросу, если это последняя строка метода для перенаправления, то он будет перенаправлен сразу (перенаправление также требует возврата).
 

настраиваемый тип возврата

Помимо использования @ResponseBody для установки типа возвращаемого значения и выполнения переадресации и перенаправления, вы также можете реализовать собственный тип возвращаемого значения следующим образом:

Давайте рассмотрим пример для иллюстрации: мы передаем объект .doc клиенту (загрузка сетевого ресурса)

1. Создайте объект пути к файлу

2. Прочитайте массив байтов в пути

3. Установите настраиваемый возвращаемый объект

@Controller
public class SelfController {
    @GetMapping("/object1")
    public ResponseEntity test() throws IOException {
        //创建返回值
        //传输字节码文件
        Path p=new File("D:\\大物实验报告\\42109211014_20221018142451.doc").toPath();
        byte[]bytes= Files.readAllBytes(p);
      return   ResponseEntity.ok().header("content-type", "application/msword").body(bytes);
    }
}

Мы используем путь для доступа

@RestController

На данный момент мы можем просто понять его функцию как: комбинированную аннотацию @Controller и @Responsebody

Как использовать: перед загрузкой класса

@RequestMapping

@RequestMapping представляет путь запроса. Эта аннотация может быть добавлена ​​как к классу, так и к методу. Если эта аннотация добавляется и к классу, и к методу, путь запроса выражается как: путь к классу + путь к методу

Инструкции:

Некоторые атрибуты:

●значение: определяет адрес сопоставления запроса запроса

●метод: определите метод адреса запроса, включая [GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.] По умолчанию запрос на получение принимается. Если метод запроса отличается от определенного метода, запрос не будет успешным.

●params: определите значения параметров, которые должны быть включены в запрос запроса.

 2. Подробно объясните, как сервер получает запрос клиента

2.1 О параметрах в пути запроса и заголовке запроса

@Pathvirable

Использование: используется для изменения формальных параметров.

Функция @Pathvirable: идентифицируйте динамические параметры в пути запроса (прочитайте переменную с тем же именем, что и переменная параметра метода, измененная @Pathvirable, из пути запроса, используя @RequestMapping, и прочитайте ее в переменную формального параметра с тем же именем переменной). в середине метода.)

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

@RestController
public class PathTest {
    @RequestMapping("/test/{id}")
    public Object test(@PathVariable Long id){
        //创建容器
        HashMap<String, Long> stringLongHashMap = new HashMap<>();
        stringLongHashMap.put("id", id);
        return  stringLongHashMap;
    }

Используйте postman для анализа результатов теста:

 Тип переменной, измененный @pathvirable, может проверить переменную из пути запроса. Если параметр в пути запроса не соответствует типу параметра, будет сообщено об ошибке 400.

@RequestHeader

Функция: получить информацию о поле заголовка запроса, привязав имя поля в заголовке запроса.

Пример использования:

   @RequestMapping("/header")
    public Object getHeader(@RequestHeader("user-agent") String headers){
        HashMap<String, String> stringLongHashMap = new HashMap<>();
        stringLongHashMap.put("user-agent", headers);
        return  stringLongHashMap;
    }

@CookieValue

Функция: получить информацию в файле cookie, привязав имя ключа в файле cookie.

Как использовать:

    @RequestMapping("/cookie")
    public Object getCookie(@CookieValue("JSESSIONID") String cookie){
        HashMap<String, String> stringLongHashMap = new HashMap<>();
        stringLongHashMap.put("my-cookie", cookie);
        return  stringLongHashMap;

@SessionAttribute

Прежде чем объяснять это, давайте кратко поговорим о взаимосвязи между файлом cookie и сеансом: сеанс хранится на стороне сервера, и сервер использует его для сохранения информации о пользователе.Мы можем понимать сеанс как пару ключ-значение, а ключ — это случайный сгенерированный sessionId. Значение представляет собой объект сеанса текущего пользователя; файл cookie сохраняется на клиенте, который также используется для сохранения информации о пользователе. При проверке информации о пользователе сопоставьте соответствующий объект сеанса на сервере в соответствии с sessionId для идентификации проверка

@SessionAttribute используется для получения информации о сеансе в параметре запроса (получите объект сеанса на сервере в соответствии с идентификатором сеанса, а затем проверьте информацию о пользователе).

Пример использования:
 

 @RequestMapping("/login")
    public Object info(HttpServletRequest request){
        //通过session存储session信息
        HttpSession session = request.getSession(true);
        //存储session信息
        session.setAttribute("user", "zhangsan");
        //创建容器并返回
        HashMap<String, String> map = new HashMap<>();
        map.put("user", "zhangsan");
        return map;
    }
    @RequestMapping("/check")
    public Object checkLogin(@SessionAttribute("user") String name){
        HashMap<String, String> map = new HashMap<>();
        map.put("user", name);
        return map;
    }

Как правило, общий процесс проверки входа выглядит следующим образом:

При первом входе в систему проверьте, существует ли объект сеанса (если он не существует, создайте новый объект сеанса), затем сохраните его в соответствии с информацией о пользователе из внешнего интерфейса, верните ответ и затем выполните другие операции. (должно быть основано на логине пользователя) Вам необходимо получить объект сеанса с сервера в соответствии с идентификатором сеанса для проверки

Анализ результатов:

2.2 О параметрах запроса

Неаннотированные параметры запроса

 Параметры внешнего интерфейса обычно делятся на четыре формата данных для передачи: строка запроса, данные типа формы, данные формата json и данные типа данных формы, а также объект java, который наш сервер получает запрос, мы делим его на простой типы данных (базовые типы данных + классы-оболочки + String) и сложные типы данных (каркас коллекции и пользовательские типы), мы проанализируем эти два типа данных ниже; сначала дадим вывод: является ли это простым типом данных
. сложный тип данных. В отсутствие аннотаций, только строка запроса может быть проанализирована на задней панели. Данные типа формы, данные формата json, данные типа json должны использовать аннотации ( @RequestBody ), мы рисуем Таблица объясняет это :

Мы анализируем эти внешние типы данных отдельно:
 

@RequestParam

@RequestParam (может изменять другие типы, кроме json, а также может изменять коллекции, такие как карта и список)

Параметры: vlaue/name: имя, используемое для идентификации параметра запроса (имя параметра запроса в пути запроса), этот параметр также не может быть передан, если параметры в методе и параметры пути запроса полностью последовательный

required: Должен ли этот параметр быть указан в параметре запроса: FALSE означает, что он не требуется, а TRUE означает, что он должен быть предоставлен.

Если тип параметра не совпадает или требуемый параметр не указан, будет выдано сообщение об ошибке 400.

Роль: Преобразование параметров запроса в формальные параметры методов контроллера.

Пример использования:
 

@RequestMapping("/requestB")
    public Object res(@RequestParam String name ,@RequestParam() Integer id){
        HashMap<String, String> map = new HashMap<>();
        map.put("name", name);
        map.put("id", id+"");
        return map;
    }

@RequestPart

@RequestPart обычно используется для multipart/form-dataсопоставления данных типа с параметрами методов обработки контроллера.

Аннотационный анализ

  ① значение:

    Имя параметра привязки, значение параметра имеет тип String.

  ② имя:

    Имя параметра привязки, значение параметра имеет тип String. имя и значение можно использовать одновременно, но значения этих двух должны быть согласованы, иначе произойдет ошибка. (400)
  ③ требуется:

    Если указанное значение должно быть включено в заголовок запроса, значение по умолчанию равно true.

    Когда required имеет значение true, будет выдано исключение, если указанное значение отсутствует в заголовке запроса.

    Когда required имеет значение false, будет возвращено значение null, если указанное значение отсутствует в заголовке запроса.

Вариант использования:

    @RequestMapping("/upload")
    //上传文件
    public Object upload(@RequestPart MultipartFile head, User user) throws IOException {
       head.transferTo(new File("D:/上传的"+head.getOriginalFilename()));
        HashMap<String, Object> map = new HashMap<>();
        map.put("file", head);
        return map;

    }

Возможные ошибки при загрузке файла: Система не может найти указанный файл
0de _00000002.tmp (файл система находит Указанный файл не найден.)

Перейдем в каталог, указанный системой, чтобы проверить, успешно ли загружен файл:

Было обнаружено, что, несмотря на сообщение об ошибке, файл был успешно загружен:

Прежде чем анализировать причину ошибки, сначала проанализируем логику загрузки файла: когда клиент передает файл на сервер, файл сначала сообщает об ошибке системной сетевой карте, а затем сохраняет часть информации о файле в память сервера. , и соответствующее содержимое файла будет сохранено в локальном временном каталоге, если мы вызовем TransferTo(), сохраненные по умолчанию системные файлы будут перемещены в указанный нами каталог файлов, в этом случае файлы в исходном временном каталоге исчезнут , поэтому, когда мы вызываем соответствующую информацию о файле позже Метод заключается в том, чтобы сначала искать в памяти сервера.Если в памяти сервера нет такой информации, вам нужно искать во временном каталоге.Если такого нет файл во временном каталоге, будет сообщено об указанной выше ошибке.

Как решить эту проблему?

Решение также относительно простое: при вызове информации, связанной с файлом, просто вызывайте ее до того, как будет выполнен метод transferTo().

@RequestBody

Как мы упоминали ранее, будь то неаннотированный параметр запроса или использование аннотации @RequestParam, он не поддерживает синтаксический анализ данных json, в то время как @RequestBody может реализовать синтаксический анализ данных json , но не поддерживает синтаксический анализ других типов данных. .

Пример использования:

  @RequestMapping("/json")

    public Object jsonSend( @RequestBody User user){
        HashMap<String, String> map = new HashMap<>();
        map.put("name", user.getName());
        map.put("id", user.getId()+"");
        return map;
    }

Задайте программные схемы конфигурации через классы конфигурации

Мы знаем, что проект springboot можно настроить, установив формат файла конфигурации, но это неудобно для установки через файл конфигурации, или мы можем установить конфигурацию с помощью программирования (настройка класса конфигурации), чего нельзя добиться с помощью файла конфигурации. . Эта функция реализована @Configuration: класс, измененный @Configuration, загрузит конфигурацию при запуске проекта springboot.Мы используем следующие два примера для загрузки описания:

Установите унифицированный префикс внутреннего пути

Функция: добавить унифицированный префикс для всех серверных контроллеров (с именем: API).

Сценарий применения: При доступе к внутреннему пути запроса необходимо добавить некоторую унифицированную проверку в логику обработки некоторых его путей.Чтобы отличить внешний путь от внутреннего пути, мы равномерно добавляем префикс для всех контроллеров.

Приводим примеры кода:

Поскольку мы делаем настройку, связанную с веб-разработкой, наша конфигурация должна наследовать интерфейс WebMvcConfigurer.

@Configuration
public class AppConfig implements WebMvcConfigurer {
    //调用路径匹配的api,为所有的后端逻辑添加前缀
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
      configurer.addPathPrefix("api", c->{
          //通过循环遍历所有的后端controller判断是否要加前缀(暂时设置所有的路径都为前缀)
          //如果需要在此处使某些控制器不加前缀,在此处应该加一些别的逻辑经即可
         return true;
      });
    }

У нас нет пути запроса API в фактическом пути, но мы должны получить к нему доступ через путь «API» при посещении, иначе мы сообщим 404 напрямую.

 

Установить перехватчик

Давайте сначала разберемся с тремя основными компонентами веб-разработки: сервлет (коннектор), слушатель (слушатель) и фильтр (фильтр). Нам нужно прояснить: официально Spring не предоставляет перехватчики, а перехватчики предоставляются springmvc. Но принцип его реализации аналогично фильтрам.

Логика обработки перехватчика следующая:

 Прежде чем клиент отправит обратно запрос, он будет обработан методом перехватчика, связанным с preHander.PreHander возвращает логическое значение, TRUE будет продолжать выполняться вниз, а FALSE вернется напрямую; после того, как уровень контроллера вернет ответ, он также пройти через перехватчик. В это время вызовите метод postHander() и, наконец, верните ответ клиенту. Наш пользовательский перехватчик обычно переопределяет следующие три метода:

1. Метод preHandler(запрос HttpServletRequest, ответ HttpServletResponse, обработчик объекта) вызывается перед обработкой запроса. Этот метод выполняется первым в классе Interceptor и используется для выполнения некоторых операций предварительной инициализации или предварительной обработки текущего запроса, а также для принятия некоторых решений, чтобы определить, следует ли продолжить выполнение запроса. Возврат этого метода имеет тип Boolean, когда он возвращает false, это означает, что запрос завершен, и последующие Interceptor и Controller не будут выполняться, когда он возвращает true, он продолжит вызывать метод preHandle следующего Перехватчик, если он последний. При вызове перехватчика будет вызван метод Controller текущего запроса.

2. Метод postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) выполняется после обработки текущего запроса, то есть после вызова метода Controller, но он будет вызван до того, как DispatcherServlet вернет представление для рендеринга , поэтому мы можем использовать это. В методе работает объект ModelAndView, обрабатываемый контроллером.

3. Метод afterCompletion (запрос HttpServletRequest, ответ HttpServletResponse, дескриптор объекта, исключение ex) будет выполняться только в том случае, если возвращаемое значение метода preHandle соответствующего класса Interceptor равно true. Как следует из названия, этот метод будет выполнен после завершения всего запроса, то есть после того, как DispatcherServlet отобразит соответствующее представление. Этот метод в основном используется для очистки ресурсов.

Процесс настройки перехватчиков может быть разработан и проанализирован с учетом следующих трех аспектов: ①Настройка перехватчиков ②Настройка путей перехвата ③Установка логики обработки перехватчиков

Мы даем следующие три кода в перехватчике:
①Обработка пути:

Настройте путь перехвата для поддержки нечеткого сопоставления: метод настройки обычно реализуется путем добавления путей перехвата и исключения некоторых путей, которые не перехватываются.

/**: добавить любой путь

/api/**: добавить любой путь под API

/api/*: добавить слой каталога под API

Установить путь исключения:

/api/login: исключить каталог входа в API

/api/register: исключить регистрационный каталог под API.

②Пользовательский перехватчик:

Настройте перехватчик и укажите ссылку на интерфейс HandlerInterceptor, а затем перепишите методы в интерфейсе.

③ Реализовать логику метода

Реализовать логику метода в переопределенном методе

Полный код:

@Configuration
public class AppConfig implements WebMvcConfigurer {
    //调用路径匹配的api,为所有的后端逻辑添加前缀
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
      configurer.addPathPrefix("api", c->{
          //通过循环遍历所有的后端controller判断是否要加前缀(暂时设置所有的路径都为前缀)
         return true;
      });
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       //使用注册器进行注册过滤器
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/login")
                        .excludePathPatterns("/api/register");
    }
}
public class LoginInterceptor implements HandlerInterceptor {
    //设置请求逻辑:在请求前进行处理
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       //获取session
        HttpSession session = request.getSession(false);
        if(session!=null){
            String user = (String)session.getAttribute("user");
            if(user!=null){
                //判断是否是用户
                if(user.equals("admin")){
                    return true;
                }
            }
        }
        response.setStatus(401);

        return false;
    }
}

Функция перехватчика
Ведение журнала: запись журнала запроса информации для мониторинга информации, статистики информации, расчета PV (просмотра страницы) и т. д.; проверка полномочий: например, обнаружение входа в систему, вход в процессор
для определения того, вошел ли пользователь в систему;
мониторинг производительности: через перехватчик при входе. Процессор записывает время начала до и записывает время окончания после обработки, чтобы получить время обработки запроса. (Обратный прокси-сервер, такой как Apache, также может автоматически записывать)
Общее поведение: Прочитайте Cookie, чтобы получить информацию о пользователе и поместить объект пользователя в запрос, чтобы облегчить использование последующих процессов, а также извлечь информацию о локали, теме и т. д. ., лишь бы процессоров было несколько Все что нужно можно реализовать с помощью перехватчиков.

Унифицированная обработка исключений

Если возникает ошибка, когда мы делаем запрос через браузер, очень вероятно, что вся информация об ошибках бэкенда будет отображаться в браузере (деструктивная операция), с другой стороны, это не очень удобно для пользователя. .

Поэтому нам необходимо выполнить унифицированную обработку исключений и унифицировать отчеты об ошибках бэкенда.Мы выполняем следующие операции: используем аннотацию @ControllerAdvice для улучшения контроллера, используем @ExceptionHandle (класс исключений) для унифицированной обработки исключений, @ExceptionHandle (класс исключений) Логика обработки следующая: в соответствии с информацией о классе исключений в скобках, когда появляется сообщение об ошибке в классе исключений в скобках, используйте следующий метод для обработки отчета об ошибке (функция является перехватом обработки исключений)

@ControllerAdvice
public class ExceptionHandle {
    //默认以json形式返回数据
    @ResponseBody
    //统一捕获异常类
    @ExceptionHandler(Exception.class)
    public Object handle(Exception e){
        HashMap<String, Object> map = new HashMap<>();
        map.put("code",500);
        map.put("message",e.getMessage());
        return map;
    }

Следует отметить, что: @ExceptionHandle (класс исключения) может захватывать только исключения в своих скобках.Как только он выйдет за пределы класса исключения в его скобках, он будет напрямую возвращать информацию об ошибке клиенту: измененная ошибка сообщение следующее:

@ControllerAdvice
public class ExceptionHandle {
    //默认以json形式返回数据
//    @ResponseBody
//    //统一捕获异常类
//    @ExceptionHandler(Exception.class)
//    public Object handle(Exception e){
//        HashMap<String, Object> map = new HashMap<>();
//        map.put("code",500);
//        map.put("message",e.getMessage());
//        return map;
//    }
    @ResponseBody
    //统一捕获异常类
    @ExceptionHandler(IOException.class)
    public Object handleIo(Exception e){
        HashMap<String, Object> map = new HashMap<>();
        map.put("code",500);
        map.put("message",e.getMessage());
        return map;
    }

Единая обработка результатов:

①Пользовательский класс результатов

@Data
public class Result {
    private Boolean ok;
    private Object data;
    private String error;
}

② Используйте @ControllerAdvice для единообразной обработки результатов: установите ok data (данные обрабатываются непосредственно в возвращаемом теле) и error

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //进行赋值处理
        Result result = new Result();
        result.setOk(true);
        result.setData(body);
        result.setError(null);
        return result;
    }
}

Мы используем этот класс результата для доступа к следующему коду:

import java.util.HashMap;

/**
 * @author tongchen
 * @create 2023-04-28 10:34
 */
@RestController
public class UserController {
    @RequestMapping("/user/{id}/{name}")
    public Object user(@PathVariable String name,@PathVariable Integer id ){
        HashMap<String, Object> map = new HashMap<>();
        map.put("user", name);
        return map;
    }
}

Результат выглядит следующим образом:

Но мы обнаружили проблему.В этом коде мы напрямую пишем возвращаемую информацию кроме данных.Мы думаем над вопросом: Как в реальных бизнес-сценариях мы должны единообразно обрабатывать возвращаемые результаты? (аномальная обработка результатов и унифицированная обработка результатов)

A: Изменить класс возврата, отменить унифицированную настройку метода возврата и вернуть результат в конкретном бизнес-сценарии, а также вернуть результат отдельно для класса исключений.

Конкретный код и результаты следующие:

@Data
public class Result<T> {
    private Integer ok;//1代表成功 0代表失败
    private T data;
    private String msg;//正确或异常的信息
    public static <T>Result<T> success(T data){
        Result<T> result = new Result<>();
        result.setData(data);
        result.setOk(1);
        return result;
    }
    public static  <T>Result<T>error(String msg){
        Result<T> result = new Result<>();
        result.setOk(0);
       result.setMsg(msg);
        return result;
    }
}

 Класс нормального результата:

@RestController
public class UserController {
    @RequestMapping("/user/{id}/{name}")
    public Object user(@PathVariable String name,@PathVariable Integer id ){
        HashMap<String, Object> map = new HashMap<>();
        map.put("id", id);
        map.put("name",name);
        return Result.success(map);
    }
}

Класс результата исключения:

public class MyException extends Exception{
    public MyException(String message) {
        super(message);
    }
}
@RestController
public class ExceptionController {
    @RequestMapping("/test")
    public void test() throws MyException {
        throw new MyException("HAHAHH");
    }
}

Обработка класса результата исключения:
 

@ControllerAdvice
public class ExceptionHandle {
    //默认以json形式返回数据
//    @ResponseBody
//    //统一捕获异常类
//    @ExceptionHandler(Exception.class)
//    public Object handle(Exception e){
//        HashMap<String, Object> map = new HashMap<>();
//        map.put("code",500);
//        map.put("message",e.getMessage());
//        return map;
//    }
    @ResponseBody
    //统一捕获异常类
    @ExceptionHandler(MyException.class)
    public Object handleIo(Exception e){
        HashMap<String, Object> map = new HashMap<>();
      return Result.error("服务器错误");
    }


}

Нормальный результат:

 Результат исключения:

О роли responseBodyAdvice

 

 Интерфейс ResponseBodyAdvice должен выполнять некоторую обработку ответа после того, как контроллер выполнит возврат и до того, как ответ будет возвращен клиенту, что может реализовать некоторую унифицированную инкапсуляцию или шифрование данных ответа.

  Этот интерфейс имеет два метода:

(1) supports — оценивая, следует ли выполнять метод beforeBodyWrite, true для выполнения, false для невыполнения — — с помощью метода supports мы можем выбрать, какие классы или методы обрабатывать ответ, а остальные не будут обрабатываться.

(2) beforeBodyWrite — конкретный метод выполнения для обработки ответа.

Supongo que te gusta

Origin blog.csdn.net/m0_65431718/article/details/130361545
Recomendado
Clasificación