【问题标题】:I need some direction with accessing mysql using a java servlet我需要一些使用 java servlet 访问 mysql 的指导
【发布时间】:2011-10-07 04:59:46
【问题描述】:

这是我的代码

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.sql.*;

@WebServlet(name = "Scores", urlPatterns = {"/Scores"})
public class Scores extends HttpServlet{

    private Connection conn;
    private PreparedStatement psmt;
    private ResultSet rs;
    private String tableName;
    private String ssnNum;

    @Override
    public void init() throws ServletException {
        connect();
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        try{
            tableName = request.getParameter("tableName");
            ssnNum = request.getParameter("ssnNum");

            rs = psmt.executeQuery();

            out.print("\t\t\t");
            out.print(rs.getString("Student") + " " + rs.getString("Score"));
            out.print("<br>");
            out.close();
        }catch(Exception e){
            System.err.println(e);
        }
    }

    public void connect(){
        try{
            //Loads Driver
            Class.forName("com.mysql.jdbc.Driver");

            //Establishes a connection to DataBase Javabook
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost/javabook", "root", "password");

            psmt = conn.prepareStatement("select Student, Score from " + tableName + 
                    " where ssn = " + ssnNum);
        } catch (Exception e){
            System.err.println(e);
        }//End Try/Catch Block
    }
}

这里是html

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>TravisMeyersP3</title>
    </head>
    <body>
        Find Your Current Score
      <form method = "get" action = "Scores">
      <p>Social Security Number <font color = "#FF0000">*</font>
         <input type = "text" name = "ssnNum">
      </p>
      <p>Course Id
         <select size = "1" name = "tableName">
           <option value = "Cpp">C++</option>
           <option value = "AdvJava">Advanced Java</option>
         </select>
      </p>
      <p><input type = "submit" name = "Submit" value = "Submit">
      </p>
    </body>
</html>

我在 netbeans 中使用 apache tomcat 7.0.21 和 java jdk 7。 servlet 应该访问我在 mysql 中创建的两个表之一并显示用户参数的值。我没有收到任何编译或运行时错误。由于某种原因,servlet 在用户提交表单后没有访问 mysql 并显示结果。


首先,我要感谢瑞恩斯图尔特、精英绅士和 CodeBuzz 抽出时间来帮助我。除了上述问题,我还遇到了 sql 语法问题。当我将变量 tableName 和 ssnNum 设置到我的新 PreparedStatement 中时 (PreparedStatement psmt = conn.prepareStatement("select Student, Score from ? where SSN = ?;");) 使用 psmt.setString(1, tableName) 等,出于某种原因,在准备好的语句中的字符串周围加上了单引号. MySQL 不喜欢这样,唯一显示错误的地方是在 tomcat 命令窗口中。解决上述问题后,一切都很好。再次感谢大家帮助我解决这个问题。

【问题讨论】:

  • 在 servlet init 上打开连接并保持打开状态是个坏主意。
  • 哦。你是对的。我会解决的。谢谢。
  • Servlet 不是线程安全的,所以不应该有任何状态。所以例如您的 tablename 字段可能会被另一个正在处理不同 HTTP 请求的线程覆盖,导致意外结果。

标签: java mysql servlets


【解决方案1】:

没有办法奏效。在 init() 上,您使用包含字段 tableNamessnNum 的查询创建 PreparedStatement。那时,这两个都是空的。在稍后(在 doGet() 中)发出请求之前,它们不会被分配。你肯定会出错。你需要找到他们。

