在获得可行的解决方案之后,我决定更进一步地使用代码,并想出了这个:
package hu.flux.helper;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import javax.servlet.jsp.JspWriter;
import com.objectmentor.library.web.framework.mocks.*;
// A holder for formatting data
public class NameAndAddress
{
public String firstName;
public String middleName;
public String lastName;
public String address1;
public String address2;
public String city;
public String state;
public String zip;
public String FormattedString()
{
String formattedString = "<PRE>\n" + firstName;
// Add the middle name only if it contains data.
if ((middleName != null) && (middleName.length() > 0))
{formattedString += " " + middleName;}
formattedString += " " + lastName + "\n";
formattedString += address1 + "\n";
if ((address2 != null) && (address2.length() > 0))
formattedString += address2 + "\n";
formattedString += city + ", " + state + " " + zip + "\n</PRE>";
return formattedString;
}
// Print out the name and address.
public void print(Writer writer) {
long now = System.currentTimeMillis();
System.out.println("--Entering-- " + now);
PrintWriter p = new PrintWriter (writer);
p.write(this.FormattedString());
now = System.currentTimeMillis();
System.out.println("--Exiting-- " + now);
}
/*
public void print(JspWriter out) throws java.io.IOException
{ print (new PrintWriter(out)); }
*/
@SuppressWarnings("deprecation")
public static void main (String args[])
{
NameAndAddress naa = new NameAndAddress();
naa.firstName = "Brian";
naa.middleName = "Matthew";
naa.lastName = "Kessler";
naa.address1 = "Tatra u. 15/b V/3";
naa.city = "Budapest";
naa.state = "Hungary";
naa.zip = "HU-1136";
System.out.println("\nTesting PrintWriter...");
PrintWriter p = null;
try { p = new PrintWriter("d:/temp/pwriter_text.txt"); }
catch (FileNotFoundException e)
{
System.err.print ("Can not create new PrintWriter: " + e);
e.printStackTrace();
}
naa.print(p);
p.flush();
FileInputStream fis;
DataInputStream dis;
try
{
fis = new FileInputStream("d:/temp/pwriter_text.txt");
dis = new DataInputStream (fis);
while (dis.available() != 0)
{ System.out.println(dis.readLine()); }
dis.close();
}
catch (Exception e)
{
System.err.println("File input error");
}
System.out.println("\nTested PrintWriter...");
System.out.println("---------------------");
System.out.println("\nTesting JSPWriter...");
JspWriter j = null;
naa.print(j);
System.out.print("\nTested JSPWriter...");
System.out.println("---------------------");
System.out.println("\nTesting MockJspWriter");
MockJspWriter m = null;
m = new MockJspWriter(255, true);
naa.print(m);
System.out.print(m.getContent());
System.out.println("\nTested MockJSPWriter...");
System.out.println("---------------------");
}
}
我希望print()方法能同时捕获JspWriter和PrintWriter。
虽然这个解决方案适用于PrintWriter,但当我尝试将其作为控制台应用程序运行时,我得到了这个输出:
Testing PrintWriter...
--Entering--
--Exiting--
<PRE>
Brian Matthew Kessler
Tatra u. 15/b V/3
Budapest, Hungary HU-1136
</PRE>
Tested PrintWriter...
---------------------
Testing JSPWriter...
--Entering--
Exception in thread "main" java.lang.NullPointerException
at hu.flux.helper.NameAndAddress.print(NameAndAddress.java:46)
at hu.flux.helper.NameAndAddress.main(NameAndAddress.java:101)
但是,如果我尝试从JSP访问print(Writer writer),我会得到一个不同的错误:
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
org.apache.jasper.JasperException: javax.servlet.ServletException: java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:492)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:407)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
javax.servlet.ServletException: java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:898)
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:827)
org.apache.jsp.Address_jsp._jspService(Address_jsp.java:92)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
org.apache.jsp.Address_jsp._jspService(Address_jsp.java:81)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.2 logs.
Apache Tomcat/7.0.2
从JSP调用时,我可以通过添加以下代码来调用JspWriter的类:
public void print(JspWriter out) throws java.io.IOException
{ print (new PrintWriter(out)); }
但是,当尝试从控制台应用程序使用JspWriter时(用于测试 - 我认为任何人都不需要在控制台中使用JspWriter!),上述控制台错误将移至此功能。
如果print(JspWriter out)可以解决JSP的问题,那么它是否也应该解决控制台应用程序的问题?
此外,如果JspWriter是一个Writer对象,它不应该总是一个Writer对象,无论是从控制台还是JSP调用它?
答案 0 :(得分:3)
此异常表示在将print(JspWriter)
更改为print(Object)
后,您的JSP代码尚未重新编译,因此它仍会尝试调用print(JspWriter)
而无法找到它。
为了强制重新编译,您可以修改JSP页面。
答案 1 :(得分:1)
这是因为Java编译器试图在JspWriter对象上找到PrintWriter.print方法。虽然它有一个print方法,但是这个方法不匹配,因为它来自另一个类。 Java不支持鸭子打字,并竭尽全力阻止它。
在编程逻辑中使用异常也被认为是不好的做法。
你必须做像
这样的事情 try
{
if (out instanceof PrintWriter) {
((PrintWriter) out).print(this.formattedString());
} else if (out instanceof JspWriter) {
((JspWriter) out).print(this.formattedString());
} else {
throw new IllegalArgumentException("NameAndAddress.print expected ether a PrintWriter or a JspWriter but received a " + out.getClass().getName());
}
catch (Exception ex)
{ System.err.println("\"out\" is not a printable type: " + ex); }
BTW:Java中的方法应按惯例以小写字母开头。
答案 2 :(得分:1)
您发布的内容应该有效,因为PrintWriter
和JspWriter
都是Writer
的子类(当然两者都是Object
的子类)。您的测试代码或环境似乎都有问题。
也许您可以尝试一个简化的示例,看看它是否有效,然后从那里开始构建。我可以建议从这里开始:
public class Test
{
public void print(Writer writer) throws IOException
{
if (writer == null)
System.out.println("Null writer");
else
{
writer.write("hello");
writer.flush();
}
}
public static void main(String args[]) throws IOException
{
Test test = new Test();
System.out.print("Testing PrintWriter...");
PrintWriter p = new PrintWriter("d:/temp/pwriter_text.txt");
test.print(p);
System.out.print("Tested PrintWriter...");
System.out.print("Testing JspWriter...");
JspWriter j = null;
test.print(j);
System.out.print("Tested JspWriter...");
}
}
这应该编译并运行。第二次调用test.print()
时,传入的JspWriter
将为null
,但您不应该获得任何NoSuchMethodError
。如果这样做,请获取代码并从servlet / JSP页面进行测试。希望这可以帮助您找到问题。
答案 3 :(得分:0)
JspWriter不是PrintWriter
您可以将原始作者包装在这样的打印作者中:
if (out instance of Writer) {
PrintWriter p = new PrintWriter((Writer) out));
p.print...
}
答案 4 :(得分:0)
嗯,你通过转换为PrintWriter
开始你的方法,所以也许jvm为你优化了方法。由于JspWriter
不是PrintWriter
的子类,因此最好的办法是编写两种方法:
public void print(JspWriter out)
{
if (out == null) return;
try {
out.print(this.FormattedString());
} Except (IOException e) {
// handle error
}
}
public void print(PrintWriter out)
{
if (out == null) return;
try {
out.print(this.FormattedString());
} Except (IOException e) {
// handle error
}
}
如果只有JspWriter和PrintWriter有一个共同的界面......叹息。
答案 5 :(得分:0)
您的print()将Object强制转换为PrintWriter。但是当你传入一个不是PrintWriter的JspWriter时,转换会失败。
但是,PrintWriter和JspWriter都是Writer的后代。您是否可以将print()
方法更改为接受Writer而不是Object,然后在print()
中使用Writer.write()方法?这对两个类都很常见。
此:
public void print(Writer writer) {
try {
writer.write(this.FormattedString());
} catch (IOException e) {
// log something...
}
}