Servlet程序仅适用于第一次

时间:2015-12-25 11:26:24

标签: java servlets

我正在尝试这个小HttpSession程序作为我项目的演示 该程序只检查用户是否是新用户,如果用户是新用户,则显示form,如果用户不是新用户,则显示用户名,他选择的color以及总数为。访问。

当我运行我的程序时,它仅适用于第一次。这意味着当我运行我的程序的另一个实例时,它会显示一个空白的网页。

导致此问题的代码有什么问题?

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


public class SessionServlet extends HttpServlet {

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=UTF-8");
    try (PrintWriter out = response.getWriter()) {
        Integer hitCount;
        HttpSession s = request.getSession(true);            
        if(s.isNew()) {
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet SessionServlet</title>");            
            out.println("</head>");
            out.println("<body>");

            out.println("<form method=get action=SessionServlet>");
            out.println("<h3>Please sleect a Color</h3>");
            out.println("<input type=radio name=color />Red");
            out.println("<br /><input type=radio name=color />Green");
            out.println("<br /><input type=text name=txtName />");
            out.println("<br /><input type=submit name=Submit value=Submit />");
            out.println("</form>");

            out.println("</body>");
            out.println("</html>");
        } else if(!s.isNew()){
            String name = (String) request.getParameter("txtName");
            String color = (String) request.getParameter("color");
            hitCount = new Integer(1);
            s.setAttribute("Name", name);
            s.setAttribute("color", color);
            s.setAttribute("HitCount", hitCount);
            if((name != null) && (color != null)) {
                out.println("Name: " + s.getAttribute("Name"));
                hitCount = (Integer)s.getAttribute("HitCount");
                hitCount = hitCount++;
                s.setAttribute("HitCount", hitCount);
                //out.println("<body bgcolor=" + s.getAttribute("color") + ">");
                out.println("you selected" + s.getAttribute("color"));
                out.println("Total visits=====>" + s.getAttribute("HitCount"));
            }
        }
    }
}  
}

2 个答案:

答案 0 :(得分:2)

第二次运行此代码时,会话已经存在,因此程序会通过 else 分支 - 但“旧”请求对象(来自应用程序的第一次运行)及其参数(颜色名称)在那时已经消失。在第一次应用程序运行的响应被发送回客户端后,请求被容器销毁。

在您的代码中

String name = (String) request.getParameter("txtName"); String color = (String) request.getParameter("color");

您正在尝试获取不存在的参数。参数 txtName color 不再存在于 request 中。因此它们是null并且是下一个条件

if((name != null) && (color != null))

总是 false 。并且没有任何内容写入 out Writer。

为了完成这项工作,您应该做的是从会话对象中读取参数(这是会话的目的),您应该将它们放在第一个应用程序运行中。此代码无效。您的 hitCount 将始终为1(请参阅 HttpSessionListener 界面)。这个代码在很多层面都是错误的 - 你应该在else if分支之后重新编写所有内容,而这个分支应该只有else

TLDR: 你的问题是为什么它不起作用:答案是 - 你正在阅读不存在的参数。您必须在第一个应用程序运行中将参数放入 session 对象并从中读取它们。

在12月31日之后编辑你的问题:

这是我要做的。假设这个名为 SessionServlet 的简单项目的目录结构如下。这个结构将用于整个答案。为了简化事情,我不会列出每个目录,你肯定会从中得到这个想法。这是目录结构的真实示例,为了本教程示例的目的,它被简化。

<path-to-project>/SessionServlet/src/com/example/session
<path-to-project>/SessionServlet/WebContent/META-INF
<path-to-project>/SessionServlet/WebContent/WEB-INF

创建 html 文件,例如 start.html 。它应包含您需要在会话中存储的值的输入字段。文件在这里

<path-to-project>/SessionServlet/WebContent/start.html

其内容

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Start page</title>
</head>
<body>
    <form method="get" action="MySessionServlet">
       <h3>Please select a Color</h3>
       <input type="radio" name="color" value="red" />Red<br>
       <input type="radio" name="color" value="green" />Green<br>
       <input type="text" name="txtName" /><br>
       <input type="submit" name="Submit" value="Submit" />
    </form>
</body>
</html>

