Trình duyệt không thể truy cập / tìm các tài nguyên tương đối như CSS, hình ảnh và liên kết khi gọi Servlet chuyển tiếp đến JSP


82

Tôi đang gặp sự cố khi tải CSS và hình ảnh cũng như tạo liên kết đến các trang khác khi tôi chuyển tiếp một servlet tới JSP. Cụ thể, khi tôi đặt tôi <welcome-file>đến index.jsp, CSS đã được nạp và hình ảnh của tôi đang được hiển thị. Tuy nhiên, nếu tôi đặt tôi <welcome-file>để HomeServletđó chuyển tiếp kiểm soát để index.jsp, CSS chưa được áp dụng và hình ảnh của tôi không được hiển thị.

Tệp CSS của tôi ở trong web/styles/default.css.
Hình ảnh của tôi có trong web/images/.

Tôi đang liên kết với CSS của mình như vậy:

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

Tôi đang hiển thị hình ảnh của mình như sau:

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

Làm thế nào vấn đề này được gây ra và làm thế nào tôi có thể giải quyết nó?


Cập nhật 1 : Tôi đã thêm cấu trúc của ứng dụng, cũng như một số thông tin khác có thể hữu ích.

văn bản thay thế

Các header.jsptập tin là tập tin có chứa các thẻ liên kết cho CSS. Các HomeServletđược thiết lập như tôi welcome-fileweb.xml:

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

Servlet được khai báo và ánh xạ như sau trong 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>

Cập nhật 2 : Cuối cùng tôi đã tìm thấy sự cố - servlet của tôi đã được ánh xạ không chính xác. Rõ ràng khi đặt Servlet làm Servlet của bạn, <welcome-file>nó không thể có mẫu URL /, điều mà tôi thấy hơi lạ, vì điều đó không phải là đại diện cho thư mục gốc của trang web?

Ánh xạ mới như sau:

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

Cảm ơn bạn đã cập nhật 2, tôi đã đập đầu vào tường trong vài giờ để cố gắng tìm ra lý do tại sao css của tôi không tải. (đã có / làm chú thích).
kiwicomb123

Câu trả lời:


100

Tất cả các URL tương đối trong trang HTML được tạo bởi tệp JSP đều liên quan đến URL yêu cầu hiện tại (URL như bạn thấy trong thanh địa chỉ trình duyệt) chứ không phải vị trí của tệp JSP ở phía máy chủ như bạn mong đợi. Cụ thể là trình duyệt web phải tải xuống từng tài nguyên đó theo URL, chứ không phải trình duyệt web phải đưa chúng vào đĩa bằng cách nào đó.

Ngoài việc thay đổi các URL tương đối để làm cho chúng tương đối với URL của servlet thay vì vị trí của tệp JSP, một cách khác để khắc phục sự cố này là đặt chúng tương đối với miền gốc (tức là bắt đầu bằng a /). Bằng cách này, bạn không cần phải lo lắng về việc thay đổi các đường dẫn tương đối một lần nữa khi bạn thay đổi URL của servlet.

<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>

Tuy nhiên, bạn có thể không muốn mã hóa đường dẫn ngữ cảnh. Rất hợp lí. Bạn có thể lấy đường dẫn ngữ cảnh trong EL bằng cách ${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ó thể dễ dàng rút ngắn <c:set var="root" value="${pageContext.request.contextPath}" />và sử dụng như ${root}ở những nơi khác)

Hoặc, nếu bạn không sợ XML không đọc được và đánh dấu cú pháp XML bị hỏng, hãy sử dụng 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>

Dù bằng cách nào, điều này cũng khá phức tạp nếu bạn có nhiều URL tương đối. Đối với điều đó, bạn có thể sử dụng <base>thẻ. Tất cả các URL tương đối sẽ ngay lập tức trở thành tương đối với nó. Nó có tuy nhiên để bắt đầu với chương trình ( http://, https://, vv). Không có cách nào rõ ràng để có được đường dẫn ngữ cảnh cơ sở trong EL đơn giản, vì vậy chúng tôi cần một chút trợ giúp của JSTL ở đây.

<%@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>

Điều này lần lượt (một lần nữa) có một số cảnh báo. Neo (của #identifierURL) cũng sẽ tương đối với đường dẫn cơ sở! Thay vào đó, bạn muốn đặt nó liên quan đến URL yêu cầu (URI). Vì vậy, hãy thay đổi như

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

đến

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

Mỗi cách đều có ưu và nhược điểm riêng. Bạn phải chọn cái nào. Ít nhất, bây giờ bạn nên hiểu vấn đề này gây ra như thế nào và cách giải quyết nó :)

Xem thêm:


Tôi thực sự hy vọng rằng điều này sẽ hoạt động đúng như ý muốn, nhưng trình duyệt vẫn không thể định vị các tệp. Tôi đã thêm một số thông tin khác vào câu hỏi của mình (cấu trúc ứng dụng và một số thông tin chung khác). Cảm ơn đã giúp đỡ!
Brian DiCasa

3
Bạn đã ánh xạ servlet trên /(mùi, mùi;)). Vì vậy, nó cũng chặn các tệp CSS (thực tế là mọi yêu cầu HTTP). Nó có xử lý chúng một cách chính xác không? Tức là bạn có thể truy cập trực tiếp tệp CSS trong trình duyệt web của localhost: 8080 / context / styles / default.css ?
BalusC

Không phải khi nó được ánh xạ tới "/". Tôi có thể khi nó được ánh xạ là "/ HomeServlet".
Brian DiCasa

