/ *에서 전역 프런트 컨트롤러 서블릿을 매핑 할 때 정적 리소스에 액세스하는 방법
Spring MVC 디스패처를 .NET의 전역 프런트 컨트롤러 서블릿으로 매핑했습니다 /*
.
<servlet>
<servlet-name>home</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
그러나이 매핑은 /res/
폴더 에있는 CSS, JS, 이미지 등과 같은 정적 파일에 대한 액세스를 중지 합니다.
그래도 어떻게 액세스 할 수 있습니까?
나는 이것도 만났지만 훌륭한 해결책을 찾지 못했습니다. 결국 URL 계층 구조에서 한 수준 더 높은 서블릿을 매핑했습니다.
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
이제 컨테이너가 기본 컨텍스트 (및 / res 디렉토리)의 모든 것을 제공 할 수 있습니다.
컨트롤러 서블릿을보다 구체적인 url-pattern
유사 에 매핑하고 /pages/*
, 정적 콘텐츠를 특정 폴더에 배치하고, 정적 콘텐츠에 대한 체인을 투명하게 계속하고 다른 콘텐츠에 대한 요청을 컨트롤러 서블릿에 전달 /static
하는 Filter
수신 대기를 만듭니다 /*
.
간단히 말해서 :
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
필터의 다음과 같이 doFilter()
:
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/static")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/pages" + path).forward(request, response);
}
아니오, 이것은 /pages
브라우저 주소 표시 줄에서 끝나지 않습니다 . 완전히 투명합니다. 당신은 할 수 필요 한 경우 "/static"
및 / 또는 필터."/pages"
init-param
와 봄 3.0.4.RELEASE 높은 당신은 사용할 수 있습니다
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
Spring Reference 에서 볼 수 있습니다.
당신이하는 일은 web.xml에 환영 파일을 추가하는 것입니다.
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
그런 다음이를 서블릿 매핑에 추가하여 누군가가 애플리케이션의 루트로 이동하면 내부적으로 index.html로 전송 된 다음 매핑이 내부적으로이를 매핑하는 서블릿으로 보냅니다.
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
최종 결과 : / Application을 방문하지만 다른 루트 요청을 방해하지 않고 / Application / MainActions 서블릿이 표시됩니다.
알 겠어요? 따라서 앱은 여전히 하위 URL에 있지만 사용자가 사이트의 루트로 이동하면 자동으로 표시됩니다. 이렇게하면 /images/bob.img는 여전히 일반 위치로 이동할 수 있지만 '/'는 앱입니다.
Tomcat을 사용하는 경우 리소스를 기본 서블릿에 매핑 할 수 있습니다.
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
URL http : // {context path} / static / res / ...를 사용하여 리소스에 액세스합니다.
다른 서블릿 컨테이너에 대해서는 확실하지 않은 Jetty에서도 작동합니다.
여러 서블릿 매핑 정의에서 적절한 접미사로 정적 콘텐츠를 제공하면 게시 된 답변 중 하나의 댓글 중 하나에서 언급 된 보안 문제가 해결되었습니다. 아래 인용 :
이것은 Tomcat의 보안 허점 (WEB-INF 및 META-INF 콘텐츠는이 방식으로 액세스 가능)이었으며 7.0.4에서 수정되었습니다 (5.x 및 6.x로 이식 될 예정 임). – BalusC 2010 년 11 월 2 일 22:44
많은 도움이되었습니다. 그리고 해결 방법은 다음과 같습니다.
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
3.0.4부터는 이를 달성하기 위해 스프링 문서에 설명 된대로 mvc:resources
와 함께 사용할 수 있어야합니다 mvc:default-servlet-handler
.
The reason for the collision seems to be because, by default, the context root, "/", is to be handled by org.apache.catalina.servlets.DefaultServlet. This servlet is intended to handle requests for static resources.
If you decide to bump it out of the way with your own servlet, with the intent of handling dynamic requests, that top-level servlet must also carry out any tasks accomplished by catalina's original "DefaultServlet" handler.
If you read through the tomcat docs, they make mention that True Apache (httpd) is better than Apache Tomcat for handling static content, since it is purpose built to do just that. My guess is because Tomcat by default uses org.apache.catalina.servlets.DefaultServlet to handle static requests. Since it's all wrapped up in a JVM, and Tomcat is intended to as a Servlet/JSP container, they probably didn't write that class as a super-optimized static content handler. It's there. It gets the job done. Good enough.
But that's the thing that handles static content and it lives at "/". So if you put anything else there, and that thing doesn't handle static requests, WHOOPS, there goes your static resources.
I've been searching high and low for the same answer and the answer I'm getting everywhere is "if you don't want it to do that, don't do that".
So long story short, your configuration is displacing the default static resource handler with something that isn't a static resource handler at all. You'll need to try a different configuration to get the results you're looking for (as will I).
'Static' files in App Engine aren't directly accessible by your app. You either need to upload them twice, or serve the static files yourself, rather than using a static handler.
The best way to handle this is using some kind of URL re-writing. In this way, you can have clean restful URLs, and NOT with any extensions i.e abc.com/welcom/register as opposed to abc.com/welcome/resister.html
I use Tuckey URL which is pretty cool.
It's got instructions on how to set up your web app.I have set it up with my Spring MVC web app. Of course, everything was fine until I wanted to use annotations for Spring 3 validations like @Email
or @Null
for domain objects.
When I add the Spring mvc directives:
< mvc:annotation-driven />
< mvc:default-servlet-handler />
.. it breaks the good ol Tuckey code. Apparently, < mvc:default-servlet-handler />
replaces Tuckey, which I'm still trying to solve.
Add the folders which you don't want to trigger servlet processing to the <static-files>
section of your appengine-web.xml file.
I just did this and looks like things are starting to work ok. Here's my structure:
/
/pages/<.jsp files>
/css
I added "/pages/**" and "/css/**" to the <static-files>
section and I can now forward to a .jsp file from inside a servlet doGet without causing an infinite loop.
After trying the filter approach without success (it did for some reason not enter the doFilter() function) I changed my setup a bit and found a very simple solution for the root serving problem:
Instead of serving " / * " in my main Servlet, I now only listen to dedicated language prefixes "EN", "EN/ *", "DE", "DE/ *"
Static content gets served by the default Servlet and the empty root requests go to the index.jsp which calls up my main Servlet with the default language:
< jsp:include page="/EN/" /> (no other content on the index page.)
I found that using
<mvc:default-servlet-handler />
in the spring MVC servlet bean definition file works for me. It passes any request that isn't handled by a registered MVC controller on to the container's original default handler, which should serve it as static content. Just make sure you have no controller registered that handles everything, and it should work just fine. Not sure why @logixplayer suggests URL rewriting; you can achieve the effect he's looking for just adequately using Spring MVC alone.
I'd recommend trying to use a Filter instead of a default servlet whenever possible.
Other two possibilities:
Write a FileServlet yourself. You'll find plenty examples, it should just open the file by URL and write its contents into output stream. Then, use it to serve static file request.
Instantiate a FileServlet class used by Google App Engine and call service(request, response) on that FileServlet when you need to serve the static file at a given URL.
You can map /res/* to YourFileServlet or whatever to exclude it from DispatcherServlets' handling, or call it directly from DispatcherServlet.
And, I have to ask, what does Spring documentation say about this collision? I've never used it.
I found a simpler solution with a dummy index file.
Create a Servlet (or use the one you wanted to respond to "/") which maps to "/index.html" (Solutions mentioned here use the mapping via XML, I used the 3.0 version with annotation @WebServlet) Then create a static (empty) file at the root of the static content named "index.html"
I was using Jetty, and what happened was that the server recognized the file instead of listing the directory but when asked for the resource, my Servlet took control instead. All other static content remained unaffected.
In Embedded Jetty I managed to achieve something similar by adding a mapping for the "css" directory in web.xml. Explicitly telling it to use DefaultServlet:
<servlet>
<servlet-name>DefaultServlet</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>/css/*</url-pattern>
</servlet-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:default-servlet-handler/>
</beans>
and if you want to use annotation based configuration use below code
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
With regard to Tomcat, a lot depends on the particular version. There was a bug fix https://bz.apache.org/bugzilla/show_bug.cgi?id=50026 which means the servlet-mapping (other than for '/') for the default servlet behaves differently in Tomcat 6.0.29 (and earlier) compared with later versions.
'Development Tip' 카테고리의 다른 글
UIMenuController가 표시되지 않음 (0) | 2020.12.09 |
---|---|
한 모서리에만 테두리 반경을 사용하는 방법 (반응 네이티브)? (0) | 2020.12.09 |
php_network_getaddresses : getaddrinfo 실패 : 이름 또는 서비스를 알 수 없음 (0) | 2020.12.08 |
dict에 대한 키로서의 Python 변수 (0) | 2020.12.08 |
유닉스 타임 스탬프는 int 열에 어떻게 저장되어야합니까? (0) | 2020.12.08 |