是否可以在单个 servlet 中包含两种内容类型?

Is it possible to have two content types in single servlet?

我创建了如下所示的 servlet:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class otpcheck extends HttpServlet {


/**
 * Handles the HTTP <code>POST</code> method.
 *
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    PrintWriter out =response.getWriter();
    Crypting c=new Crypting();
    BufferedImage imgKey;
    BufferedImage imgEnc;
    imgKey = ImageIO.read(new File("E:/Key.png"));
    imgEnc=ImageIO.read(new File("E:/E.png"));

    response.setContentType("text/html");
    out.println(
"<!DOCTYPE html>\n" +
"<html>\n" +
"    <head>\n" +
"      \n" +
"        <title>Online Banking</title>\n" +
"        \n" +
"        <link rel=\"stylesheet\" href=\"newcss.css\">\n" +
"    </head>\n" +
"<!DOCTYPE html>\n" +
"\n" +
"        <div class=\"wrapper\">\n" +
"            \n" +
"        <div class=\"header\">\n" +
"            <img src=\"header_1.jpg\" height=\"100%\" width=\"100%\"/>\n" +
"            </div>\n" +
"            <div class=\"navbar\">\n" +
"                \n" +
"            <ul>\n" +
"            <li><a href=\"index.jsp\">Home</a></li>\n" +
"            <li><a href=\"features.jsp\">Features</a></li>\n" +
"            <li id=\"last\"><a href=\"contact.jsp\">Contact Us</a></li>\n"     +
"            </ul>\n" +
"            </div>" +
"\n" +
"<div class='content'>\n" +
"<div class=\"user_login\">");
    out.println("<p>Scan the QR Image to get OTP</p>");
     BufferedImage imgDec=Crypting.decryptImage(imgKey,imgEnc);
    response.setContentType("image/png");
    OutputStream os=response.getOutputStream();
    ImageIO.write(imgDec,"png",os);
    out.println("<form action=\"otpvalidate\" method=\"POST\"    enctype=\"multipart / form - data\">Enter OTP:<input type=\"password\" name=\"otp\"/>\n<input type=\"submit\" value=\"SUBMIT\" name=\"submit\" /></form >");
    out.println("</div>\n" +
"</div>\n" +
"<!DOCTYPE html>\n" +
"        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-    8\">\n" +
"        <div class=\"footer\">\n" +
"<ul>\n" +
"                   \n" +
"                   <div class=\"footer_content\">\n" +
"                   <li><a href=\"features.jsp\">Features </a></li>\n" +
"                   <li><a href=\"contact.jsp\"> Contact</a></li>\n" +
"                 \n" +
"                   <li><a href=\"safeonlinebanking.jsp\">Safe online Banking tips</a></li>\n" +
"                   \n" +
"                   <li style=\"padding-left:450px;\">Copyright&copy;2017   onlinebanking.com</li>\n" +
"                   \n" +
"                   </div>\n" +
"                   </ul>                    \n" +
"       \n" +
"    \n" +
"    \n" +
" </div>\n" +
"           </div> \n" +
"    </body>\n" +
"</html>\n" +
"\n" +
"</html>");

}


}

由于图像是动态生成的(即解密的)我无法将其保存为 filesystem.So 中的文件 我使用 OutputStreamresponse.setContentType("image/png") 来显示图像。 但我还需要使用 html.So 生成输入和按钮 我使用另一个 response.setContentType("text/html") 来显示 html。

我的问题是我收到错误 java.lang.IllegalStateException: getWriter() has already been called for this response。因此内容类型响应相互冲突。

请帮我解决这个错误!!!

在 HTTP 协议中您访问资源。每个资源都有自己的类型。

在您的示例中,您至少有 3 个资源,一个用于 HTML 页面,一个用于 key.png,一个用于 e.png

怎么办?

您可以让您的 servlet 只为您的 HTML 页面提供服务,并且在 HTML 页面中您可以让图像标签指向图像资源

<html>
...
<img src="http://miserver/key.png">
<img src="http://miserver/e.png">

对于图像,您可以将它们放在 war 文件中,服务器会提供这些图像。

但是如果您的图像像数据库一样存储在 war 之外,您可以创建其他 servlet 来为您的图像提供服务。在 IMG 标签的 SRC 属性 中,你放置了那个 servlet 的 URL。

您可以从同一个 Servlet 提供 HTML 和 PNG,前提是:

  • 对于每个请求,您只提供其中一个,而不是同时提供两个
  • 可以从必须提供哪些内容的请求中推断出来
  • 您相应地将 servlet 映射到所有需要的 URL 或模式

例如,如果您必须提供 HTML 或 PNG 内容,您可以将 servlet 映射到 /onlinebanking.html/onlinebanking.png 并从请求 URI 的扩展中推断出来。或者仅映射到 /onlinebanking 并始终发送 HTML 除非使用例如/onlinebanking?content=image 即评估查询字符串或查询参数以做出决定。

首先,感谢大家 contributions.I 找到了答案并使其发挥作用。

我为 return 创建了一个 servlet image.Then 我创建了一个 jsp 文件来通过给 URL 作为 <img src="${pageContext.request.contextPath}/otpcheck" /> 来获取该图像。 而且效果很好。 这是代码。

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class otpcheck extends HttpServlet {



@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {


    Crypting c=new Crypting();
    BufferedImage imgKey;
    BufferedImage imgEnc;
    imgKey = ImageIO.read(new File("E:/Key.png"));
    imgEnc=ImageIO.read(new File("E:/upload/E.png"));
     BufferedImage imgDec=Crypting.decryptImage(imgKey,imgEnc);
    response.setContentType("image/png");
    OutputStream os=response.getOutputStream();
    ImageIO.write(imgDec,"png",os);
}
}

而jsp如下:

<img src="${pageContext.request.contextPath}/otpcheck" />
    <form action="otpvalidate" method="POST" enctype="multipart/form-data">
        Enter OTP:<input type="password" name="otp"/><input type="submit" value="SUBMIT" name="submit" />
    </form>

我参考了 BalusC.That 的代码工作方式给出的一些答案。