предисловие
Аутентификация и авторизация пользователей, ведение журнала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
Эта учетная запись будет продолжать делиться сухими товарами серверных технологий, включая основы виртуальных машин, многопоточное программирование, высокопроизводительные фреймворки, асинхронное ПО, промежуточное ПО для кэширования и обмена сообщениями, распределенные и микросервисы, материалы для обучения архитектуре и расширенные учебные материалы и статьи.