我是一名应用程序程序员,正在开发我的第一个 JSF 2.0 网站,并且承认我对 JSF 的了解还不够多。几个月来我一直在苦苦寻找文档,特别感谢这些论坛,我才没有陷入困境。网站的大部分内容已完成并正在运行,此处使用的支持 bean 在其他地方使用也没有问题。
我有一个序列化的搜索条件对象,需要通过 servlet 从 applet 提交到支持 bean。然后,支持 bean 方法处理搜索条件数据并将其应用于数据库中保存的产品列表,然后在新的 JSF 页面中显示排名产品的列表。
所有打开包含正确数据的结果页面的尝试都失败了。导航案例“return“process_MainSearchResult”;”没有在支持 bean 中执行任何操作(请参阅进一步的支持 bean 代码和 faces-config 条目)。我尝试使用 appletContext.showDocument (见下文)从 applet 打开结果页面,但新页面没有搜索条件对象传递到的支持 bean,因此没有正确的数据。
注意,在小程序中的setRequestMethod上设置POST没有任何效果;它总是使用服务。如果 setDoInput 和 setDoOutput 未设置为 true 并且响应从 servlet 发送回 applet,则不会发送提交的对象并且不会发生任何情况。我怀疑这是我问题的核心,但以任何方式改变它都会阻止序列化对象成功提交。
就目前情况而言,对象已成功发送到支持 bean,但新页面不会加载正确的数据(使用 applet 中的 showDocument,而不是 servlet 中的重定向)。有没有办法在新网页上设置原始的支持 bean 或者我这样做都是错误的?
Web服务器是Glassfish 3.x,IDE是Netbeans 7.0.1,系统是WinXP。 支持 bean 类是“ProductSelection”; servlet 类是“CriteriaServlet”。
小程序“提交搜索条件”按钮代码:
private void jButton8ActionPerformed(java.awt.event.ActionEvent evt)
{
criteriaModel.loadCodeBase();
int choice = JOptionPane.showConfirmDialog(this,
"Are you sure you want to submit your search criteria and exit the \"Customise Search Criteria\" web page?",
"Confirm Submit",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (choice == 0)
{
try
{
URL url;
url = new URL(criteriaModel.getCodeBase(), "CriteriaServlet");
System.out.println("Servlet address is: " + url);
// Get the search criteria object.
Object searchSubmitObject = criteriaModel.getObjectSlideData();
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type","application/x-java-serialized-object");
ObjectOutputStream out = new ObjectOutputStream(connection.getOutputStream());
out.writeObject(searchSubmitObject);
out.flush();
out.close();
out.close();
System.out.println("Object Written");
// If this and the corresponding servlet response code is removed
// then the searchSubmitObject fails to be sent.
ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
String response = (String)in.readObject();
System.out.println(response);
in.close();
}
catch (MalformedURLException ex)
{
JOptionPane.showMessageDialog(jPanel8, "Submit criteria file Malformed URL."
+ ex.toString());
System.out.println("MalformedURLException occurred");
Logger.getLogger(CriteriaInterfaceView.class.getName()).log(Level.SEVERE, null, ex);
}
catch (Exception e)
{
System.out.println("Submit criteria file ERROR exception: " + e.toString());
JOptionPane.showMessageDialog(jPanel8, "Submit criteria file ERROR exception:"
+ e.toString());
}
}
// This opens a new page but with a new backing bean with the wrong data.
try
{
appletContext.showDocument(new URL(criteriaModel.getCodeBase()+"MainSearchResult.xhtml"),"_SELF");
}
catch (MalformedURLException ex)
{
Logger.getLogger(CriteriaInterfaceView.class.getName()).log(Level.SEVERE, null, ex);
}
}
我尝试使用redirect(url)在servlet中进行重定向,但没有成功:
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
System.out.println("service(ServletRequest req, ServletResponse res)");
res.setContentType("application/x-java-serialized-object");
try
{
ObjectInputStream in = new ObjectInputStream(req.getInputStream());
slideData = (MultipleSlideDataObject2)in.readObject();
in.close();
if(slideData != null)
{
System.out.println("Serial number of submitted slide series is: " + slideData.getSerialNumber());
}
String temp = "Criteria file Recieved";
ObjectOutputStream outputToApplet = new ObjectOutputStream(res.getOutputStream());
outputToApplet.writeObject(temp);
outputToApplet.flush();
outputToApplet.close();
}
catch (ClassNotFoundException ex)
{
Logger.getLogger(CriteriaServlet.class.getName()).log(Level.SEVERE, null, ex);
}
FacesContext facesContext = FacesUtil.getFacesContext(req, res);
// Get the backing bean.
ProductSelection productSelection = (ProductSelection) facesContext.getApplication().evaluateExpressionGet(facesContext, "#{productSelection}", ProductSelection.class);
productSelection.submitSearchCriteriaFile(slideData);
// This throws an java.lang.IllegalStateException error.
try
{
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext extContext = context.getExternalContext();
String url = extContext.encodeActionURL(context.getApplication().getViewHandler().getActionURL(context, "/MainSearchResult.xhtml"));
extContext.redirect(url);
}
catch (IOException e)
{
throw new FacesException(e);
}
给出以下错误,因为我怀疑当前响应已经提交:
WARNING: StandardWrapperValve[CriteriaServlet]: PWC1406: Servlet.service() for servlet CriteriaServlet threw exception java.lang.IllegalStateException at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:522) at com.sun.faces.context.ExternalContextImpl.redirect(ExternalContextImpl.java:572) at searchselection.CriteriaServlet.service(CriteriaServlet.java:217) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) at java.lang.Thread.run(Thread.java:619)
返回“process_MainSearchResult”;在支持 bean 中不起作用:
public String submitSearchCriteriaFile(MultipleSlideDataObject2 slideData) throws IOException
{
System.out.println("Recieved slide series with serial number: " + slideData.getSerialNumber());
// If there is no slide data then...
if (slideData == null)
{
return "process_MainSearchResultFailed";
}
else
{
rankProducts(slideData);
}
rowStart = 0;
currentStartPage = 0;
currentPageIndex = 0;
calculateNumberPages();
SetupPaginationValues();
// Ignores this...
return "process_MainSearchResult";
}
Faces-config.xml 条目:
<navigation-rule>
<navigation-case>
<from-outcome>process_MainSearchResult</from-outcome>
<to-view-id>/MainSearchResult.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
我也在支持 bean 中尝试过强制重定向:
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
try
{
response.sendRedirect("MainSearchResult.xhtml");
//response.redirect("http://localhost:8080/SearchEngineServer/faces/MainSearchResult.xhtml");
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
还有支持 bean 中的这个:
redirectToPage("/MainSearchResult.xhtml");
调用此方法:
private void redirectToPage(String toUrl)
{
try
{
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extContext = ctx.getExternalContext();
String url = extContext.encodeActionURL(ctx.getApplication().getViewHandler().getActionURL(ctx, toUrl));
extContext.redirect(url);
}
catch (IOException e)
{
throw new FacesException(e);
}
}
所有这些都会给出与上面给出的 servlet 示例相同的 java.lang.IllegalStateException 错误。重定向的文档说明了这一点:
IllegalStateException - if, in a portlet environment, the current response object is a RenderResponse instead of an ActionResponse IllegalStateException - if, in a servlet environment, the current response has already been committed
最佳答案
重定向失败,因为您在 servlet 中执行重定向之前已经编写并提交了响应。您似乎认为可以对单个请求发送多个响应。这实际上是不正确的。每个 HTTP 请求只能发回一个 HTTP 响应,不能发送更多。删除以 FacesUtil#getFacesContext()
开头的整个 block 线。它不属于那里。
我不确定该 servlet 在做什么,它似乎没有做任何有用的事情,但您应该让小程序本身通过 AppletContext#showDocument()
执行“重定向”调用 servlet 后。您可以按照通常的方式将搜索条件(您尝试序列化的 Java 对象实例的属性)作为 GET 请求参数传递给 JSF 页面/bean,并让 JSF 通过 @ManagedProperty
来收集它。或<f:viewParam>
并通过 @PostConstruct
处理它或<f:event>
.
例如
String query = "?param1=" + URLEncoder.encode(param1, "UTF-8")
+ "¶m2=" + URLEncoder.encode(param2, "UTF-8")
+ "¶m3=" + URLEncoder.encode(param3, "UTF-8");
getAppletContext().showDocument(new URL(getCodeBase(), "MainSearchResult.xhtml" + query), "_SELF");
与两者之一
@ManagedBean
@RequestScoped
public class ProductSelection {
@ManagedProperty("#{param.param1}")
private String param1;
@ManagedProperty("#{param.param2}")
private String param2;
@ManagedProperty("#{param.param3}")
private String param3;
@PostConstruct
public void init() {
// Do your business job based on the submitted request parameters.
}
// ...
}
或
<f:metadata>
<f:viewParam name="param1" value="#{productSelection.param1}" />
<f:viewParam name="param2" value="#{productSelection.param2}" />
<f:viewParam name="param3" value="#{productSelection.param3}" />
<f:event type="preRenderView" listener="#{productSelection.init}" />
</f:metadata>
当以这种方式实现时,我认为笨拙的 servlet 步骤以及所有 Java 序列化是完全多余的。你可以直接删除它。此外,通过这种方式,您最终会得到一个很好的可添加书签、可重用且可搜索机器人索引的页面,该页面可以独立于小程序/servlet 打开。
另请参阅:
关于java - 如何通过 servlet 将序列化对象从 Applet 提交到支持 bean,然后打开结果 JSF 页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12256324/