Servlet 介绍

小吴
2023-01-01 / 0 评论 / 9 阅读 / 正在检测是否收录...

  前面已经介绍过,JSP 的本质就是 Servlet,开发者把编写好的 JSP 页面部署在 Web 容器中之后,Web 容器会将 JSP 编译成对应的 Servlet。但直接使用 Servlet 的坏处是:Servlet 的开发效率非常低,特别是当使用 Servlet 生成表现层页面时,页面中所有的 HTML 标签,都需采用 Servlet 的输出流来输出,因此极其烦琐。而且 Servlet 是标准的 Java 类,必须由程序员开发、修改,美工人员难以参与 Servlet 页面的开发。这一系列的问题,都阻碍了 Servlet 作为表现层的使用。
  自 MVC 规范出现后,Servlet 的责任开始明确下来,仅仅作为控制器使用,不再需要生成页面标签,也不再作为视图层角色使用。

Servlet 的开发

  前面介绍的 JSP 的本质就是 Servet,Servlet 通常被称为服务器端小程序,是运行在服务器端的程序,用于处理及响应客户端的请求。
  Servlet 是个特殊的 Java 类,这个 Java 类必须继承 HttpServlet。每个 Servlet 可以响应客户端的请求。Servlet 提供不同的方法用于响应客户端请求。
  ➢ doGet:用于响应客户端的 GET 请求。
  ➢ doPost:用于响应客户端的 POST 请求
  ➢ doPut:用于响应客户端的 PUT 请求。
  ➢ doDelete:用于响应客户端的 DELETE 请求
  事实上,客户端的请求通常只有 GET 和 POST 两种,Servlet 为了响应这两种请求,必须重写 doGet()和 doPost()两个方法。如果 Servlet 为了响应 4 种方式的请求,则需要同时重写上面的 4 个方法。
  大部分时候,Servlet 对于所有请求的响应都是完全一样的。此时,可以采用重写一个方法来代替上面的几个方法:只需重写 service() 方法即可响应客户端的所有请求。
  另外,HttpServlet 还包含两个方法。
  ➢ init(ServletConfig config):创建 Servlet 实例时,调用该方法的初始化 Servlet 资源。
  ➢ destroy():销毁 Servlet 实例时,自动调用该方法的回收资源。
  通常无须重写 init()和 destroy()两个方法,除非需要在初始化 Servlet 时,完成某些资源初始化的方法,才考虑重写 init 方法。如果需要在销毁 Servlet 之前,先完成某些资源的回收,比如关闭数据库连接等,才需要重写 destroy 方法。

  下面提供一个 Servlet 的示例,该 Servlet 将获取表单请求参数,并将请求参数显示给客户端。

package lee;

import java.io.PrintStream;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// Servlet 必须继承 HttpServlet 类
@WebServlet(name="firstServletr",urlPatterns={"/firstServlet"})
public class FirstServlet extends HttpServlet{
    // 客户端的响应方法,使用该方法可以响应客户端所有类型的请求
    public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,java.io.IOException{
        // 设置解码方式
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charSet=UTF-8");
        // 获取 name 的请求参数值
        String name = request.getParameter("name");
        // 获取 gender 的请求参数值
        String gender = request.getParameter("gender");
        // 获取 color 的请求参数值
        String[] color =request.getParameterValues("color");
        // 获取 country的请求参数值
        String national = request.getParameter("country");
        //获取页面输出流
        PrintStream out = new PrintStream(response.getOutputStream());
        // 输出 HTML 页面标签
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet 测试</title>");
        out.println("</head>");
        out.println("<body>");
        // 输出请求参数的值:name
        out.println("您的名字:" + name + "<hr/>");
        // 输出请求参数的值:gender
        out.println("您的性别:" + gender + "<hr/>");
        // 输出请求参数的值:color
        out.println("您喜欢的颜色:");
        for(String c : color)
        {
            out.println(c + " ");
        }
        out.println("<hr/>");
        // 输出请求参数的值:national
        out.println("您来自的国家:" + national + "<hr/>");
        out.println("</body>");
        out.println("</html>");
    }
}

  上面的 Servlet 类继承了 HttpServet 类,表明它作为一个 Servlet 使用。程序的粗体字代码定义了 service 方法来响应用户请求。对比该 Servlet 和 JSP 脚本中的 9 个内置对象中的 request1.jsp 页面,该 Servlet 和 request1.jsp 页面的效果完全相同,都通过 HttpServltRequest 获取客户端的 form 请求参数,并显示请求参数的值。
  Servlet 和 JSP 的区别在于:
  ➢ Servlet 中没有内置对象,原来 JSP 中的内置对象都必须由程序显式创建。
  ➢ 对于静态的 HTML 标签,Servlet 都必须使用页面输出流逐行输出。
  这也正是前面介绍的,JSP 是 Servlet 的一种简化,使用 JSP 只需要完成程序员需要输出到客户端的内容,至于 JSP 脚本如何嵌入一个类中,由 JSP 容器完成。而 Servlet 则是个完整的 Java 类,这个类的 service()方法用于生成对客户端的响应。
  普通 Servlet 类里的 service()方法的作用,完全等同于 JSP 生成 Servlet 类的_jspService()方法。因此原 JSP 页面的 JSP 脚本、静态 HTML 内容,在普通 Servlet 里都应该转换成 service()方法的代码或输出语句;原 JSP 声明中的内容,对应为在 Servlet 中定义的成员变量或成员方法。

