Servlet开发

自MVC规范出现后,Servlet的责任开始明确下来,仅仅作为控制器使用,不再需要生成页面标签,也不再做为视图层角色使用。servlet通常被称为服务器端小程序,是运行在服务器端的程序 。用于处理用户的请求及响应。

一. Servlet 介绍

Servlet是特殊的Java类,这个Java类必须继承HTTPServlet,每个servlet可以响应用户的请求。Servlet提供不同的方法用于相应用户的请求

  • doGet():用于相应客户端的get请求
  • doPost():用于响应客户端的Post请求
  • doPut():用于相应客户端的put请求
  • doDelete():用于相应客户端的delete请求

事实上,客户端请求通常只有get和post两种,servlet为了响应这两种请求,必须重写doPost()和doGet()两个方法。

大部分时候,servlet对于所有请求的响应都是都是完全一样的。因此可以采用重写一个方法来代替上面四个方法:只需要重写service方法即可响应客户端所有请求。

另外,HTTPServlet还包括另外两个方法

  • init(ServletConfig config):创建servlet实例时,使用该方法初始化Servlet资源。
  • destroy():销毁Servlet实例时,自动调用该方法回收资源

通常无需重写这两个方法。除非需要初始化Servlet时,完成某些资源初始化的方法,才考虑重写init()方法。如果需要在销毁Servlet之前,先完成某些资源的回收,比如关闭数据库连接等,才需要重写destroy方法。

Servlet与JSP的区别在于:

  • Servlet没有内置对象,原JSP中的内置对象必须由程序显示创建
  • 对于静态的HTML标签,servlet必须使用页面输出流逐行输出

二. Servlet 配置

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

为了让Servlet响应用户请求,还必须将Servlet配置在web应用中。配置Servlet时,需要修改web.xml文件》

从servlet3.0开始,配置servlet的两种方式

  • 在servlet类中使用@webServlet注解进行配置
  • 通过在web.xml文件中进行配置 

使用注解@webServlet配置Servlet时,常用的属性有

 

@webServlet支持的常用属性
属性 是否必须 说明
asynsSupported 指定该Servlet是否支持异步操作模式
displayName

指定该Servlet的显示名

initParam 用于为该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不能响应该用户请求。

三. JSP/Servlet 的生命周期

当Servlet在容器中运行时,其实例的创建及销毁等都不是程序员决定的,而是由web容器进行控制的的

创建servlet实例有两个时机

  • 客户端第一次请求某个Servlet时,系统创建该Servlet的实例:大部分的Servlet都是这种Servlet
  • Web应用启动时立即创建Servlet实例,即load-on-startup Servlet.

每个Servlet运行都遵循如下生命周期

  1. 创建Servlet实例
  2. Web容器调用Servlet的init方法,对Servlet进行初始化。
  3. Servlet初始化后,将一直保存在容器中,用于响应客户端的请求,调用doGet()或者doPost()方法处理并响应请求,或者统一使用service方法
  4. web容器决定销毁Servlet时,先调用Servlet的destroy()方法,通常在关闭Web应用时销毁Servlet。

四. load-on-startup 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 的initParam属性来指定
  • 通过在web.xml文件的<servlet.../>元素中添加<init-param.../>指定

访问Servlet参数通过servletConfig对象完成,ServletConfig提供如下方法。

String getInitParamter(String name):用于获取初始化参数

六. 使用Servlet作为控制器

在标准的Java EE的MVC设计模式中Servlet仅作为控制器使用。JSP作为表现层技术,其作用有两点

  • 负责收集用户请求参数
  • 将应用的处理结果,状态数据呈现给用户

servlet仅充当控制器角色,它的作用类似于调度员;所有用户请求都发给Servlet,Servlet调用Model来处理用户请求,并调用JSP来呈现处理结果;或者Servlet直接调用JSP将应用的状态数据呈现给用户

 model通常由JavaBean充当,所有业务逻辑,数据访问逻辑都在model中实现。事实上,隐藏在Model下的可能还有很多丰富的组件,例如dao组件,领域对象等,下面介绍了一个使用Servlet作为控制器的MVC应用,该应用演示了一个简单的登录验证。

<%@ page contentType="text/html;charset=UTF-8" language="java"  errorPage="" %>
<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>
请输入用户名和密码:<br/>
<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="登录">
</form>
</body>
</html>
package java.gdut.servlet;

import javax.servlet.RequestDispatcher;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.ResultSet;

@WebServlet(name = "login",urlPatterns = "/login")
public class LoginServlet extends javax.servlet.http.HttpServlet {
    protected void service(javax.servlet.http.HttpServletRequest request,
                           javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        String errMsg = "";
        RequestDispatcher rd;
        String username = request.getParameter("username");
        String pass = request.getParameter("pass");
        try{
            DbDao db = new DbDao("jdbc:mysql://localhost:3306/tb_test","com.mysql.jdbc.Driver","sherman","a123");
            ResultSet rs = db.querry("select pass from user_inf where name=?",username);
            if(rs.next()){
                if(rs.getString("pass").equals(pass)){
                    HttpSession session = request.getSession(true);
                    session.setAttribute("name",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);
        }
    }


}
package java.gdut.servlet;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

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

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

    public String getUrl() {
        return url;
    }

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

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPass() {
        return pass;
    }

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

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

    /**
     * 执行插入
     * @param sql
     * @param args
     * @return
     * @throws Exception
     */
    public boolean insert(String sql,Object... args) throws Exception{
        PreparedStatement prst = getConn().prepareStatement(sql);
        for (int i = 0; i <args.length ; i++) {
            prst.setObject(i+1,args[i]);
        }
        if(prst.executeUpdate() != 1){
            return false;
        }

        return true;
    }

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

    public void modify(String sql,Object... args)throws Exception{
        PreparedStatement prst = getConn().prepareStatement(sql);
        for (int i = 0; i < args.length; i++) {
            prst.setObject(i+1,args[1]);
        }
        prst.executeUpdate();
        prst.close();
    }

    public void closeConn()throws Exception{
        if(null != conn && !conn.isClosed()){
            conn.close();
        }
    }


}

 

猜你喜欢

转载自www.cnblogs.com/yumiaoxia/p/9032758.html