оригинал:191122-Четыре варианта регистрации сервлета в веб-главе руководств серии SpringBoot.
Руководство по использованию и общие элементы фильтра, подверженные ошибкам, в трех элементах Java-сети представлены ранее.Далее давайте посмотрим на состояние использования сервлета.В этой статье в основном представлены четыре положения регистрации пользовательского Servelt в среде SpringBoot. .
-
@WebServletаннотация -
ServletRegistrationBeanопределение фасоли -
ServletContextдобавлять динамически - нормальная весенняя фасоль
I. Конфигурация среды
1. Строительство проекта
Прежде всего, нам нужно создать веб-проект, чтобы облегчить последующую демонстрацию примера регистрации servlt.Вы можете создать проект через официальный сайт весенней загрузки или создать проект maven, который настроен следующим образом в pom .xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
Специальное примечание:
Чтобы не отставать от последней версии SpringBoot, начиная с этой статьи, версия SpringBoot в примере проекта, соответствующем сообщению в блоге, обновлена до2.2.1.RELEASE
II. Регистрация сервлета
Настроить сервлет относительно просто, и распространенной операцией является наследование.HttpServlet, затем перезапишитеdoGet, doPostОднако ключевым моментом является то, как эти настраиваемые сервлеты могут быть распознаны и использованы SpringBoot.Четыре метода регистрации описаны ниже.
1. @WebServlet
Добавьте аннотации Servlet3+ к пользовательским сервлетам.@WebServlet, чтобы объявить, что этот класс является сервлетом
Подобно методу регистрации Fitler, для использования этой аннотации вам необходимо сотрудничать с Spring Boot@ServletComponentScan, в противном случае простое добавление приведенной выше аннотации не подействует
/**
* 使用注解的方式来定义并注册一个自定义Servlet
* Created by @author yihui in 19:08 19/11/21.
*/
@WebServlet(urlPatterns = "/annotation")
public class AnnotationServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
PrintWriter writer = resp.getWriter();
writer.write("[AnnotationServlet] welcome " + name);
writer.flush();
writer.close();
}
}
Выше приведен простой тестовый сервлет, который получает параметры запроса.name, и вернутьсяwelcome xxx; Для того, чтобы приведенные выше аннотации вступили в силу, необходимо установить класс запуска
@ServletComponentScan
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
Затем запустите тест, и результаты вывода будут следующими:
➜ ~ curl http://localhost:8080/annotation\?name\=yihuihui
# 输出结果
[AnnotationServlet] welcome yihuihui%
2. ServletRegistrationBean
При регистрации Filter мы знаем, что есть способ определить Spring BeanFilterRegistrationBeanЧтобы обернуть наш пользовательский фильтр, чтобы контейнер Spring управлял нашим фильтром; также в сервлете есть аналогичные bean-компоненты-оболочки:ServletRegistrationBean
Пользовательский компонент выглядит следующим образом, обратите внимание, что в классе нет аннотаций.
/**
* Created by @author yihui in 19:17 19/11/21.
*/
public class RegisterBeanServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
PrintWriter writer = resp.getWriter();
writer.write("[RegisterBeanServlet] welcome " + name);
writer.flush();
writer.close();
}
}
Далее нам нужно определитьServletRegistrationBean, пусть держитRegisterBeanServletслучай
@Bean
public ServletRegistrationBean servletBean() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean();
registrationBean.addUrlMappings("/register");
registrationBean.setServlet(new RegisterBeanServlet());
return registrationBean;
}
Вывод тестового запроса выглядит следующим образом:
➜ ~ curl 'http://localhost:8080/register?name=yihuihui'
# 输出结果
[RegisterBeanServlet] welcome yihuihui%
3. ServletContext
Эта поза редко используется при фактической регистрации сервлета.javax.servlet.ServletContext#addServlet(java.lang.String, java.lang.Class<? extends javax.servlet.Servlet>)метод активного добавления сервлета
Поэтому нам нужно найти подходящее время, чтобы получитьServletContextэкземпляр и зарегистрируйте сервлет. В экосистеме SpringBoot вы можете использоватьServletContextInitializer
ServletContextInitializer в основном реализуется RegistrationBean для регистрации Servlet, Filter или EventListener в контейнере ServletContext. Эти ServletContextInitializers предназначены в первую очередь для управления этими экземплярами контейнером Spring IoC.
/**
* Created by @author yihui in 19:49 19/11/21.
*/
public class ContextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
PrintWriter writer = resp.getWriter();
writer.write("[ContextServlet] welcome " + name);
writer.flush();
writer.close();
}
}
/**
* Created by @author yihui in 19:50 19/11/21.
*/
@Component
public class SelfServletConfig implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
ServletRegistration initServlet = servletContext.addServlet("contextServlet", ContextServlet.class);
initServlet.addMapping("/context");
}
}
Результаты теста следующие
➜ ~ curl 'http://localhost:8080/context?name=yihuihui'
# 输出结果
[ContextServlet] welcome yihuihui%
4. bean
Следующий метод регистрации не является элегантным, но он также может достичь цели регистрации сервлета, но есть подводные камни, пожалуйста, используйте его с осторожностью.
См. мою предыдущую запись в блоге191016-SpringBoot серия руководств, веб-часть руководства по фильтруодноклассники, может есть немного изображения, его можно добавить прямо на фильтре@ComponentАннотация: когда контейнер Spring сканирует bean-компонент, он находит все подклассы, реализующие фильтр, и активно оборачивает его вFilterRegistrationBean, для достижения цели регистрации
Может ли наш сервлет сделать то же самое? Далее давайте тестировать
@Component
public class BeanServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
PrintWriter writer = resp.getWriter();
writer.write("[BeanServlet1] welcome " + name);
writer.flush();
writer.close();
}
}
Теперь возникает вопрос, приведенный выше сервлет не определяет правило urlMapping, как его запросить?
Чтобы подтвердить, что указанный выше сервлет зарегистрирован, мы нашли фактическое место регистрации по ключевой ссылке анализа исходного кода предыдущего фильтра.ServletContextInitializerBeans#addAsRegistrationBean
// org.springframework.boot.web.servlet.ServletContextInitializerBeans#addAsRegistrationBean(org.springframework.beans.factory.ListableBeanFactory, java.lang.Class<T>, java.lang.Class<B>, org.springframework.boot.web.servlet.ServletContextInitializerBeans.RegistrationBeanAdapter<T>)
@Override
public RegistrationBean createRegistrationBean(String name, Servlet source, int totalNumberOfSourceBeans) {
String url = (totalNumberOfSourceBeans != 1) ? "/" + name + "/" : "/";
if (name.equals(DISPATCHER_SERVLET_NAME)) {
url = "/"; // always map the main dispatcherServlet to "/"
}
ServletRegistrationBean<Servlet> bean = new ServletRegistrationBean<>(source, url);
bean.setName(name);
bean.setMultipartConfig(this.multipartConfig);
return bean;
}
Как видно из приведенного выше исходного кода, URL-адрес этого сервлета либо/, либо/beanName/
Далее собственно измерение, все 404
➜ ~ curl 'http://localhost:8080/?name=yihuihui'
{"timestamp":"2019-11-22T00:52:00.448+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}%
➜ ~ curl 'http://localhost:8080/beanServlet1?name=yihuihui'
{"timestamp":"2019-11-22T00:52:07.962+0000","status":404,"error":"Not Found","message":"No message available","path":"/beanServlet1"}%
➜ ~ curl 'http://localhost:8080/beanServlet1/?name=yihuihui'
{"timestamp":"2019-11-22T00:52:11.202+0000","status":404,"error":"Not Found","message":"No message available","path":"/beanServlet1/"}%
Затем при определении сервлета
@Component
public class BeanServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
PrintWriter writer = resp.getWriter();
writer.write("[BeanServlet2] welcome " + name);
writer.flush();
writer.close();
}
}
проверить снова
➜ ~ curl 'http://localhost:8080/beanServlet1?name=yihuihui'
{"timestamp":"2019-11-22T00:54:12.692+0000","status":404,"error":"Not Found","message":"No message available","path":"/beanServlet1"}%
➜ ~ curl 'http://localhost:8080/beanServlet1/?name=yihuihui'
[BeanServlet1] welcome yihuihui%
➜ ~ curl 'http://localhost:8080/beanServlet2/?name=yihuihui'
[BeanServlet2] welcome yihuihui%
Из фактических результатов теста видно, что при использовании этого метода определения соответствующий URL-адрес этого сервлетаbeanName + '/'
Меры предосторожности
Затем возникает проблема, когда определен только один сервлет, согласно предыдущему анализу исходного кода, сервлет должен реагировать соответствующим образом.http://localhost:8080/запрос, но почему при тестировании 404?
На этот вопрос легко ответить, в основном из-за приоритета сервлета. Соответствующий приоритет сервлета в приведенном выше методе ниже, чем у Spring Web Servlet. Тот же запрос URL-адреса сначала назначается сервлету Spring. Это также просто проверить это. , два шага
- Аннотировать первым
BeanServlet2Аннотация к классу@Component - существует
BeanServlet1В классе добавьте аннотации@Order(-10000)
Затем снова запустите тест, вывод будет следующим
➜ ~ curl 'http://localhost:8080/?name=yihuihui'
[BeanServlet1] welcome yihuihui%
➜ ~ curl 'http://localhost:8080?name=yihuihui'
[BeanServlet1] welcome yihuihui%
5. Резюме
В этой статье в основном представлены четыре метода регистрации сервлета, что касается руководства по использованию сервлета, мы подождем следующей части.
Есть два распространенных случая регистрации:
-
@WebServletАннотация помещается в класс Servlet, а затем добавляется в класс запуска.@ServletComponentScan, чтобы Spring мог распознавать аннотации Serlvet3+. - Делегирование пользовательского экземпляра сервлета bean-компоненту
ServletRegistrationBean
Два необычных регистрационных случая:
- реализовать интерфейс
ServletContextInitializer,пройти черезServletContext.addServletдля регистрации пользовательских сервлетов - Зарегистрируйте Serlvet непосредственно в Spring как обычный bean-компонент.
- Когда в этом случае в проекте только один сервлет, он отвечает на url: '/', но следует отметить, что когда приоритет не указан, сервлет Spring по умолчанию имеет более высокий приоритет, поэтому он не может принимать запросы.
- Когда проект имеет несколько сервлетов для этого случая, URL-адрес ответа
beanName + '/', обратите внимание, что следующий '/' должен иметь
II. Другое
0. Проект
веб-сериал
- 191120-Открытие сжатия данных GZIP в серии руководств SpringBoot Web
- 191018-Расширение руководства пользователя фильтра для веб-главы руководств по серии SpringBoot
- 191016-SpringBoot серия руководств, веб-часть руководства по фильтру
- 191012-Пользовательская обработка исключений HandlerExceptionResolver в веб-главе серии руководств SpringBoot
- 191010-Обработка глобальных исключений в веб-главе серии руководств SpringBoot
- 190930 — конфигурация страницы исключений 404, 500 в веб-главе серии руководств по SpringBoot
- 190929-Перенаправление обучающих веб-статей серии SpringBoot
- 190913-Положение операции при возврате текста, веб-страниц и изображений в веб-главе серии руководств SpringBoot.
- 190905-Решение проблемы с искаженными китайскими символами в веб-главе серии учебных пособий SpringBoot.
- 190831-Как настроить анализатор параметров в веб-главе серии руководств по SpringBoot.
- 190828-Сводная информация об анализе параметров запроса Post в веб-главе серии руководств SpringBoot.
- 190824-Краткий обзор положения синтаксического анализа параметров запроса в веб-учебнике SpringBoot Series
- 190822-Создание среды Beetl в веб-главе серии руководств SpringBoot
- 190820-Springboot Series Учебное пособие в Интернете Строительство среды IMELEAF
- 190816-Веб-глава серии SpringBoot, посвященная построению среды Freemaker
- 190421 - Инструкции по использованию веб-сокета WEB в SpringBoot Advanced
- 190327-Полный анализ исключения синтаксического анализа параметра urlencode для Spring-RestTemplate
- 190317-Spring Создание веб-приложения на основе MVC на основе конфигурации java без конфигурации xml
- 190316-Создание веб-приложения на основе конфигурации XML для Spring MVC
- 190213-Подсказка об исключении загрузки файла SpringBoot Временное местоположение загрузки xxx недопустимо
Исходный код проекта
- проект:GitHub.com/JuneB/tickets…
- проект:GitHub.com/JuneB/tickets…
1. Блог одного пепла
Это не так хорошо, как письмо.Вышеупомянутое содержание чисто из семьи.Из-за ограниченных личных способностей неизбежно есть упущения и ошибки.Если вы найдете ошибки или у вас есть лучшие предложения, вы можете критиковать и исправлять их.
Ниже представлен серый личный блог, в котором записываются все посты в блоге по учебе и работе, приглашаю всех посетить
- Блог One Ash Личный блогblog.hhui.top
- Блог One Ash - специальный весенний блогspring.hhui.top