如何从一个Applet提交序列化对象,通过一个servlet,到后台bean,然后打开一个结果JSF

2019-09-28 11:14发布

我是一名应用程序员做我的第一个JSF 2.0的网站,并坦白地说,我不知道像我应该对JSF。 我一直在pooring文件数月,这要归功于特别是这些论坛,都没有得到坚持了这一点。 该网站的大部分完成,工作,这里使用的支持bean在别处使用没有问题。

我有一个序列化的搜索条件对象需要从一个小程序到后台bean提交,通过一个servlet。 backing bean的方法,然后处理搜索标准的数据并将其应用于产品列表,在数据库中保存,然后显示在一个新的JSF页面排名的产品列表。

所有试图打开一个搜索结果页用正确的数据都失败了。 导航情况“回归‘process_MainSearchResult’;” 是不是做在后台bean什么(见进一步下跌支持bean代码和faces-config条目)。 我曾尝试使用appletContext.showDocument(见下文),但新的页面不具有的搜索条件的对象传递给后台bean,因此没有正确的数据来自小程序打开一个结果页面。

需要注意的是在applet的setRequestMethod设置POST没有影响; 它总是使用的服务。 如果setDoInput和setDoOutput未设置为true,从servlet发送回小应用程序的响应,然后提交的对象就不会发送,没有任何反应。 我怀疑这是在我的问题的核心,但改变它以任何方式被成功提交停止序列化对象。

既然这样,对象成功发送到后台bean,但新的页面不会用正确的数据加载(在小程序,而不是在servlet重定向使用showDocument)。 是否有设置原始支持bean的新网页上还是我做的这一切错误的方法吗?

Web服务器是Glassfish的3.x中,IDE是Netbeans的7.0.1,系统是WinXP的。 支撑类是“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);
    }
}   

我曾尝试使用重定向(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);
    }

提供了以下错误,因为我怀疑当前响应已经提交:

警告:StandardWrapperValve [CriteriaServlet]:PWC1406:Servlet.service()进行的servlet CriteriaServlet在com.sun.faces投掷异常java.lang.IllegalStateException在org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:522)。 context.ExternalContextImpl.redirect(ExternalContextImpl.java:572)在searchselection.CriteriaServlet.service(CriteriaServlet.java:217)在org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)在org.apache.catalina .core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)在org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641 )在com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)在com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)在org.apache.catalina.core.StandardHostValve。在org.apache.catalina调用(StandardHostValve.java:185)。 connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)在com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper。 Java的:165)在com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)在com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)在com.sun.grizzly.http .ProcessorTask.process(ProcessorTask.java:954)在com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)在com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)在融为一体。 sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)在com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)在com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)在com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)在com.sun.grizzly.SelectionKeyContextTask.call(SelectionK eyContextTask.java:57)在com.sun.grizzly.ContextTask.run(ContextTask.java:69)在com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:330)在com.sun.grizzly .util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:309)在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);
    }
}

所有给出相同java.lang.IllegalStateException误差由于上述的servlet实例。 对重定向状态的文档这样的:

 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 

Answer 1:

重定向失败,因为你已经写了,并承诺在servlet中执行重定向之前的响应。 你似乎认为你可以在单个请求发送多个响应。 其实,这是不正确的。 你可以只发送一个HTTP响应返回每个HTTP请求,而不是更多。 删除整个块开始于FacesUtil#getFacesContext()线。 它不属于那里。

我不知道那是什么servlet正在做什么,它似乎并没有做什么有用的东西,但你应该反而让小程序本身执行的“重定向” AppletContext#showDocument()已经调用的servlet之后。 您可以通过搜索标准的JSF页面/豆(在Java对象实例你想序列化的属性)的GET请求参数通常的方式,并有JSF通过收集其@ManagedProperty<f:viewParam>和通过处理它@PostConstruct<f:event>

String query = "?param1=" + URLEncoder.encode(param1, "UTF-8")
             + "&param2=" + URLEncoder.encode(param2, "UTF-8")
             + "&param3=" + 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>

当这种方式来实现它,那么我认为,与所有的Java序列化笨拙的servlet一步完全是多余的。 你可能只是将其删除。 此外,这样您最终可以独立于小应用程序/ servlet的打开一个很好的可收藏,可重复使用和searchbot编制索引的页面。

