java从入门到精通----servlet07

1.http协议 (了解)

(1)什么是http协议?

是一种网络应用层协议、规定了浏览器与web服务器之间如何 通信以及相应的数据包的格式。

1)如何通信?

step1.建立连接
step2.发送请求
step3.发送响应
step4.关闭连接

这样做的好处是,服务器可以利用有限的连接数为尽可能
多的请求服务。

java从入门到精通----servlet07java从入门到精通----servlet07

2)数据包的格式

a.请求数据包

请求行(请求方式 请求资源路径 协议和版本)
若干消息头
    消息头是一些键值对,使用": "隔开,通信的
    双方可以借助于消息头来传递一些特定的信息,比如
    浏览器可以发送"user-agent"消息头,告诉服务器
    浏览器的类型和版本。
实体内容
    如果请求类型为get,实体内容为空。
    只有当请求类型为post时,实体内容才会有数据。

b.响应数据包

状态行(协议类型和版本 状态码 状态描述)
    注:
        状态码是一个三位数字,表示服务器处理请求
        的一种状态,常见状态码如下:
        200: 正常
        500: 系统出错
        404: 请求路径出错
若干消息头
    服务器也可以发送一些消息头给浏览器,比如,发送
    content-type消息头,告诉浏览器,服务器返回的数据类型(包括编码)

c.实体内容

程序的处理结果,浏览器会解析出来,生成相应的页面。

(2)两种请求方式

1)哪些情况下,浏览器会发送get请求?

a.直接在浏览器地址栏输入地址。
b.点击链接。
c.表单的默认提交方式。

2)get请求的特点

a.会将请求参数显示在浏览器地址栏,不安全。
注:
    因为有些网络设备(比如路由器)会记录访问地址。
b.会将请求参数添加到请求资源路径的后面,只能提交
少量的数据给服务器。
注:
    因为请求行大约只能存放2k左右的数据。

3)哪些情况下,浏览器会发送post请求

a.设置表单的method属性值为"post"。    

4)post请求的特点

a.不会将请求参数显示在浏览器地址栏,相对安全。
注:
    http协议并不会对数据进行加密,所以,对于
    敏感数据,需要进行加密处理(使用https协议)。

b.将请求参数添加到了实体内容里面,可以提交大量的
数据给服务器。

2.Servlet输出中文需要注意的问题

(1)为什么会产生乱码?

因为out.println方法默认会使用"iso-8859-1"来编码。

(2)如何解决?

response.setContentType("text/html;charset=utf-8");

3.读取请求参数值

(1)String getParameter(String paramName)

a.请求参数名(paramName)要与实际传递过来的请求
参数名一致,否则会获得null值。
b.提交表单时,如果不填写任何数据,会获得""。

(2)String[] getParamterValues(String paramName)

a.当有多个请求参数名相同时,使用此方法。
b.对于多选框,如果不选择任何选项,会获得null值。

4.表单包含有中文参数值,如何处理?

(1)为什么会产生乱码?

提交表单时,浏览器会对表单中的中文参数值进行编码,比如 使用utf-8来编码,服务器端默认会使用iso-8859-1来解码,所以会产生乱码。

注:
    浏览器会按照打开该表单所在页面时的字符集来编码。

(2)如何解决?

1)post请求

request.setCharacterEncoding("utf-8");

注:
    此行代码要添加到所有的getParameter方法的最前面。
    只针对post请求有效。

2)get请求

修改tomcat的配置文件(server.xml)

<Connector URIEncoding="utf-8"/>
注:
    只针对get请求有效。

5.访问数据库

step1.导包

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>

step2.添加jdbc.properties文件。

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jsd1807db?useUnicode=true&characterEncoding=UTF-8
username=root
password=root

step3.添加DBUtils类。

public class DBUtils {
private static String driver;
private static String url;
private static String username;
private static String password;

private static BasicDataSource dataSource;

static {
    Properties prop = new Properties();
    InputStream ips = DBUtils.class
        .getClassLoader()
        .getResourceAsStream("jdbc.properties");
    try {
        prop.load(ips);
        driver = prop.getProperty("driver");
        url = prop.getProperty("url");
        username = prop.getProperty("username");
        password = prop.getProperty("password");

        //创建数据源对象
        dataSource = 
                new BasicDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setInitialSize(3);
        dataSource.setMaxActive(3);

    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            ips.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
public static Connection getConn() 
        throws Exception {
    return dataSource.getConnection();
}
public static void close(Connection conn,
        Statement stat, ResultSet rs) {
    try {
        if(rs!=null) {
            rs.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    try {
        if(stat!=null) {
            stat.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    try {
        if(conn!=null) {
            //打开自动提交
            conn.setAutoCommit(true);
            conn.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
        }
    }
}

step4.添加一张表(t_user)

create table t_user(
    id int primary key auto_increment,
    username varchar(50) unique,
    password varchar(20),
    email varchar(30)
);

step5.在service方法里面,使用jdbc api访问数据库

public class AddUserServlet extends HttpServlet{

@Override
protected void service(
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, 
        IOException {

    //处理表单中文参数值的问题
    request.setCharacterEncoding("utf-8");

    /*
     * 这行代码的作用:
     * 1.设置content-type消息头的值。
     * 2.out.println方法在输出时,会使用
     * charset指定的字符集来编码。
     */
    response.setContentType(
            "text/html;charset=utf-8");
    PrintWriter out = 
            response.getWriter();

    //读取用户信息
    String username = 
            request.getParameter("username");
    String pwd = 
            request.getParameter("pwd");
    String email = 
            request.getParameter("email");

    //将用户信息插入到数据库
    Connection conn = null;
    PreparedStatement ps = null;
    try {
        conn = DBUtils.getConn();
        String sql = "INSERT INTO t_user "
                + "VALUES(null,?,?,?)";
        ps = conn.prepareStatement(sql);
        ps.setString(1, username);
        ps.setString(2, pwd);
        ps.setString(3, email);
        ps.executeUpdate();
        out.println("添加成功");

    } catch (Exception e) {
        /*
         * step1.记日志(保留现场)
         * 注:
         *   在实际项目中,经常需要将异常
         * 信息写到文件里面。
         */
        e.printStackTrace();
        /*
         * step2.看异常能否恢复,如果
         * 异常不能够恢复(比如数据库服务
         * 停止、网络中断等等,这样的异常
         * 我们一般称之为系统异常),则提示
         * 用户稍后重试;
         * 如果能够恢复,则立即恢复。
         */
        out.println("系统繁忙,稍后重试");

    }finally {
        DBUtils.close(conn, ps, null);
        }
    }
}