предисловие
Аутентификация и авторизация пользователей, ведение журналаMDC
,кодировать декодировать,UA
Проверка, многотерминальная переписка и т. д. должны пройтизапрос на перехватдля обработки. тогда нужноServlet
,Filter
,Listener
,Interceptor
эти компоненты. вместоSpring Boot
проект преобразован вSpring Boot
В проекте необходимо использовать предыдущие коды, поэтому необходимо понимать их и ихиспользованиеижизненный цикл.
Статьи из этой серии
- Actual Spring Boot 2.0 Series (1) — Создание образов Docker с помощью Gradle
- Actual Spring Boot 2.0 Series (2) — глобальная обработка исключений и тестирование
- Actual Spring Boot 2.0 Series (3) — Подробное объяснение асинхронных вызовов с использованием @Async
- Actual Spring Boot 2.0 Series (4) — Использование WebAsyncTask для обработки асинхронных задач
- Actual Spring Boot 2.0 Series (5) — прослушиватель, сервлет, фильтр и перехватчик
- Actual Spring Boot 2.0 Series (6) — несколько реализаций одномашинных задач синхронизации
текст
1. Введение нескольких компонентов
1.1 Слушатель
Listener
может контролироватьweb
один из серверовдействие события, и запустить зарегистрированныйПерезвони. простой языкapplication
,session
,request
три объектасоздать/смертьилиДобавления, удаления и модификациисвойство, функциональный компонент, который автоматически выполняет код.
1.2. Servlet
Servlet
это операцияСервис-терминализjava
приложение, сНезависимость от платформы и протоколафункции и могут быть динамически сгенерированыweb
страница, она работает назапрос клиентаиответ серверасредний слой.
1.3 Фильтр
Filter
правильноЗапрос пользователяпровестипредварительная обработка, затем передайте запросServlet
провестииметь дело сигенерировать ответ,НаконецFilter
Правильно сноваответ серверапровестиПостобработка.Filter
это повторно используемый фрагмент кода, часто используемый для преобразованияHTTP
просить,откликиинформация заголовка.Filter
в отличиеServlet
, он не может производитьотклик, но толькоИсправлятьдля ресурсапроситьилиотклик.
1.4. Перехватчик
похожийАспектно-ориентированное программированиесерединаразделиУведомление, мы проходимДинамический проксик одномуservice()
способ добавитьУведомлениеСделайте функциональные улучшения. Например, перед выполнением методапроцесс инициализации, после выполнения методаПостобработка.перехватчикмысль иAOP
похоже, разница естьперехватчиктолько правильноController
изHTTP
запрос на перехват.
2. Фильтры против перехватчиков
2.1 Разница между ними
-
Filter
основан наобратный вызов функции, покаInterceptor
основан наJava
отражениеиДинамический прокси. -
Filter
зависит отServlet
контейнер, покаInterceptor
Это не зависит отServlet
контейнер. -
Filter
почтивсе запросыработает, покаInterceptor
только правильноController
работает по запросу.
2.2 Порядок исполнения
на заказServlet
Для процесса распределения запросов:
-
Filter
обработка запроса фильтра; -
Servlet
обработка запросов; -
Filter
Обработка ответа фильтра.
на заказController
Процесс распределения запросов для:
-
Filter
обработка запроса фильтра; -
Interceptor
обработка запроса на перехват; - соответствующий
HandlerAdapter
обработка запросов; -
Interceptor
Обработка ответа на перехват; -
Interceptor
окончательная обработка; -
Filter
Обработка ответа фильтра.
3. Подготовка окружающей среды
Настройка зависимостей градиента
использоватьSpring Initializer
Создаватьgradle
проектspring-boot-listener-servlet-filter-interceptor
, добавляйте связанные зависимости при создании. получить начальныйbuild.gradle
следующее:
buildscript {
ext {
springBootVersion = '2.0.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'io.ostenant.springboot.sample'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
Настроить класс входа при запуске
настроитьSpring Boot
Запустите начальный класс, здесь вам нужно настроить две аннотации.
-
@ServletComponentScan: разрешить
Spring Boot
сканировать и монтировать текущийпуть к пакетуиподпутьнастроен подServlet
. -
@EnableWvc: разрешить
Spring Boot
настроитьSpring MVC
Связанные пользовательские свойства, такие как: перехватчики, обработчики ресурсов, преобразователи сообщений и т. д.
@EnableWebMvc
@ServletComponentScan
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4. Настройте прослушиватель Listener
настроитьServletContext
Слушатель, используй@WebListener
Отметьте это. существуетServlet
контейнеринициализацияв процессе,contextInitialized()
метод будет вызываться в контейнереразрушатьбудет вызван, когдаcontextDestroyed()
.
@WebListener
public class IndexServletContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexServletContextListener.class);
public static final String INITIAL_CONTENT = "Content created in servlet Context";
@Override
public void contextInitialized(ServletContextEvent sce) {
LOGGER.info("Start to initialize servlet context");
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("content", INITIAL_CONTENT);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
LOGGER.info("Destroy servlet context");
}
}
Здесь, когда контейнер инициализирован, перейдите кServletContext
Контекст устанавливает имя параметра вINITIAL_CONTENT
, к которым можно получить прямой глобальный доступ.
5. Настройте сервлет
настроитьIndexHttpServlet
, переписатьHttpServlet
изdoGet()
метод, прямой выводIndexHttpServlet
ОпределенныйПараметры инициализацииИ вIndexServletContextListener
наборServletContext
параметр контекста.
@WebServlet(name = "IndexHttpServlet",
displayName = "indexHttpServlet",
urlPatterns = {"/index/IndexHttpServlet"},
initParams = {
@WebInitParam(name = "createdBy", value = "Icarus"),
@WebInitParam(name = "createdOn", value = "2018-06-20")
}
)
public class IndexHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.getWriter().println(format("Created by %s", getInitParameter("createdBy")));
resp.getWriter().println(format("Created on %s", getInitParameter("createdOn")));
resp.getWriter().println(format("Servlet context param: %s",
req.getServletContext().getAttribute("content")));
}
}
настроить@WebServlet
Аннотация используется для регистрации этогоServlet
,@WebServlet
аннотированныйкаждый параметрсоответствуют соответственноweb.xml
Конфигурация в:
<servlet-mapping>
<servlet-name>IndexHttpServlet</servlet-name>
<url-pattern>/index/IndexHttpServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>IndexHttpServlet</servlet-name>
<servlet-class>io.ostenant.springboot.sample.servlet.IndexHttpServlet</servlet-class>
<init-param>
<param-name>createdBy</param-name>
<param-value>Icarus</param-value>
</init-param>
<init-param>
<param-name>createdOn</param-name>
<param-value>2018-06-20</param-value>
</init-param>
</servlet>
6. Настройте фильтр Фильтр
ОдинServlet
Запросы могут быть сделаны через несколькоFilter
отфильтровать и, наконец,Servlet
Обработка и ответ клиенту. Вот пример настройки двух фильтров:
FirstIndexFilter.java
@WebFilter(filterName = "firstIndexFilter",
displayName = "firstIndexFilter",
urlPatterns = {"/index/*"},
initParams = @WebInitParam(
name = "firstIndexFilterInitParam",
value = "io.ostenant.springboot.sample.filter.FirstIndexFilter")
)
public class FirstIndexFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(FirstIndexFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("Register a new filter {}", filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("FirstIndexFilter pre filter the request");
String filter = request.getParameter("filter1");
if (isEmpty(filter)) {
response.getWriter().println("Filtered by firstIndexFilter, " +
"please set request parameter \"filter1\"");
return;
}
chain.doFilter(request, response);
LOGGER.info("FirstIndexFilter post filter the response");
}
@Override
public void destroy() {
LOGGER.info("Destroy filter {}", getClass().getName());
}
}
выше@WebFilter
связанные свойства конфигурации, соответствующиеweb.xml
Конфигурация выглядит следующим образом:
<filter-mapping>
<filter-name>firstIndexFilter</filter-name>
<filter-class>io.ostenant.springboot.sample.filter.FirstIndexFilter</filter-class>
<url-pattern>/index/*</url-pattern>
<init-param>
<param-name>firstIndexFilterInitParam</param-name>
<param-value>io.ostenant.springboot.sample.filter.FirstIndexFilter</param-value>
</init-param>
</filter-mapping>
настроитьFirstIndexFilter
,использовать@WebFilter
Аннотации отмечены. когдаFirstIndexFilter
Во время инициализации он будет выполнятьinit()
метод. Каждый путь запроса соответствуетurlPatterns
Когда вы настроите путь, вы войдетеdoFilter()
метод, чтобы быть конкретнымпроситьиФильтрация ответов.
когдаHTTP
запросить переносfilter1
параметр, запрос будет снят, в противном случае напрямуюпрерывание фильтра, чтобы завершить обработку запроса.
SecondIndexFilter.java
@WebFilter(filterName = "secondIndexFilter",
displayName = "secondIndexFilter",
urlPatterns = {"/index/*"},
initParams = @WebInitParam(
name = "secondIndexFilterInitParam",
value = "io.ostenant.springboot.sample.filter.SecondIndexFilter")
)
public class SecondIndexFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(SecondIndexFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("Register a new filter {}", filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("SecondIndexFilter pre filter the request");
String filter = request.getParameter("filter2");
if (isEmpty(filter)) {
response.getWriter().println("Filtered by firstIndexFilter, " +
"please set request parameter \"filter2\"");
return;
}
chain.doFilter(request, response);
LOGGER.info("SecondIndexFilter post filter the response");
}
@Override
public void destroy() {
LOGGER.info("Destroy filter {}", getClass().getName());
}
}
выше@WebFilter
связанные свойства конфигурации, соответствующиеweb.xml
Конфигурация выглядит следующим образом:
<filter-mapping>
<filter-name>secondIndexFilter</filter-name>
<filter-class>io.ostenant.springboot.sample.filter.SecondIndexFilter</filter-class>
<url-pattern>/index/*</url-pattern>
<init-param>
<param-name>secondIndexFilterInitParam</param-name>
<param-value>io.ostenant.springboot.sample.filter.SecondIndexFilter</param-value>
</init-param>
</filter-mapping>
настроитьSecondIndexFilter
,использовать@WebFilter
Аннотации отмечены. когдаSecondIndexFilter
Во время инициализации он будет выполнятьinit()
метод. Каждый путь запроса соответствуетurlPatterns
Когда вы настроите путь, вы войдетеdoFilter()
метод, чтобы быть конкретнымпроситьиФильтрация ответов.
когдаHTTP
запросить переносfilter2
параметр, запрос будет снят, в противном случае напрямуюпрерывание фильтра, чтобы завершить обработку запроса.
приди и посмотриdoFilter()
Три основных параметра:
- ServletRequest: не прибыл
Servlet
изHTTP
просить; - Ответ сервлета: от
Servlet
обработано и сгенерированоHTTP
отклик; - FilterChain: цепочка фильтровобъект, несколько могут быть зарегистрированы последовательнофильтр.
FilterChain.doFilter(request, response);
объяснять:Одинцепочка фильтровОбъекты могут быть зарегистрированы несколько раз подрядфильтр. соответствует текущим условиям фильтрации фильтра, то есть запросуОтфильтровано успешноОтпустите сразу, затем передайте следующемуфильтрдля обработки. После завершения фильтрации всех запросов
IndexHttpServlet
обрабатывать и генерироватьотклик, затем вцепочка фильтровв противоположном направленииоткликВыполнение постфильтрации.
Конфигурация контроллера контроллера
настроитьIndexController
, для тестирования/index/IndexController
Будет ли путьFilter
фильтр иInterceptor
Перехватите и проверьте порядок этих двоих.
@RestController
@RequestMapping("index")
public class IndexController {
@GetMapping("IndexController")
public String index() throws Exception {
return "IndexController";
}
}
7. Настраиваем перехватчик Interceptor
перехватчикInterceptor
только правильноHandler
эффективный.Spring MVC
было быController
каждый изметод запросасоздан какHandler
объект, поHandlerMapping
Объект направляет запросы к определеннымHandler
, затем поHandlerAdapter
запрос через отражениеиметь дело сиотклик, с вкраплениямиОбработка перехвата.
написать перехватчик
Чтобы различать журналы, следующее то же самое, что иIndexController
Настройте два класса перехватчиков:
FirstIndexInterceptor.java
public class FirstIndexInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(FirstIndexInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOGGER.info("FirstIndexInterceptor pre intercepted the request");
String interceptor = request.getParameter("interceptor1");
if (isEmpty(interceptor)) {
response.getWriter().println("Filtered by FirstIndexFilter, " +
"please set request parameter \"interceptor1\"");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
LOGGER.info("FirstIndexInterceptor post intercepted the response");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOGGER.info("FirstIndexInterceptor do something after request completed");
}
}
SecondIndexInterceptor.java
public class SecondIndexInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SecondIndexInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOGGER.info("SecondIndexInterceptor pre intercepted the request");
String interceptor = request.getParameter("interceptor2");
if (isEmpty(interceptor)) {
response.getWriter().println("Filtered by SecondIndexInterceptor, " +
"please set request parameter \"interceptor2\"");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
LOGGER.info("SecondIndexInterceptor post intercepted the response");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOGGER.info("SecondIndexInterceptor do something after request completed");
}
}
Настроить перехватчик
существуетSpring Boot
серединаНастроить перехватчикочень просто, просто реализуйтеWebMvcConfigurer
интерфейс, вaddInterceptors()
через методInterceptorRegistry
Добавить кперехватчикипуть совпаденияВот и все.
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
private static final Logger LOGGER = LoggerFactory.getLogger(WebConfiguration.class);
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FirstIndexInterceptor()).addPathPatterns("/index/**");
registry.addInterceptor(new SecondIndexInterceptor()).addPathPatterns("/index/**");
LOGGER.info("Register FirstIndexInterceptor and SecondIndexInterceptor onto InterceptorRegistry");
}
}
соответствующийSpring XML
Конфигурация выглядит следующим образом:
<bean id="firstIndexInterceptor"
class="io.ostenant.springboot.sample.interceptor.FirstIndexInterceptor"></bean>
<bean id="secondIndexInterceptor"
class="io.ostenant.springboot.sample.interceptor.SecondIndexInterceptor"></bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/index/**" />
<ref local="firstIndexInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/index/**" />
<ref local="secondIndexInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
Принципиальный анализ
мы достигаем путемHandlerInterceptor
интерфейс для разработкиперехватчик,приди и посмотриHandlerInterceptor
Три важных метода интерфейса:
-
preHandle(): в
controller
получить запрос, обработатьrequest
Выполнено ранее, возвращаемое значение равноboolean
, возвращаемое значение равноtrue
затем выполнитьpostHandle()
иafterCompletion()
метод; если возвращаетсяfalse
нопрерыватьвоплощать в жизнь. -
postHandle (): в
controller
После обработки запроса,ModelAndView
Выполняется перед обработкой, вы можетерезультат ответамодифицировать. -
после завершения(): в
DispatchServlet
Обработка этого запроса завершена, то есть генерацияModelAndView
Выполнить потом.
Просто взгляните нижеSpring MVC
центральный планировщикDispatcherServlet
изdoDispatch()
Принципы метода, основное вниманиеперехватчикПорядок выполнения трех вышеуказанных методов.
- doDispatch():
DispatchServlet
Основной метод обработки отправки запроса.
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 1. 按从前往后的顺序调用各个拦截器preHandle()方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 2. HandlerAdapter开始真正的请求处理并生产响应视图对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 3. 按照从后往前的顺序依次调用各个拦截器的postHandle()方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
// 4. 最终会调用拦截器的afterCompletion()方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
} catch (Throwable err) {
// 4. 最终会调用拦截器的afterCompletion()方法
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else {
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
Несколько примечаний выше
HandlerExecutionChain
Методы:applyPreHandle()
,applyPostHandle()
иtriggerAfterCompletion()
.
- applyPreHandle(): нажмитеСпереди назадПорядок вызова каждого перехватчика
preHandle()
метод. кто-нибудьHandlerInterceptor
перехват возвратаfalse
,ноpreHandle()
возвращениеfalse
, который записывает местоположение перехватчикаinterceptorIndex
, затем прервите обработку перехвата и, наконец, вызовитеAfterCompletion()
метод и возвратfalse
.
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
- applyPostHandle(): согласнозадом напередПорядок вызова каждого перехватчика по очереди
postHandle()
метод. только если всеHandlerInterceptor
изpreHandle()
метод возвращаетtrue
только когда появляется возможность выполнитьapplyPostHandle()
метод.
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
- triggerAfterCompletion:
triggerAfterCompletion()
только вpreHandle()
метод возвращаетfalse
иПрограмма выдает исключениепри исполнении. существуетpreHandle()
метод, черезinterceptorIndex
зарегистрированный возвратfalse
изИндекс перехватчика. однаждыapplyPreHandle()
метод возвращаетfalse
, затем вернуться из текущегоfalse
перехватчикзадом напередисполнениеafterCompletion()
метод.
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
8. Запустите тест
тестирование жизненного цикла
запускатьSpring Boot
Приложение, наблюдайте за журналом программы при запуске, ниже я следуюприказдля анализа того, что делается во время запуска.
- регистр
Spring MVC
изdispatcherServlet
и обычайIndexHttpServlet
.
2018-06-23 09:39:55.400 INFO 12301 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]
2018-06-23 09:39:55.404 INFO 12301 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet IndexHttpServlet mapped to [/index/IndexHttpServlet]
Уведомление:
dispatcherServlet
изload-up-onstartup
за1
, будет иметь приоритет над другимиServlet
загрузить.
- Расставь все фильтры по порядку
Filter
Объекты отображаются с путями, гдеcharacterEncodingFilter
даSpring MVC
Встроенное решение для искаженных символовFilter
.
2018-06-23 09:39:55.408 INFO 12301 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-06-23 09:39:55.409 INFO 12301 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'firstIndexFilter' to urls: [/index/*]
2018-06-23 09:39:55.409 INFO 12301 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'secondIndexFilter' to urls: [/index/*]
- инициализация
IndexServletContextListener
и выполнитьcontextInitialized()
метод инициализации контекста.
2018-06-23 09:39:55.429 INFO 12301 --- [ost-startStop-1] i.o.s.s.l.IndexServletContextListener : Start to initialize servlet context
- выполнять последовательно
Filter
изinit()
метод для инициализации.
2018-06-23 09:39:55.432 INFO 12301 --- [ost-startStop-1] i.o.s.sample.filter.SecondIndexFilter : Register a new filter secondIndexFilter
2018-06-23 09:39:55.434 INFO 12301 --- [ost-startStop-1] i.o.s.sample.filter.FirstIndexFilter : Register a new filter firstIndexFilter
- Создайте, инициализируйте перехватчик и зарегистрируйте его единообразно для
InterceptorRegistry
начальство.
2018-06-23 09:39:55.502 INFO 13150 --- [ main] i.o.s.s.interceptor.WebConfiguration : Register FirstIndexInterceptor and SecondIndexInterceptor onto InterceptorRegistry
- правильно
IndexController
процесс,проситьURI
иПодходсопоставить сHandlerMapping
включено и кэшировано.
2018-06-23 09:39:55.541 INFO 12301 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/index/IndexController],methods=[GET]}" onto public java.lang.String io.ostenant.springboot.sample.controller.IndexController.index() throws java.lang.Exception
закрытиеSpring Boot
При применении приложения наблюдайте за выходным журналом следующим образом:
2018-06-23 10:07:03.294 INFO 12301 --- [ost-startStop-2] i.o.s.sample.filter.FirstIndexFilter : Destroy filter io.ostenant.springboot.sample.filter.SecondIndexFilter
2018-06-23 10:07:03.294 INFO 12301 --- [ost-startStop-2] i.o.s.sample.filter.FirstIndexFilter : Destroy filter io.ostenant.springboot.sample.filter.FirstIndexFilter
2018-06-23 10:07:03.294 INFO 12301 --- [ost-startStop-2] i.o.s.s.l.IndexServletContextListener : Destroy servlet context
Вы можете увидеть фильтр, настроенный вышеdestroy()
Методы иIndexServletContextListener
изcontextDestroyed()
Способы называются.
проверка контроля доступа
Тест сервлета
доступhttp://localhost:8080/index/IndexHttpServlet, содержимое страницы ответа выглядит следующим образом:
доступhttp://localhost:8080/index/IndexHttpServlet?filter1=filter1, содержимое страницы ответа выглядит следующим образом:
доступhttp://localhost:8080/index/IndexHttpServlet?filter1=filter1&filter2=filter2, содержимое страницы ответа выглядит следующим образом:
Просмотрите журнал вывода консоли, чтобы проверитьфильтрПорядок фильтров правильный.
2018-06-23 10:19:47.944 INFO 13150 --- [nio-8080-exec-1] i.o.s.sample.filter.FirstIndexFilter : FirstIndexFilter pre filter the request
2018-06-23 10:19:47.944 INFO 13150 --- [nio-8080-exec-1] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter pre filter the request
2018-06-23 10:19:47.944 INFO 13150 --- [nio-8080-exec-1] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter post filter the response
2018-06-23 10:19:47.944 INFO 13150 --- [nio-8080-exec-1] i.o.s.sample.filter.FirstIndexFilter : FirstIndexFilter post filter the response
в заключении:индивидуальныефильтрправильно
IndexHttpServlet
эффективным, при этомнастроитьПерехватчик вступает в силу.
тест контроллера
доступhttp://localhost:8080/index/IndexController, содержимое страницы ответа выглядит следующим образом:
доступhttp://localhost:8080/index/IndexController?filter1=filter1, содержимое страницы ответа выглядит следующим образом:
доступhttp://localhost:8080/index/IndexController?filter1=filter1&filter2=filter2, содержимое страницы ответа выглядит следующим образом:
доступhttp://localhost:8080/index/IndexController?filter1=filter1&filter2=filter2&interceptor1=interceptor1, содержимое страницы ответа выглядит следующим образом:
доступhttp://localhost:8080/index/IndexController?filter1=filter1&filter2=filter2&interceptor1=interceptor1&interceptor2=interceptor2, содержимое страницы ответа выглядит следующим образом:
2018-06-23 10:21:42.533 INFO 13150 --- [nio-8080-exec-4] i.o.s.sample.filter.FirstIndexFilter : FirstIndexFilter pre filter the request
2018-06-23 10:21:42.533 INFO 13150 --- [nio-8080-exec-4] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter pre filter the request
2018-06-23 10:21:42.534 INFO 13150 --- [nio-8080-exec-4] i.o.s.s.i.FirstIndexInterceptor : FirstIndexInterceptor pre intercepted the request
2018-06-23 10:21:42.534 INFO 13150 --- [nio-8080-exec-4] i.o.s.s.i.SecondIndexInterceptor : SecondIndexInterceptor pre intercepted the request
2018-06-23 10:21:42.535 INFO 13150 --- [nio-8080-exec-4] i.o.s.s.i.SecondIndexInterceptor : SecondIndexInterceptor post intercepted the response
2018-06-23 10:21:42.535 INFO 13150 --- [nio-8080-exec-4] i.o.s.s.i.FirstIndexInterceptor : FirstIndexInterceptor post intercepted the response
2018-06-23 10:21:42.535 INFO 13150 --- [nio-8080-exec-4] i.o.s.s.i.SecondIndexInterceptor : SecondIndexInterceptor do something after request completed
2018-06-23 10:21:42.535 INFO 13150 --- [nio-8080-exec-4] i.o.s.s.i.FirstIndexInterceptor : FirstIndexInterceptor do something after request completed
2018-06-23 10:21:42.535 INFO 13150 --- [nio-8080-exec-4] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter post filter the response
2018-06-23 10:21:42.535 INFO 13150 --- [nio-8080-exec-4] i.o.s.sample.filter.FirstIndexFilter : FirstIndexFilter post filter the response
в заключении:индивидуальныефильтриперехватчикправильноконтроллер
Controller
эффективный. ифильтрприоритет выше, чемперехватчик.
резюме
В этой статье подробноListener
,Servlet
,Filter
,Controller
иInterceptor
ЖдатьWeb
Функции, методы, порядок, объем и жизненный цикл различных компонентов. Приведен подробный пример кода в сочетании сисходный кодПроанализировал процесс, объединилконтрольная работаВывод проверен. Долгая история, я надеюсь, что вы всеServlet
компоненты иSpring MVC
Более четкое понимание компонентов фреймворка.
Добро пожаловать в технический публичный аккаунт: Zero One Technology Stack
Эта учетная запись будет продолжать делиться сухими товарами серверных технологий, включая основы виртуальных машин, многопоточное программирование, высокопроизводительные фреймворки, асинхронное ПО, промежуточное ПО для кэширования и обмена сообщениями, распределенные и микросервисы, материалы для обучения архитектуре и расширенные учебные материалы и статьи.