也可以看看:

  • ViewParam VS @ManagedProperty(值= “#{param.id}”)
  • 处理GET请求参数-在JSF 2.0通信


Answer 2:

BalusC的回答是少量的对象数据的合适的答案,但是,我提交给支持bean对象是2.2兆,不适合在URL编码。 进一步,我不希望别人添加为书签这个特定页面的多个属性可以被添加到在未来的搜索标准文件,这将使本书标记属性无效。

我使用的解决方案是什么高科技,但它的工作原理。 小应用程序提交的序列化对象到servlet,这反过来将其传送到后端bean,然后返回一个失败或成功消息发送到小程序。 如果提交成功,则小程序调用网页上的JavaScript函数加载结果页面。 这确保了正确的支持bean被保留。

最终的代码如下:

小程序“提交搜索条件”按钮的代码:

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 = new URL(criteriaModel.getCodeBase(), "CriteriaServlet");

             System.out.println("Servlet address is: " + url);

            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");

            ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
            String response = (String)in.readObject();
            System.out.println(response);
            in.close();

            if(response.equals("Failed"))
            {
                JOptionPane.showMessageDialog(jPanel8, "Submit Search criteria file to server failed.\n Try Again later.");
            }
            else
            {
                getAppletContext().showDocument(new URL("javascript:openResultsPage()"));
            }
         } 
         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());
         }
     }         
}      

在servlet:

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
    System.out.println("service(ServletRequest req, ServletResponse res)");

    res.setContentType("text/plain");

    try
    {
        ObjectInputStream in = new ObjectInputStream(req.getInputStream());
        slideData = (MultipleSlideDataObject2)in.readObject();
        in.close();

        String reply = "Failed";

        if(slideData != null)
        {
            System.out.println("Serial number of submitted slide series is: " + slideData.getSerialNumber());

            FacesContext facesContext = FacesUtil.getFacesContext(req, res);
            ProductSelection productSelection = (ProductSelection) facesContext.getApplication().evaluateExpressionGet(facesContext, "#{productSelection}", ProductSelection.class);
            productSelection.submitSearchCriteriaFile(slideData);

            reply = "Success";
        }

        ObjectOutputStream outputToApplet = new ObjectOutputStream(res.getOutputStream());
        outputToApplet.writeObject(reply);
        outputToApplet.flush();          
        outputToApplet.close();
    }
    catch (ClassNotFoundException ex)
    {
        Logger.getLogger(CriteriaServlet.class.getName()).log(Level.SEVERE, null, ex);
    }
}

在支持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);
    }

    return "process_MainSearchResult";
}

在JSF页面,其中包含applet的标题:

<SCRIPT language="javascript">

    function openResultsPage()
    {
        window.location = "MainSearchResult.xhtml";
    }

    </SCRIPT>

FacesUtil基于BalusC的FacesUtil类(微小的改动请求和响应类型)用于获取该Servlet的支持bean:

    package searchselection;

import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FacesUtil
{
    // Getters -----------------------------------------------------------------------------------

    public static FacesContext getFacesContext(
        ServletRequest request, ServletResponse response)
    {
        // Get current FacesContext.
        FacesContext facesContext = FacesContext.getCurrentInstance();

        // Check current FacesContext.
        if (facesContext == null) {

            // Create new Lifecycle.
            LifecycleFactory lifecycleFactory = (LifecycleFactory)
                FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); 
            Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

            // Create new FacesContext.
            FacesContextFactory contextFactory  = (FacesContextFactory)
                FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
            facesContext = contextFactory.getFacesContext(
                request.getServletContext(), request, response, lifecycle);

            // Create new View.
            UIViewRoot view = facesContext.getApplication().getViewHandler().createView(
                facesContext, "");
            facesContext.setViewRoot(view);                

            // Set current FacesContext.
            FacesContextWrapper.setCurrentInstance(facesContext);
        }

        return facesContext;
    }

    // Helpers -----------------------------------------------------------------------------------

    // Wrap the protected FacesContext.setCurrentInstance() in a inner class.
    private static abstract class FacesContextWrapper extends FacesContext {
        protected static void setCurrentInstance(FacesContext facesContext) {
            FacesContext.setCurrentInstance(facesContext);
        }
    } 

}


文章来源: How to submit a serialised object from an Applet, via a servlet, to a backing bean then open a results JSF page