Tôi không chắc tại sao ban đầu bạn lại ánh xạ nó /*, nhưng nếu bạn đang cố gắng tạo ra một loại bộ điều khiển phía trước, tôi khuyên bạn nên tự mình vượt qua câu trả lời này và có thể cũng là câu trả lời này .
BalusC

@BalusC - Trong đoạn đầu tiên của bạn, nơi bạn nói "Cụ thể là trình duyệt web phải tải xuống các tài nguyên đó riêng lẻ theo URL, chứ không phải máy chủ web phải đưa chúng từ đĩa bằng cách nào đó." Chúng ta có thể kiểm tra thực tế rằng trình duyệt có trách nhiệm tìm nạp tài nguyên chứ không phải máy chủ web không? Nếu bạn có thể chỉ cho tôi một số ví dụ thực tế hoặc hướng dẫn sẽ rất tuyệt!
Abhishek Aggarwal


2

Bạn phải phân tích đầu ra HTML thực tế, để biết gợi ý.

Bằng cách đưa ra đường dẫn như thế này có nghĩa là "từ vị trí hiện tại", mặt khác nếu bạn bắt đầu bằng một đường /dẫn có nghĩa là "từ ngữ cảnh".


Tôi không chắc bạn muốn nói gì. Nếu tôi thay đổi liên kết css thành này:
Brian DiCasa,

Ý tôi là bạn có thể xem nguồn HTML từ trình duyệt của mình, để tìm hiểu xem đường dẫn có đúng hay không. Nếu không, bạn cần phải làm gì để sửa lại.
Adeel Ansari

Tôi đang xem nguồn và những gì xuất hiện cho các thẻ liên kết của tôi là những gì tôi đã đăng trong câu hỏi của mình. Tôi đoán rằng tôi không chắc tại sao nếu tôi liên kết trực tiếp đến jsp của mình thì các tệp có thể được tìm thấy và nếu tôi chuyển tiếp, chúng không thể được tìm thấy? Tôi có thể lưu trữ hình ảnh của mình ở đâu để có thể tìm thấy chúng từ bất kỳ vị trí nào trong ứng dụng web?
Brian DiCasa

Được rồi, đó là vì của bạn index.jspở cùng vị trí / cấp độ với thư mục stylesvà của bạn images. Do đó, khi bạn trực tiếp sử dụng index.jspnhư một tệp chào mừng, mọi thứ xuất hiện như một sự quyến rũ. Mặt khác, khi bạn chuyển tiếp cùng một tài nguyên thông qua servlet, vấn đề không còn giống như vậy nữa. [còn tiếp tục ...]
Adeel Ansari

@Brian D.: ... Để hướng một yêu cầu đến một servlet cụ thể mà chúng tôi không coi là đường dẫn, chúng tôi sử dụng ánh xạ servlet. Bây giờ, chúng ta phải hiểu context pathở đây. Như bạn đã thấy trong tài liệu /có một số ý nghĩa cụ thể khi được sử dụng trong đường dẫn mà chúng tôi muốn chuyển tiếp yêu cầu hoặc chuyển hướng yêu cầu. Nếu không có dấu gạch chéo, nó sẽ được lấy từ vị trí hiện tại, không phải từ đường dẫn ngữ cảnh. Tôi hy vọng bạn đang có được tôi bây giờ.
Adeel Ansari

0

Trang chào mừng của bạn được đặt là Servlet đó. Vì vậy, tất cả css, đường dẫn hình ảnh nên được cung cấp liên quan đến DIR của servlet đó. đó là một ý tưởng tồi! tại sao bạn cần servlet làm trang chủ? đặt .jsp làm trang chỉ mục và chuyển hướng đến bất kỳ trang nào từ đó?

bạn đang cố gắng điền bất kỳ trường nào từ db, đó là lý do tại sao bạn đang sử dụng servlet?


4
Sử dụng một servlet làm bộ điều khiển phía trước (MVC) chắc chắn không phải là một ý tưởng tồi.
BalusC

0

Nếu bạn đang sử dụng Spring MVC, thì bạn cần phải khai báo servlet hành động mặc định cho nội dung tĩnh. Thêm các mục sau vào spring-action-servlet.xml. Nó đã làm việc cho tôi.

LƯU Ý: giữ tất cả nội dung tĩnh bên ngoài 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

Đối với bản cập nhật của bạn, tôi đã bối rối vì lý do đằng sau. Dug sâu hơn một chút và tìm thấy viên ngọc này:

  • yourite.com trở thành trang web của bạn.com/
  • yourite.com/ là một thư mục, vì vậy danh sách tệp tin chào mừng sẽ được quét
  • yourite.com/CMS là tệp tin chào mừng đầu tiên ("CMS" trong danh sách tệp tin chào mừng) và có một ánh xạ / CMS tới servlet MyCMS, để servlet đó được truy cập.

Nguồn: http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage

Vì vậy, ánh xạ sau đó có ý nghĩa.

Và bây giờ người ta có thể thoải mái sử dụng $ {pageContext.request.contextPath} / path / as src / href cho các liên kết tương đối!


0

câu trả lời ngắn gọn - thêm dòng sau vào jsp sẽ xác định base
cơ sở href = "/ {root of your application} /"


0

Mã dưới đây làm việc cho tôi.

thay vì sử dụng <% @ include file = "styles / default.css"%>


0

Bạn cũng có thể thử cái này. Bởi vì điều này làm việc cho tôi và nó đơn giản.

<style>
    <%@ include file="/css/style.css" %>
</style>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.