Servlet 的配置

  编辑好的 Servlet 源文件并不能响应用户请求,还必须将其编译成 class 文件。将编译后的 FirstServlet.class 文件放在 WEB-INF/classes 路径下,如果 Servlet 有包,则还应该将 class 文件放在对应的包路径下(例如,本例的 FirstServlet.class 就放在 WEB-INF/classes/lee 路径下)。

  为了让 Servlet 能响应用户请求,还必须将 Servlet 配置在 Web 应用中。配置 Servlet 时,需要修改 web.xml文件。
  从 Servlet 3.0 开始,配置 Servlet 有两种方式。
  ➢ 在 Servlet 类中使用@WebServlet 注解进行配置。
  ➢ 通过在 web.xml 文件中进行配置。
  上面开发 Servlet 类时使用了@WebServlet 注解修饰该 Servlet 类,使用@WebServlet 时可指定如下表所示的常用属性。

属性是否必需说明
asyncSupported指定该 Servlet 是否支持异步操作模式。
displayName指定该 Servlet 的显示名
initParams用于为该 Servlet 配置参数
loadOnStartup用于将该 Servlet 配置成 load-on-startup 的 Servlet
name指定该 Servlet 的名称
urlPatterns/value这两个属性的作用完全相同。都指定该 Servlet 处理的 URL

  如果打算使用注解来配置 Servlet,有两点需要指出。
  ➢ 不要在 web.xml 文件的根元素(<web-app.../>)中指定 metadata-complete="true"。
  ➢ 不要在 web.xml 文件中配置该 Servlet。
  如果打算使用 web.xml 文件来配置该 Servlet,则需要配置如下两个部分。
  ➢ 配置 Servlet 的名字:对应 web.xml 文件中的<servlet/>元素。
  ➢ 配置 Servlet 的 URL:对应 web.xml 文件中的<servlet-mapping/>元素。这一步是可选的。但如果没有为 Servlet 配置 URL,则该 Servlet 不能响应用户请求。

  因此,配置一个能响应客户请求的 Servlet,至少需要配置两个元素。关于上面的 FirstServlet 的配置如下。

  <!-- 配置 Servlet 的名字 -->
  <servlet>
      <!-- 指定 Servlet 的名字,相当于指定@WebServlet 的 name 属性 -->
      <servlet-name>firstServlet</servlet-name>
      <!-- 指定 Servlet 的实现类-->
      <servlet-class>lee.FirstServlet</servlet-class>
  </servlet>
  <!-- 配置Servlet的URI -->
  <servlet-mapping>
      <!-- 指定 Servlet 的名字-->
      <servlet-name>firstServlet</servlet-name>
      <!-- 指定Servlet 映射的 URL 地址,相当于指定@WebServlet 的urlPatterns 属性-->
    <url-pattern>/aa</url-pattern>
  </servlet-mapping>

  如果在 web.xml 文件中增加了如上所示的粗体字配置片段,则该 Servlet 的 URL 为/aa。如果没有在 web.xml 文件中增加上面的配置片段,那么该 Servlet 类上的@WebServlet 注解就会起作用,该 Servlet 的 URL 为/firstServlet。
  将JSP 脚本中的 9 个内置对象中的 form.jsp 复制到本应用中,并对其进行简单修改,将 form 表单元素的 action 修改成 aa,在表单域中输入相应的数据,然后单击“提交”按钮,效果如下图所示。

