브라우저는 JSP로 전달되는 서블릿을 호출 할 때 CSS, 이미지 및 링크와 같은 관련 리소스에 액세스하거나 찾을 수 없습니다.


82

서블릿이 JSP로 전달 될 때 CSS 및 이미지를로드하고 다른 페이지에 대한 링크를 만드는 데 문제가 있습니다. 내가 설정 한 경우 특히, <welcome-file>에을 index.jsp의 CSS로드되고 있으며, 내 이미지가 표시되고있다. 그러나 제어를 전달하는 내 <welcome-file>를로 설정 하면 CSS가 적용되지 않고 내 이미지가 표시되지 않습니다.HomeServletindex.jsp

내 CSS 파일은 web/styles/default.css.
내 이미지는 web/images/.

내 CSS에 다음과 같이 연결합니다.

<link href="styles/default.css" rel="stylesheet" type="text/css" />

다음과 같이 내 이미지를 표시하고 있습니다.

<img src="images/image1.png" alt="Image1" />

이 문제는 어떻게 발생하며 어떻게 해결할 수 있습니까?


업데이트 1 : 응용 프로그램의 구조와 도움이 될 수있는 기타 정보를 추가했습니다.

대체 텍스트

header.jsp파일은 CSS에 대한 링크 태그가 들어있는 파일입니다. 은 HomeServlet내로 설정 welcome-file에서 web.xml:

<welcome-file-list>
    <welcome-file>HomeServlet</welcome-file>
</welcome-file-list>

서블릿은 다음과 같이 선언되고 매핑됩니다 web.xml.

<servlet>
    <servlet-name>HomeServlet</servlet-name>
    <servlet-class>com.brianblog.frontend.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

업데이트 2 : 마침내 문제를 발견했습니다-내 서블릿이 잘못 매핑되었습니다. 분명히 Servlet을 설정할 때 <welcome-file>URL 패턴을 가질 수 없습니다 /. 사이트의 루트 디렉토리를 나타내지 않기 때문에 이상한 것 같습니다.

새 매핑은 다음과 같습니다.

<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>

업데이트 2에 감사드립니다. 내 CSS가로드되지 않는 이유를 파악하기 위해 몇 시간 동안 벽에 머리를 부딪 혔습니다. (주석으로 / 있음).
kiwicomb123

답변:


100

JSP 파일에 의해 생성 된 HTML 페이지의 모든 상대 URL은 예상대로 서버 측의 JSP 파일 위치가 아니라 현재 요청 URL (브라우저 주소 표시 줄에 표시되는 URL)에 상대적 입니다. 즉, 디스크에서 리소스를 포함해야하는 웹 서버가 아니라 URL별로 리소스를 개별적으로 다운로드해야하는 웹 브라우저입니다.

JSP 파일의 위치 대신 서블릿의 URL을 기준으로 상대 URL을 변경하는 것 외에도이 문제를 해결하는 또 다른 방법은 도메인 루트에 대해 상대 URL을 만드는 것입니다 (예 :로 시작 /). 이렇게하면 서블릿의 URL을 변경할 때 상대 경로를 다시 변경하는 것에 대해 걱정할 필요가 없습니다.

<head>
    <link rel="stylesheet" href="/context/css/default.css" />
    <script src="/context/js/default.js"></script>
</head>
<body>
    <img src="/context/img/logo.png" />
    <a href="/context/page.jsp">link</a>
    <form action="/context/servlet"><input type="submit" /></form>
</body>

그러나 컨텍스트 경로를 하드 코딩하지 않는 것이 좋습니다. 매우 합리적입니다. 를 사용하여 EL에서 컨텍스트 경로를 얻을 수 있습니다 ${pageContext.request.contextPath}.

<head>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/default.css" />
    <script src="${pageContext.request.contextPath}/js/default.js"></script>
</head>
<body>
    <img src="${pageContext.request.contextPath}/img/logo.png" />
    <a href="${pageContext.request.contextPath}/page.jsp">link</a>
    <form action="${pageContext.request.contextPath}/servlet"><input type="submit" /></form>
