Eu sou novo no Spring. Percebi que ao manipular resources estáticos, existem duas opções disponíveis:
Opção 1:
Se o DispatcherServlet
do Spring for mapeado para /
com o código abaixo, o que o torna o “Servlet Padrão”, é possível mapear determinados resources estáticos para os manipuladores Spring com a anotação RequestMapping
(substituindo a class AbstractAnnotationConfigDispatcherServletInitializer
):
@Override protected String[] getServletMappings() { return new String[]{"/"}; }
Então, ainda podemos ativar o “Servlet Padrão” do contêiner para manipular esses resources estáticos cujo padrão de URL não é coberto pelo mapeamento de solicitação do Spring (substituindo a class WebMvcConfigurerAdapter
):
@Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); }
Isso basicamente usa o “Servlet Padrão” do contêiner do servlet como o pega-tudo para lidar com todos os resources estáticos perdidos pelo DispatcherServlet
do Spring.
Opção 2:
(substituindo a class WebMvcConfigurerAdapter
)
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("*.efi").addResourceLocations("/"); }
Eu costumo pegar a opção 2 porque eu quero ficar com a spring, mas sei que não é uma razão forte.
Alguma referência relacionada ao manuseio de resources estáticos:
ADICIONAR 1
Parece que a opção 2 oferece muito mais flexibilidade em relação ao mapeamento de resources. E até mesmo resources dentro WEB-INF
pasta WEB-INF
podem ser mapeados.
Aqui está um exemplo concreto de quando Falling Back no servlet “padrão” para servir resources não é aplicável.
Esta é uma implementação típica da abordagem acima:
@Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); return; }
No entanto, a melhor prática atual para lidar com erros 404 no Spring 4 parece ser usar setThrowExceptionIfNoHandlerFound
:
@Override protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) { DispatcherServlet dispatcherServlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext); dispatcherServlet.setThrowExceptionIfNoHandlerFound(true); return dispatcherServlet; }
Infelizmente, de acordo com a documentação do DispatcherServlet :
Observe que, se
DefaultServletHttpRequestHandler
for usado, as solicitações sempre serão encaminhadas para o servlet padrão e umaNoHandlerFoundException
nunca será lançada nesse caso.
Realmente, esse é o caso. Combinar as duas abordagens acima não resulta em um NoHandlerFoundException
sendo acionado, e isso, por sua vez, impede que minha página de erro 404 customizada seja resolvida. Agora, se eu fosse comentar meu método configureDefaultServletHandling
, o NoHandlerFoundException
é lançado e meu tratamento de erros (via @ControllerAdvice
como mostrado na resposta vinculada) resolve o meu personalizado ‘notFoundPage’.
Infelizmente, isso agora significa que meus resources estáticos (isto é, ‘default.css’) não são resolvidos:
DEBUG org.springframework.web.servlet.DispatcherServlet - Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name 'notFoundPage'; model is {} org.springframework.web.servlet.NoHandlerFoundException: No handler found for GET /webapp-test/style/default.css
Eu não vejo nenhuma maneira de conciliar essas duas abordagens para que elas não interfiram umas nas outras. Minha conclusão é que a abordagem “Servlet Padrão” não é apropriada para servir resources estáticos neste caso, o que nos deixa com o método addResourceHandlers
.
Entre os benefícios do uso do método addResourceHandlers
estão:
Veja também esta resposta para um exemplo mais complicado de como lidar com resources estáticos com o servlet padrão pode causar efeitos colaterais indesejados.