Servlet 处理用户请求

  在这种情况下,Servlet 与 JSP 的作用效果完全相同。

JSP/Servlet 的生命周期

  JSP 的本质就是 Servlet,开发者编写的 JSP 页面将由 Web 容器编译成对应的 Servlet,当 Servlet 在容器中运行时,其实例的创建及销股等都不是由程序员决定的,而是由 Web 容器进行控制的。
  Servlet 实例有两个时机。
  ➢ 客户端第一次请求某个 Servlet 时,系统创建该 Servlet 的实例:大部分的 Servlet 都是这种 Servlet。
  ➢ Web 应用启动时立即创建 Servlet 实例,即 load-on-startup Servlet。
  每个 Servlet 的运行都遵循如下生命周期。
  (1) 创建 Servlet 实例。
  (2) Web 容器调用 Servlet 的 init 方法,对 Servlet 进行初始化。
  (3) Servlet 初始化后,将一直存在于容器中,用于响应客户端请求。如果客户端发送 GET 请求,容器调用 Servlet 的 doGet 方法处理并响应请求;如果客户端发送 POST 请求,容器调用 Servlet 的 doPost 方法处理并响应请求。或者统一使用 service()方法处理来响应用户请求。
  (4) Web 容器决定销毁 Servlet 时,先调用 Servlet 的 destroy 方法,通常在关闭 Web 应用之时销毁 Servlet。
  Servlet 的生命周期如下图所示。

Servlet 的生命周期

load-on-startup Servlet

  上面已经介绍过,创建 Servlet 实例有两个时机:用户请求之时或应用启动之时。应用启动时就创建 Servlet,通常是用于某些后台服务的 Servlet,或者需要拦截很多请求的 Servlet;这种 Servlet 通常作为应用的基础 Servlet 使用,提供重要的后台服务。
  配置 load-on-startup 的 Servlet 有两种方式。
  ➢ 在 web.xml 文件中通过<servlet.../>元素的<load-on-startup...>子元素进行配置。
  ➢ 通过@WebServlet 注解的 loadOnStartup 属性指定。
  <load-on-startup../>元素或 loadOnStartup 属性都只接收一个整型值,这个整型值越小,Servlet 就越优先实例化。
  下面是一个简单的 Servlet,该 Servlet 不响应用户请求,它仅仅执行计时器功能,每隔一段时间会在控制台打印出当前时间。

@WebServlet(loadOnStartup=1)
public class TimerServlet extends HttpServlet
{
    public void init(ServletConfig config) throws ServletException
    {
        super.init(config);
        Timer t = new Timer(1000,new ActionListener()
        {
                public void actionPerformed(ActionEvent e)
                {
                    System.out.println(new Date());
                }
        });
        t.start();
    }
}

  这个 Servlet 没有提供 service()方法,这表明它不能响应用户请求,所以无须为它配置 URL 映射。由于它不能接收用户请求,所以只能在应用启动时实例化。
  以上程序中@WebServlet 注解即可将该 Servlet 配置了 load-on-startup Servlet。除此之外,还可以在 web.xml 文件中增加如下配置片段。

<servlet>
      <!-- Servlet 名 -->
      <servlet-name>timerServlet</servlet-name>
      <!-- Servlet 的实现类 -->
      <servlet-class>lee.TimerServlet</servlet-class>
      <!-- 配置应用启动时,创建 Servlet 实例,相当于指定@WebServlet 的 loadOnStartup 属性-->
      <load-on-startup>1</load-on-startup>
  </servlet>

  以上配置片段中粗体字代码指定 Web 应用启动时,Web 容器将会实例化该 Servlet,且该 Servlet 不能响应用户请求,将一直作为后台服务执行:每隔 1 秒钟输出一次系统时间。