</body>

(쉽게 단축하여 다른 곳 <c:set var="root" value="${pageContext.request.contextPath}" />에서처럼 사용할 수 있음 ${root})

또는 읽을 수없는 XML과 깨진 XML 구문 강조 표시를 두려워하지 않는다면 JSTL을 사용하십시오 <c:url>.

<head>
    <link rel="stylesheet" href="<c:url value="/css/default.css" />" />
    <script src="<c:url value="/js/default.js" />"></script>
</head>
<body>
    <img src="<c:url value="/img/logo.png" />" />
    <a href="<c:url value="/page.jsp" />">link</a>
    <form action="<c:url value="/servlet" />"><input type="submit" /></form>
</body>

어느 쪽이든, 상대 URL이 많은 경우 이는 차례로 매우 번거 롭습니다. 이를 위해 <base>태그를 사용할 수 있습니다 . 모든 상대 URL은 즉시 상대 URL이됩니다. 이 계획 (로 시작하지만이 http://, https://등). 일반 EL에서 기본 컨텍스트 경로를 얻을 수있는 깔끔한 방법이 없으므로 여기서 JSTL에 대한 약간의 도움이 필요합니다 .

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="req" value="${pageContext.request}" />
<c:set var="uri" value="${req.requestURI}" />
<c:set var="url">${req.requestURL}</c:set>
...
<head>
    <base href="${fn:substring(url, 0, fn:length(url) - fn:length(uri))}${req.contextPath}/" />
    <link rel="stylesheet" href="css/default.css" />
    <script src="js/default.js"></script>
</head>
<body>
    <img src="img/logo.png" />
    <a href="page.jsp">link</a>
    <form action="servlet"><input type="submit" /></form>
</body>

이것은 다시 (다시) 몇 가지주의 사항이 있습니다. 앵커 ( #identifierURL)도 기본 경로에 상대적이됩니다! 대신 요청 URL (URI)에 상대적으로 만들고 싶습니다. 그래서 변경

<a href="#identifier">jump</a>

...에

<a href="${uri}#identifier">jump</a>

각 방식마다 장단점이 있습니다. 선택하는 것은 당신에게 달려 있습니다. 적어도이 문제의 원인과 해결 방법을 이제 이해해야합니다. :)

또한보십시오:


나는 이것이 의미있는대로 작동하기를 정말로 바랐지만 브라우저는 여전히 파일을 찾을 수 없습니다. 내 질문에 더 많은 정보 (앱 구조 및 기타 일반 정보)를 추가했습니다. 도와 주셔서 감사합니다!
Brian DiCasa

3
/(smell, smell;)) 에 서블릿을 매핑했습니다 . 따라서 CSS 파일 (실제로 모든 HTTP 요청)을 가로 챕니다. 올바르게 처리하고 있습니까? 즉, localhost : 8080 / context / styles / default.css를 통해 웹 브라우저에서 직접 CSS 파일에 액세스 할 수 있습니까?
BalusC

"/"로 매핑되었을 때가 아닙니다. 그래도 "/ HomeServlet"으로 매핑되면 할 수 있습니다.
Brian DiCasa