在你的servlet示例中,你忘记了radiobutton输入中的 value 属性,因此无论你要检查哪个radiobutton,值都是 on ,而不是颜色名称。

接下来,您必须创建servlet类 SessionServlet.java ,这与您最初的想法略有不同。它在这里:

<path-to-project>/SessionServlet/src/com/example/session/SessionServlet.java

其内容

package com.example.session;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class SessionServlet extends HttpServlet {

   private static final long serialVersionUID = -3808675281434686897L;

   @Override
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
       String requestColor = null;
       String requestTxtName = null;

       PrintWriter out = response.getWriter();
       MySessionListener listener = new MySessionListener();
       HttpSession session = request.getSession();

       if (session.isNew()) {
           //these are request parameters sent from html form
           requestColor = request.getParameter("color");
           requestTxtName = request.getParameter("txtName");

           //save the attributes in session in order to use them later
           session.setAttribute("sessionColor", requestColor);
           session.setAttribute("sessionTxtName", requestTxtName);
       }
       else {
           //get the previously stored attributes from session
           String color = (String) session.getAttribute("sessionColor");
           String name = (String) session.getAttribute("sessionTxtName");

           //session info
           out.println("session already existed");

           if (color != null && name != null) {
               out.println("Name: " + name);
               out.println("Color: " + color);

               out.println("Session count: " + listener.getSessionCount());
           }
       }
   }
}

我认为servlet的代码几乎是不言自明的。但是,如果您有任何特殊问题,请询问。

为了计算活动会话,您需要创建一个SessionListener类并计算会话数。出于本示例的目的,我将该类放入与servlet类相同的目录中。请不要在实际项目中这样做。你会制造一个大混乱。这只是简化的Java Enterprise Hello world 示例。该文件在这里

<path-to-project>/SessionServlet/src/com/example/session/MySessionListener.java

其内容为

package com.example.session;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MySessionListener implements HttpSessionListener {

    private static int sessionCount;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("Creating session with id: " + se.getSession().getId());
        sessionCount++;
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("Destroying session id: " + se.getSession().getId());
        sessionCount--;
    }

    public int getSessionCount() {
        return sessionCount;
    }
}

用于计算活动会话的侦听器类必须实现 HttpSessionListener 接口。我们在SessionServlet类中调用了方法 getSessionCount(),正如您已经注意到的那样。

最后要做的是创建一个部署描述符xml,以告诉容器如何处理我们创建的类。 文件必须命名为web.xml,必须放在WEB-INF目录中。

<path-to-project>/SessionServlet/WebContent/WEB-INF/web.xml

其内容为

<?xml version="1.0" encoding="UTF-8"?>
<web-app    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
        id="WebApp_ID"
        version="3.1">

   <display-name>SessionServlet</display-name>

   <welcome-file-list>
       <welcome-file>start.html</welcome-file>
   </welcome-file-list>

   <servlet>
       <servlet-name>my Session Servlet</servlet-name>
       <servlet-class>com.example.session.SessionServlet</servlet-class>
   </servlet>

   <servlet-mapping>
       <servlet-name>my Session Servlet</servlet-name>
       <url-pattern>/MySessionServlet</url-pattern>
   </servlet-mapping>

   <!-- set session timeout to 30 minutes -->
   <session-config>
       <session-timeout>30</session-timeout>
   </session-config>

   <!-- register listener class -->
   <listener>
       <listener-class>com.example.session.MySessionListener</listener-class>
   </listener>
</web-app>

就是这样。最后我的两分钱 - 你应该首先熟悉标准版Java。这是来自企业界的一个例子。网上有很多教程。给它一些时间,你不会后悔的。

关于servlet-在开始创建实际项目之前,您应该(必须)首先了解请求,响应,会话,客户端和容器(谁是谁,生命周期,管理等)的基本概念。我见过的最好的书是Head First - Servlets和JSP,它应该是理解这个主题的起点。

答案 1 :(得分:1)

您设置response.setContentType("text/html;charset=UTF-8") ....

但在您的if(!s.isNew()){....部分中,输出不是HTML,而是纯文本。 (“Name:”等等......)

我敢打赌,内容已存在,但您的浏览器未显示内容。