访问 Servlet 的配置参数

  配置 Servlet 时,还可以增加额外的配置参数。通过使用配置参数,可以实现提供更好的可移植性,避免将参数以硬编码方式写在程序代码中。
  为 Servlet 配置参数有两种方式。
  ➢ 通过@WebServlet 的 initParams 属性来指定。
  ➢ 通过在 web.xml 文件的<servlet.../>元素中添加<init-param.../>子元素来指定。
  第二种方式与为 JSP 配置初始化参数极其相似,因为 JSP 的实质就是 Servlet,而且配置 JSP 的实质就是把 JSP 当 Servlet 使用。
  访问 Servlet 配置参数通过 ServletConfig 对象完成,ServletConfig 提供如下方法。
  ➢ java.langString getInitParameter(java.lang.String name):用于获取初始化参数。

  下面的 Servlet 将会连接数据库,并执行 SQL 查询,但程序并未直接给出数据库连接信息,而是将数据库连接信息放在 web.xml 文件中进行管理。

@WebServlet(name="testServlet",urlPatterns={"/testServlet"},
            initParams={
                @WebInitParam(name="driver",value="com.mysql.jdbc.Driver"),
                @WebInitParam(name="url",value="jdbc:mysql://localhost:3306/javaee"),
                @WebInitParam(name="user",value="root"),
                @WebInitParam(name="pass",value="root")})