其他东西:

  1. 在适当的情况下使用局部变量而不是字段。
  2. 为每个请求打开一个新连接。
  3. 不要关闭响应 Writer(或 OutputStream)。
  4. //Loads Driver 是一个糟糕的评论。其他的也不太热。
  5. 永远不会将字符串直接连接到 SQL 查询中。 Use a PreparedStatement with placeholders 和 set* 方法插入参数。
  6. 添加一些有意义的日志记录以帮助您识别正在发生的事情,而无需附加调试器。 (不过,您显然必须先弄清楚消息的去向。)
  7. 您需要先调用 ResultSet 上的next(),然后才能从中获取值。
  8. 不需要Class.forName(...) 行。
  9. 您的 ResultSet、Statement 和/或 Connection 需要在完成后关闭。否则,您就是在浪费资源。
  10. 与其捕获和忽略异常,不如让它们从您的 servlet 中抛出。这将有助于您进行故障排除。
  11. 永远不要捕获异常。仅捕获您希望捕获的特定类型。

【讨论】:

  • 好的。这需要考虑很多,但我会解决它。
  • 关于#5,你可以开始阅读SQL注入on WikipediaXKCD
  • psmt = conn.prepareStatement("select Student, Score from ? where ssn = ?"); psmt.setString(1, tableName); psmt.setString(2, ssnNum);
【解决方案2】:

您的 HTML &lt;form&gt; 声明错误:

<form method = "get" action = "Scores">

以下是您上述错误的一些解决方案:

  • 您的方法必须是 GET 而不是 get(遵循 HTTP 方法)。
  • 您的操作必须是 /Scores 而不是 Scores
  • 你需要在ResultSet上调用next()之前使用getXXX方法(其中XXX可以是IntStringDouble等)。
  • 总是关闭ResultSet,然后关闭Statement/PreparedStatement,最后关闭Connection

另外,我建议永远不要这样做:

  • 根本不允许 Servlet 上的连接。您在init() 上打开一个连接,这很糟糕,因为连接可能会超时或关闭,而且您无法打开它(Servlet 是单例)。
  • 另外,我建议使用PreparedStatement 而不是连接字符串。驱动程序知道如何将数据类型转换为相应的 SQL 类型。

我建议您创建一个遵循简单数据库 CRUD 操作的持久层。

【讨论】:

    【解决方案3】:

    您在 init() 函数中准备了一个查询语句,但您没有得到任何记录,因为
    tableNamessnNum 中的 null 值。
    因此,当您在doGet() 函数中收到response 时,请更改此并准备好查询,然后执行它。

    【讨论】:

      【解决方案4】:

      在 doGet 方法而不是 connect 方法中创建 Prepared 语句。`

       @Override
      
           public void doGet(HttpServletRequest request, HttpServletResponse
              response) throws ServletException, IOException {
      
          response.setContentType("text/html");
          PrintWriter out = response.getWriter();
          try{
              tableName = request.getParameter("tableName");
              ssnNum = request.getParameter("ssnNum");
              psmt = conn.prepareStatement("select Student, Score from ? where ssn = ?");
              psmt.setString(1,tableName);
              psmt.setString(2,ssnNum);
              rs = psmt.executeQuery();
      
              out.print("\t\t\t");
              out.print(rs.getString("Student") + " " + rs.getString("Score"));
              out.print("<br>");
              out.close();
          }catch(Exception e){
              System.err.println(e);
          }
      }
      
      public void connect(){
          try{
              //Loads Driver
              Class.forName("com.mysql.jdbc.Driver");
      
              //Establishes a connection to DataBase Javabook
              conn = DriverManager.getConnection(
                      "jdbc:mysql://localhost/javabook", "root", "password");
      
      
          } catch (Exception e){
              System.err.println(e);
          }//End Try/Catch Block
      }
      

      `

      更好的方法是创建一个业务类来处理数据库连接并从 servlet 使用这个类。 见Select Records Using PreparedStatement

      【讨论】:

      • 好的。我解决了你们提到的问题。结果还是一样。当我提交表单时,我得到一个空白页。 ???
      • 我最初在 doget 方法中有准备好的语句。我把它放在 connect 方法中,因为我只是想尽一切办法让它工作。
      • 我修复了他提到的问题,除了使用持久层,这对我来说有点高级,我得读一下。
      猜你喜欢
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多