Внутренняя работа фильтров Servlet в Spring - PullRequest
0 голосов
/ 19 сентября 2019

Я из Node-ExpressJS, так что я знаком с концепцией промежуточного программного обеспечения.Когда я изучал Spring, я узнал о компоненте под названием Filter, который во многом отличается от промежуточного программного обеспечения в Express с некоторыми отличиями.

Поэтому я пытаюсь понять, как Filter и FilterChain на самом деле работает весной.

У меня есть следующий код:

Filter1.java

@Component
@Order(1)
public class Filter1 implements Filter {

    .....
    .....

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        LOGGER.info("############# Invoking Filter1 ############");
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        LOGGER.info("************ Moving on to next Filter");
        LOGGER.info("Adding new Attribute");
        req.setAttribute("Custom_Attribute_1", "TEST***TEST***TEST");
        chain.doFilter(request, response);
        resp.addHeader("1st Header", "1ST"); // Custom header that never shows up

        LOGGER.info("+++++++++ GOING BACK FROM Filter1 +++++++++");

    }

}

Filter2.java

@Component
@Order(2)
public class Filter2 implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        LOGGER.info("############# Invoking Filter2 ####################");
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        req.setAttribute("Filter2 Attribute", "2nd ORDER");
        resp.addHeader("2nd Header", "2ND"); //Custom header that actually shows up
        chain.doFilter(request, response);      
        LOGGER.info("+++++++++++ GOING BACK FROM Filter2 ++++++++++");
    }

}

Controller.java

@RestController
public class Controller {

   @GetMapping("/")
   public ResponseEntity<Object> createResource(HttpServletRequest req) {
     return new ResponseEntity<Object>("Resource Created",HttpStatus.OK);
   }
}

Когда я отправляю запрос своему контроллеру с помощью Postman, я вижу только один из моих пользовательских заголовков в ответе, а именно 2nd Header, но не вижу другой заголовок.

Заголовки ответа в Почтальоне

2nd Header → 2ND
Content-Type → text/plain;charset=UTF-8
Content-Length → 15
Date → Thu, 19 Sep 2019 20:16:25 GMT

Имеет ли какое-либо отношение к этому вызов chain.doFilter(request, response)?Кажется, что не может быть никакой модификации объекта response в классе Filter1 после вызова doFilter из FilterChain.

Что я пытаюсь понять здесь:

  1. Если FilterChain.doFilter - это то, что нужно вызвать для распространения объекта request на следующие фильтры и, в конечном итоге, на контроллер, разве нельзя разрешить модификацию объекта response послепозвонить на chain.doFilter возврат?Как именно это работает внутри?Как вызов передает все вниз на контроллер, а затем возвращается к первому фильтру?

  2. Кроме того, если Filter1 хотел увидеть телоответ после того, как он вернется из Filter2 и, возможно, изменить его, как бы он это сделал?

1 Ответ

0 голосов
/ 19 сентября 2019

Как правило, doFilter() отправляет объект запроса и ответа следующему фильтру в FilterChain, как указано в javadoc .

В вашем первом примере перед добавлением «1st Header» вы вызываете следующеефильтр в цепи.Вот почему вы не получаете "1-й заголовок" в первую очередь.Этот запрос перейдет на уровень контроллера, а затем будет оценен вашим контроллером.Когда контроллер завершает работу с объектом, ответ начинает заполняться фильтрами.

Таким образом, ваш код работает следующим образом:

arrived Filter1 -> Filter 2 > add "2st Header" > .. > Controller > Controller runs and prepares a response object.

Controller Response > .... > Filter 2 > Filter 1 > add "1st Header" > ...

Поэтому, когда запрос достигает вашего контроллера, контроллер никогда не будетиметь «1-й заголовок» в контексте запроса.

Кроме того, если Filter1 хочет увидеть тело ответа после его возврата из Filter2 и, возможно, изменить его, как бы он это сделал?

Я не пробовал этого, но вы должны взглянуть на эту тему , похоже, что вы хотите достичь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...