public class TestServlet extends HttpServlet{
    // 重写 init 方法
    public void init(ServletConfig config) throws ServletException{
        // 重写该方法,应该首先调用父类的 init 方法
        super.init(config);
    }
    // 响应客户端请求的方法
    public void service (HttpServletRequest request,HttpServletResponse response)throws ServletException,java.io.IOException{
        try{
            // 获取 ServletConfig 对象
            ServletConfig config = getServletConfig();
            // 通过 ServletConfig 对象获取配置参数:dirver
            String driver = config.getInitParameter("driver");
            // 通过 Servletconfig 对象获取配置参数:url
            String url = config.getInitParameter("url");
            // 通过 ServletConfig 对象获取配置参数:user
            String user = config.getInitParameter("user");
            // 通过 ServletConfig 对象获取配置参数:pass
            String pass = config.getInitParameter("pass");
            // 注册驱动
            Class.forName(driver);
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url,user,pass);
            // 创建 Statement 对象
            Statement stmt = conn.createStatement();
            // 执行查询,获取 ResuletSet 对象
            ResultSet rs = stmt.executeQuery("select * from news_inf");
            response.setContentType("text/html;charSet=UTF-8");
            // 获取页面输出流
            PrintStream out= new PrintStream(response.getOutputStream());
            // 输出 HTML 标签
            out.println("<html>");
            out.println("<head>");
            out.println("<title>访问 Servlet 初始化参数测试</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<table bgcolor=\"#9999dd\" border= \"l\"" + "width=\"480\">");
            // 遍历结果集
            while(rs.next()){
                // 输出结果集内容
                out.println("<tr>");
                out.println("<td>" + rs.getString(1) + "</td>");
                out.println("<td>" + rs.getString(2) + "</td>");
            }
            out.println("</table>");
            out.println("</body>");
            out.println("</html>");
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

  ServletConfig 获取配置参数的方法 ServletContext 获取配置参数的方法完全一样,只是 ServletConfig 是取得当前 Servlet 的配置参数,而 ServletContext 是获取整个 Web 应用的配置参数。
  以上程序中@WebServlet 中的 initParams 属性用于为该 Servlet 配置参数,initParams 属性值的每个@WebInitParam 配置一个初始化参数,每个@WebInitParam 可指定如下两个属性。
  ➢ name: 指定参数名。
  ➢ value:指定参数值。
  类似地,在 web.xml 文件中为 Servlet 配置参数使用<init-param../>元素,该元素可以接受如下两个子元素。
  ➢ param-name:指定配置参数名。
  ➢ param-value:指定配置参数值。
  下面是该 Servlet 在 web.xml 文件中的配置片段。

  <servlet>
    <!-- 配置 Servlet名 -->
    <servlet-name>testServlet</servlet-name>
    <!-- 指定 Servlet 的实现类 -->
    <servlet-class>lee.TestServlet</servlet-class>
    <!-- 配置 Servlet 的初始化参数:driver -->
    <init-param>
        <param-name>driver</param-name>
        <param-value>com.mysql.jdbc.Driver</param-value>
    </init-param>
    <!-- 配置 Servlet 的初始化参数:url-->
    <init-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/javaee</param-value>
    </init-param>
    <!-- 配置 Servlet 的初始化参数:user -->
    <init-param>
        <param-name>user</param-name>
        <param-value>root</param-value>
    </init-param>
    <!-- 配置 Servlet 的初始化参数:pass-->
    <init-param>
        <param-name>pass</param-name>
        <param-value>root</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <!-- 确定 Servlet 名-->
    <servlet-name>testServlet</servlet-name>
    <!-- 配置 Servlet 映射的 URL -->
    <url-pattern>/testServlet</url-pattern>
  </servlet-mapping>

  以上配置片段的代码配置了 4 个配置参数,Servlet 通过这 4 个配置参数就可连接数据库。在浏览器中浏览该 Servlet,可看到数据库查询成功(如果数据库的配置正确)。

使用 Servlet 作为控制器

  正如前面见到的,使用 Servlet 作为表现层的工作量太大,所有的 HTML 标签都需要使用页面输出流生成。因此,使用 Servlet 作为表现层有如下三个劣势。
  ➢ 开发效率低,所有的 HTML 标签都需使用页面输出流完成。
  ➢ 不利于团队协作开发,美工人员无法参与 Servlet 界面的开发。
  ➢ 程序可维护性差,即使修改一个按钮的标题,都必须重新编辑 Java 代码,并重新编译。
  在标准的 MVC 模式中,Servlet 仅作为控制器使用。Java EE 应用架构正是遵循 MVC 模式的,对于遵循 MVC 模式的 Java EE 应用而言,JSP 仅作为表现层(View)技术,其作用有两点。
  ➢ 负责收集用户请求参数。
  ➢ 将应用的处理结果、状态数据呈现给用户。
  Servlet 则仅充当控制器(Controller)角色,它的作用类似于调度员:所有用户请求都发送给 Servlet,Servlet 调用 Model 来处理用户请求,并调用 JSP 来呈现处理结果;或者 Servlet 直接调用 JSP 将应用的状态数据呈现给用户。
  Model 通常由 JavaBean 来充当,所有业务逻辑、数据访问逻辑都在 Model 中实现。实际上隐藏在 Model 下的可能还有很多丰富的组件,例如 DAO 组件、领域对象等。
  下面介绍一个使用 Servlet 作为控制器的 MVC 应用,该应用演示了一个简单的登录验证。
  下面是本应用的登录页面。

<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<!DOCTYPE html>
<html>
<head>
    <title>new document</title>
</head>
<body>
<!-- 输出出错提示 -->
<span style="color: red;font-weight: bold">
<%if(request.getAttribute("err") != null){
        out.println(request.getAttribute("err") + "<br/>");
}%>
</span>
请输入用户名和密码:
<!-- 登录表单,该表单提交到一个 Servlet -->
<form id="login" method="post" action="login">
用户名:<input type="text" name="username"/><br/>
密&nbsp;&nbsp 码: <input type="password" name="pass"/><br/>
<input type="submit" value="登录"/><br/>
</form>
</body>
</html>

  以上页面除了判断语句使用 JSP 脚本输出错误提示之外,该页面其实是一个简单的表单页面,用于收集用户名及密码,并将请求提交到指定 Servlet,该 Servlet 充当控制器角色。


  控制器 Servlet 的代码如下。

@WebServlet(name="login",urlPatterns={"/login"})
public class LoginServlet extends HttpServlet{
    // 响应客户端请求的方法
    public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,java.io.IOException{
        String errMsg = "";
        // Servlet 本身并不输出响应到客户端,因此必须将请求转发到视图页面
        RequestDispatcher rd;
        // 获取请求参数
        String username = request.getParameter("username");
        String pass = request.getParameter("pass");
        try{
            // Servlet 本身并不执行任何的业务逻辑处理,它调用 JavaBean 处理用户请求
            DbDao dd = new DbDao("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/liuyan","root","root") ;
            // 查询结果集
            ResultSet rs = dd.query("select pass from user_inf" +  " where name = ?",username) ;
            if (rs.next()){
                // 用户名和密码匹配
                if (rs.getString("pass").equals(pass)){
                    // 获取 session 对象
                    HttpSession session = request.getSession(true);
                    // 设置 session 属性,跟踪用户会话状态
                    session.setAttribute("namen",username);
                    // 获取转发对象
                    rd = request.getRequestDispatcher("/welcome.jsp");
                    // 转发请求
                    rd.forward(request,response);
                }
                else{
                    // 用户名和密码不匹配时
                    errMsg += "您的用户名密码不符合,请重新输入";
                }
            }
            else{
                // 用户名不存在时
                errMsg += "您的用户名不存在,请先注册";
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        // 如果出错,转发到重新登录
        if (errMsg != null && !errMsg.equals("")){
            rd = request.getRequestDispatcher("/login.jsp");
            request.setAttribute("err",errMsg);
            rd.forward(request,response);
        }
    }
}

  控制器负责接收客户端的请求,它既不直接对客户端输出响应,也不处理用户请求,只调用 JavaBean 来处理用户请求,如程序中代码所示;JavaBean 处理结束后,Servlet 根据处理结果,调用不同的 JSP 页面向浏览器呈现处理结果。
  上面 Servlet 使用@WebServlet 注解为该 Servlet 配置了 URL 为/login,因此向/login 发送的请求将会交给该 Servlet 处理。
  下面是本应用中 DbDao 的源代码。

public class DbDao {
    private Connection conn;
    private String driver;
    private String url;
    private String username;
    private String pass;

    public DbDao() {
    }

    public DbDao(String driver, String url, String username, String pass) {
        this.driver = driver;
        this.url = url;
        this.username = username;
        this.pass = pass;
    }

    // 下面是各个成员属性的 setter 和 getter 方法
    public void setDriver(String driver) {
        this.driver = driver;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPass(String pass) {
        this.pass = pass;
    }

    public String getDriver() {
        return (this.driver);
    }

    public String getUrl() {
        return (this.url);
    }

    public String getUsername() {
        return (this.username);
    }

    public String getPass() {
        return (this.pass);
    }

    // 获取数据库连接
    public Connection getConnection() throws Exception {
        if (conn == null) {
            Class.forName(this.driver);
            conn = DriverManager.getConnection(url, username, this.pass);
        }
        return conn;
    }

    // 插入记录
    public boolean insert(String sql, Object... args) throws Exception {
        PreparedStatement pstmt = getConnection().prepareStatement(sql);
        for (int i = 0; i < args.length; i++) {
            pstmt.setObject(i + 1, args[i]);
        }
        if (pstmt.executeUpdate() != 1) {
            return false;
        }
        return true;
    }

    // 执行查询
    public ResultSet query(String sql, Object... args) throws Exception {
        PreparedStatement pstmt = getConnection().prepareStatement(sql);
        for (int i = 0; i < args.length; i++) {
            pstmt.setObject(i + 1, args[i]);
        }
        return pstmt.executeQuery();
    }

    // 执行修改
    public void modify(String sql, Object... args) throws Exception {
        PreparedStatement pstmt = getConnection().prepareStatement(sql);
        for (int i = 0; i < args.length; i++) {
            pstmt.setObject(i + 1, args[i]);
        }
        pstmt.executeUpdate();
        pstmt.close();
    }

    // 关闭数据库连接的方法
    public void closeConn() throws Exception {
        if (conn != null && !conn.isClosed()) {
            conn.close();
        }
    }
}

  上面 DbDao 负责完成查询、插入、修改等操作。从上面这个应用的结构来看,整个应用的流程非常清晰,下面是 MVC 中各个角色的对应组件。
  M:Model,即模型,对应 JavaBean。
  V:View,即视图,对应 JSP 页面。
  C:Controller,即控制器,对应 Servlet。

2

评论

博主关闭了当前页面的评论