처음 그것을 매핑 된 이유는 확실하지 않다 /*,하지만 당신은 어떤 전면 컨트롤러의 만들려고한다면, 나는 통해 자신을 얻을 좋을 것 이 답변 어쩌면 또한 및 이 답변을 .
BalusC

@BalusC-첫 번째 단락에서 "즉, 디스크에서 리소스를 포함해야하는 웹 서버가 아니라 URL로 개별적으로 리소스를 다운로드해야하는 웹 브라우저입니다." 웹 서버가 아닌 리소스를 가져 오는 것이 브라우저의 책임이라는 것을 실제로 확인할 수 있습니까? 실용적인 예제 나 튜토리얼을 알려 주시면 좋을 것입니다!
Abhishek Aggarwal


2

힌트를 위해 실제 HTML 출력을 분석해야합니다.

이와 같은 경로를 제공하는 것은 "현재 위치에서"를 의미하는 반면,로 시작하면 /"컨텍스트에서"를 의미합니다.


무슨 말인지 잘 모르겠습니다. 내가 이것에 대한 CSS 링크를 변경하면 :
Brian DiCasa

브라우저에서 HTML 소스를보고 경로가 올바른지 여부를 확인할 수 있습니다. 그렇지 않은 경우 수정하기 위해 무엇을해야합니까?
Adeel Ansari

나는 소스를보고 있었고 내 링크 태그에 대해 나오는 것은 내 질문에 게시 한 것입니다. 내 jsp에 직접 연결하면 파일을 찾을 수 있으며 전달을 수행하면 찾을 수없는 이유를 잘 모르겠습니다. 웹 앱의 모든 위치에서 찾을 수 있도록 내 이미지를 어디에 저장할 수 있습니까?
Brian DiCasa

좋아요, 당신 index.jsp이 당신 stylesimages디렉토리 와 같은 위치 / 레벨에 있기 때문 입니다. 따라서 직접 index.jsp환영 파일로 사용하면 모든 것이 매력적으로 보입니다. 반면에 서블릿을 통해 동일한 리소스를 전달할 때 문제는 더 이상 동일하지 않습니다. [계속 될 ...]
Adeel 안사

@Brian D .: ... 경로를 고려하지 않는 특정 서블릿에 요청을 보내기 위해 서블릿 매핑을 사용합니다. 이제 우리는 context path여기 를 이해해야합니다 . /경로에서 사용될 때 특정 의미가 있는 문서에서 보았 듯이 요청을 전달하거나 요청을 리디렉션하려고합니다. 슬래시가 없으면 컨텍스트 경로가 아닌 현재 위치에서 가져옵니다. 나는 당신이 지금 나를 얻고 있기를 바랍니다.
Adeel Ansari

0

환영 페이지는 That Servlet으로 설정됩니다. 따라서 모든 css, 이미지 경로는 해당 서블릿 DIR에 상대적으로 제공되어야합니다. 그것은 나쁜 생각입니다! 왜 서블릿이 홈 페이지로 필요합니까? .jsp를 색인 페이지로 설정하고 거기에서 페이지로 리디렉션합니까?

db에서 필드를 채우려 고하니 서블릿을 사용하고 있습니까?


4
서블릿을 (MVC) 프론트 컨트롤러로 사용하는 것은 확실히 나쁜 생각이 아닙니다 .
BalusC

0

Spring MVC를 사용하는 경우 정적 콘텐츠에 대한 기본 액션 서블릿을 선언해야합니다. spring-action-servlet.xml에 다음 항목을 추가하십시오. 그것은 나를 위해 일했습니다.

참고 : 모든 정적 콘텐츠는 WEB-INF 외부에 보관하십시오.

<!-- Enable annotation-based controllers using @Controller annotations -->
<bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="order" value="0" />
</bean>

<bean id="controllerClassNameHandlerMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
    <property name="order" value="1" />
</bean>

<bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

0

당신의 업데이트에 관해서는, 나는 그 이유에 대해 혼란 스러웠습니다. 조금 더 깊이 파고이 보석을 찾았습니다.

  • yoursite.com은 yoursite.com/이됩니다.
  • yoursite.com/은 디렉토리이므로 welcome-file-list가 스캔됩니다.
  • yoursite.com/CMS는 첫 번째 환영 파일 (welcome-file-list의 "CMS")이며 / CMS를 MyCMS 서블릿에 매핑하므로 서블릿에 액세스 할 수 있습니다.

출처 : http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage

따라서 매핑은 의미가 있습니다.

이제 $ {pageContext.request.contextPath} / path /를 상대 링크의 src / href로 자유롭게 사용할 수 있습니다!


0

짧은 대답-jsp에 기본
기본 href = "/ {응용 프로그램의 루트} /"를 정의 할 다음 줄을 추가 합니다.



0

이것도 시도해 볼 수 있습니다. 이것은 나를 위해 일했고 간단하기 때문입니다.

<style>
    <%@ include file="/css/style.css" %>
</style>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.