首页 > 解决方案 > 从 jsp 页面调用时找不到 HTTPServlet

问题描述

我主要从事基于 jersey 的 web 服务,第一次尝试 jsp + servlet 组合,并在一些事情上苦苦挣扎

这是tomcat webapp文件夹中的目录结构:

├── 403.jsp
├── META-INF
│   ├── MANIFEST.MF
│   ├── maven
│   │   └── com.csx.cti             <-----package
│   │       └── cti_dwnld           <-----project name
│   │           ├── pom.properties
│   │           └── pom.xml
│   └── war-tracker
├── WEB-INF
│   ├── classes
│   │   └── com
│   │       └── csx
│   │           └── cti
│   │               └── servlet
│   │                   └── DownloadServlet.class.   <----- servlet in question
│   ├── lib
│   │   ├── javax.servlet-api-3.0.1.jar
│   │   └── javax.ws.rs-api-2.1.1.jar
│   └── web.xml
├── error.jsp
├── index.jsp
├── login.jsp
└── logout.jsp

web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>Login Demo Using j_security_check</display-name>
    <!--Defines Security Constraint -->
    <security-constraint>
        <display-name>JSP Demo Constraint</display-name>
        <web-resource-collection>
            <web-resource-name>cp</web-resource-name>
            <description/>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>file-user</role-name>
        </auth-constraint>
    </security-constraint>
    <!--Defines Login Config -->
    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>cti file user realm</realm-name>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/403.jsp</form-error-page>
        </form-login-config>
    </login-config>
    <!--Defines Security Role -->
    <security-role>
        <description/>
        <role-name>file-user</role-name>
    </security-role>
    <error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>
</web-app>

下载Servlet


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {

//    private static final long serialVersionUID = 1L;

    private static final long serialVersionUID = 102831973239L;

    private static final int BYTES_DOWNLOAD = 1024;

    public DownloadServlet() {
        super();
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

        // skip url params and use hardcode for now
        response.setContentType("text/plain");
        response.setHeader("Content-Disposition", "attachment;filename=sample.txt");
        ServletContext ctx = getServletContext();
        InputStream is = ctx.getResourceAsStream("sample.txt");

        int read = 0;
        byte[] bytes = new byte[BYTES_DOWNLOAD];
        OutputStream os = response.getOutputStream();

        while ((read = is.read(bytes)) != -1) {
            os.write(bytes, 0, read);
        }
        os.flush();
        os.close();
    }


    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }
}

index.jsp(应该调用下载 servlet 的部分)

      // l_Files is list of all files in the folder
      for (int a = 0; a < l_Files.size(); a++) {
          // have tried:
          // href='./download'
          // href='/download'
          // href='download'
          // href='/cti_dwnld/download'
          out.println("<a href='/download?file=sample.txt'>" + l_Files.elementAt(a).toString() + "</a><br>");
      }

我想要达到的目标:

本质上显示文件列表并将它们传递给下载 servlet 以触发下载。到目前为止,我能够让用户成功登录,但是当a标签被触发时,我最终得到 404

如下

也尝试了这个详尽的答案:

Servlet 返回“HTTP 状态 404 请求的资源 (/servlet) 不可用”

我尝试使用 servlet 直接访问浏览器,但仍然是 404。此外,href参数正在发送到~:8080/download它应该发送的时间~:8080/cti_dwnld/download/

任何指针/帮助表示赞赏!

标签: javajsptomcatservlets

解决方案


在<a> 标签中使用 servlet url-pattern 时无需使用前导 '\' 。如果您想使用 url-pattern /download调用您的 DownloadServlet,下面的代码可以正常工作

<a href='download?file=sample.txt'>Download</a>

请参阅下面的完整文件,其中文件名是动态的,我们通过用户请求从 JSP 获得,

小服务程序代码

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import jakarta.servlet.ServletContext;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {

    private static final long serialVersionUID = 102831973239L;
    private static final int BYTES_DOWNLOAD = 1024;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        
        /**
         * Get name of the file dynamically from user request
         */
        String fileName = request.getParameter("file");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        ServletContext ctx = getServletContext();
        
        /**
         * Open stream to read the file, here file will be expected to be in root directory of the project
         */
        InputStream is = ctx.getResourceAsStream(fileName);
        int read = 0;
        byte[] bytes = new byte[BYTES_DOWNLOAD];
        OutputStream os = response.getOutputStream();

        while ((read = is.read(bytes)) != -1) {
            os.write(bytes, 0, read);
        }
        os.flush();
        os.close();
    }

}

JSP代码

<%@ page import="java.util.Vector"%>
<!DOCTYPE html>
<html>
<head>
<title>Index Page</title>
</head>
<body>

    <%
    //TODO: Please replace below code with your actual code to populate file names dynamically.
    Vector<String> l_Files = new Vector<String>();
    l_Files.add("sample1.txt");
    l_Files.add("sample2.txt");
    l_Files.add("sample3.txt");
    l_Files.add("sample4.txt");
    l_Files.add("sample5.txt");

    // l_Files is list of all files in the folder
    for (int a = 0; a < l_Files.size(); a++) { %>
         <a href='download?file=<%=l_Files.elementAt(a).toString() %>'><%=l_Files.elementAt(a).toString() %></a><br>
    <%
    }
    %>
</body>
</html>

我在这里使用了您共享的相同 web.xml 文件。

下面是目录结构,

在此处输入图像描述

操作系统版本:Windows 10 家庭版

Tomcat 版本:apache-tomcat-10.0.12

浏览器版本:Firefox 93.0(64 位)


推荐阅读