主线3:Javaweb

102 阅读26分钟

前情回顾

1.什么是API:

①API是应用程序编程接口(Application Programming Interface); ②其包括源码,字节码和帮助文档(注意版本号一致)。

2.JavaSE和JavaEE:

① JavaSE: <1>javaSE是java的标准版本,有一套基本类库; <2>源码储存在JAVA_HOME\src.zip下; <3>字节码储存在JRE_HOME\lib\rt.jar下; ②JavaEE: <1>javaEE是java的企业版本,有一套企业项目类库;

3.B/S架构和C/S架构:

C/S架构:

<1>C/S架构是Client/Server(客户端/服务器);(APP) <2>C/S架构优缺点: 优点: ①速度快,用户体验好; ②大部分数据继承到客户端,相对安全; 缺点: ①升级时升级部分较多; ②需要安装特定的软件,才能访问服务器。

B/S架构:

<1>B/S架构是Browser/Server(浏览器/服务器);(网页); <2>B/S架构优缺点: 优点: ①无需安装,有浏览器就行; ②升级仅需要升级服务器端; 缺点: ①所有数据继承在服务器端,相对不安全; ②速度慢,用户体验差;

Servlet

"serv"代表服务器端,“let”代表小程序; 本机IP地址为:127.0.0.1或者localhost;

1.准备工作

配置环境变量:

①新建JAVA_HOME变量,值为jdk安装路径; ②将①加入到path中; ③新建CATALINA_HOME变量,值为Tomcat安装路径; ④将③加入到path中。

Tomcat:

①Tomcat 服务器是一个免费的开放源代码的Web 应用服务器; ②Tomcat的开启和关闭: 开启:TomcatX/bin/startup.bat(windows),startup.sh(linux); 关闭:TomcatX/bin/shutdown.bat(windows),shutdown(linux);

2.开发过程

(1)文本文件开发流程:

搭架:

①在任意处建立文件夹; ②在文件夹内可建立html等前端文件夹存放前端文件; ③在文件夹内建立WEB-INF文件夹(必须); ④WEB-INF中必须包含: <1>classes文件夹:用于存放字节码文件; <2>lib文件夹:用于存放jar包; <3>web.xml文件:存放“书写规范”;

web.xml文件书写规范:

<servlet>
	<servlet-name>(实现类变量)</servlet-name>
	<servlet-class>(实现类路径)</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>(实现类变量)</servlet-name>
	<url-pattern>(/+别名)</url-pattern>
</servlet-mapping>

部署:

将总文件夹拷贝到TomcatX/webapps包下;

访问:

<1>startup操作运行tomcat; <2>访问localhost:8080/(文件夹名+路径名)。

(2)Servlet接口:

Servlet接口:(javax.servlet.Servlet)

①Tomcat服务器下的lib文件有一个jar包存放Servlet接口; ②Http服务器只能调用【动态资源文件】,即Servlet的实现类;

HttpServlet抽象类:

①HttpServlet是一个抽象类,是Servlet的子类; ②与Servlet的对比: <1>Servlet是一个接口,调用需实现内部的五个抽象方法; <2>HttpServlet是一个抽象类,调用它仅需重写内部的service()方法; <3>HttpServlet相比Servlet的好处:降低接口中实现类的难度; 其同时也是抽象类相比接口的好处。

(3)Servlet对象的生命周期:

概述:

①其实现类实例对象仅能由Http服务器创建; ②默认情况下,Http服务器收到Servlet第一个请求时创建实例对象; ③Http运行时,一个Servlet仅能创建一个实例对象(进程),不同用户访问是多线程; ④Http关闭时,自动将所有的Servlet对象销毁。

修改创建实例对象时机为网页开启执行:

<servlet>
	...
	<load-on-startup>(大于0的整数)</load-on-startup>
</servlet>

(4)HttpServletResponse接口:

HttpServletResponse概述:

①该接口来自于Servlet接口中; ②该接口实现类由Http服务器负责提供; ③负责将doGet或doPost等方法写入响应体并交给浏览器。

HttpServletResponse功能:

①将相应结果以二进制写入响应体: print和write的对比: <1>write()方法会把传入的int类型数据转换为ASCII码对应字符; <2>print()方法会正常输出传入的int类型数据。

protected void doGet(HttpServletResponse response,HttpServletRequest){
	//执行结果
	String result = "...";	
	//拿到输出流
	PrintWriter pw = response.getWriter();	
	//用write(...)将执行结果打印到浏览器
	pw.write(result);
	
	//用print(...)将执行结果打印到浏览器
	pw.print(result);			
}

②修改输出到浏览器的编译模式: 在拿到输出流前:

//可以在浏览器上打印html语句
response.setContentType("text/html");

//可以在浏览器上打印中文
response.setContentType("text;charset=utf-8");

③控制浏览器向指定服务器发送请求:

response.sendRedirect("(网址路径)");

(5)HttpServletRequest接口:

HttpServletRequest概述:

①来自Servlet接口中; ②该接口的实现类由Http负责提供; ③该接口负责在doGet()或者doPost()方法运行时读取Http协议包中的信息。

HttpServletRequest功能:

①读取Http协议包中【请求行】信息;

//读取URL信息
String url = request.getRequestURL().toString();
//读取method信息
String method = request.getMethod();
//读取URI信息(URL的字符串截取)
String uri = request.getRequestURI();

②读取请求对象获得【请求头】中请求参数和名称;

//获得所有参数名称(返回枚举类)
Enumeration paramNames = request.getParameterNames();
//遍历枚举类(类似迭代器遍历集合)
while(paramNames.hasMoreElements()){
	String paramName = (String)paramNames.nextElement();
	//获取请求参数值
	String value = request.getParameter(paramName);
}

③从【请求体】中获取参数信息:(doPost()方式)

//获取参数值
String value = request.getParameter(paramName);

④修改请求体的解码方式为utf-8:

request.setCharacterEncoding("utf-8");

Response和Request生命周期:

①在Http服务器接收到浏览器发送到“请求协议包”时,自动生成一个【请求对象】和一个【响应对象】; ②在Http调用do..()方法时。负责将【请求对象】和【响应对象】作为实参传入方法中; ③在do..()方法后,Tomcat服务器负责将其二者销毁。

(6)互联网通信详解(B/S架构):

B/S架构简图 在这里插入图片描述 互联网通信图 在这里插入图片描述

(7)项目实战----考试信息管理系统

<1>.项目架构:

任务: 在线考试管理吸系统----用户信息管理模块 分支任务: > 用户信息注册 >用户信息查询 > 用户信息删除 > 用户信息更新 文件架构:

准备工作: 1.创建用户信息表 t_users.frm

 drop table if exists t_users;
    create table t_users(
        userId int primary key auto_increment,       #用户编号(自增操作)
        userName varchar(255),        #用户名称
        password varchar(255),        #用户密码
        sex      varchar(10),             #用户性别
        email    varchar(255)         #用户邮箱
    )

2.插入用户信息

insert into t_users(userName,password,sex,email)
    values('shawn','666','man','shawn@126.com');
    ...

3.新建一个实体类Users(entity包下)。

public class Users {
    //用户实体类的属性
    private Integer userId;
    private String userName;
    private String password;
    private String sex;
    private String email;

    //构造方法(无参)
    public Users(){}

    //构造方法(有参)
    public Users(Integer userId,String userName,String password,String sex,String email){
        this.userId = userId;
        this.userName = userName;
        this.password = password;
        this.sex = sex;
        this.email = email;
    }

    //set方法和get方法
    public void setUserId(Integer userId){
        this.userId = userId;
    }

    public Integer getUserId(){
        return userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

4.web下WEB-INF目录下,创建lib文件夹,存放mysql提供的JDBC实现jar包。

<2>注册功能实现:

a.前端网页代码(user_Add.html):
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>UserTestInformationManage_System</title>
</head>
<body>
    <center>
        <form action="/myWeb/user/add" method="get">
            <table border="2">
                <tr>
                    <td>用户姓名</td>
                    <td><input type="text" name="userName"/></td>
                </tr>
                <tr>
                    <td>用户密码</td>
                    <td><input type="password" name="password"/> </td>
                </tr>
                <tr>
                    <td>用户性别</td>
                    <td>
                        <input type="radio" name="sex" value="男"/><input type="radio" name="sex" value="女"/></td>
                </tr>
                <tr>
                    <td>用户邮箱</td>
                    <td><input type="text" name="email"/> </td>
                </tr>
                <tr>
                    <td><input type="submit" value="用户注册"/> </td>
                    <td><input type="reset" name="重置"/> </td>
                </tr>
            </table>
        </form>
    </center>
</body>
</html>

效果: 在这里插入图片描述

b.在UserDao类中书写插入数据的JDBC代码(dao包下):
package com.shawnWeb.dao;

import com.shawnWeb.entity.Users;

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

public class UserDao2 {
    public UserDao2(){}

    public int add(Users users){
        Connection conn = null;
        PreparedStatement ps = null;
        int result = 0;

        String url = "jdbc:mysql://localhost:3306/bjpowernode";
        String user = "root";
        String password = "123456";

        //注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //获取数据库连接
            conn = DriverManager.getConnection(url,user,password);
            //获取数据库操作对象
            String sql = "insert into t_users(userName,password,sex,email)"+
                    " values(?,?,?,?)";
            ps = conn.prepareStatement(sql);
            //给?传值
            ps.setString(1,users.getUserName());
            ps.setString(2,users.getPassword());
            ps.setString(3,users.getSex());
            ps.setString(4,users.getEmail());

            //执行sql语句
            result = ps.executeUpdate();

            //
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if (ps != null){
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            return result;
        }
    }
}
c.书写doGet(...)方法(模拟互联网通信流程):
package com.shawnWeb.controller;

import com.shawnWeb.dao.UserDao2;
import com.shawnWeb.entity.Users;

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

public class UserAddServlet2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userName,password,sex,email;
        //创建User对象,用于存储从浏览器传送过来的用户信息
        Users user = null;
        //创建Dao对象,用于下述调用注册方法
        UserDao2 dao2 = new UserDao2();
        //插入数据的返回值
        int result = 0;
        //创建输出流,便于将结果打印到浏览器中
        PrintWriter out = null;

        //1.调用请求对象读取请求头参数信息,得到用户的信息
        userName = request.getParameter("userName");
        password = request.getParameter("password");
        sex = request.getParameter("sex");
        email = request.getParameter("email");

        //2.使用JDBC将用户信息填充到MySQL数据库
        //将用户信息存储到user中
        user = new Users(null,userName,password,sex,email);
        result = dao2.add(user);
        //3.调用响应对象将处理结果以二进制形式传入响应体中
        //更该浏览器的编码方式,以便能编译其html和中文
        response.setContentType("text/html;charset=utf-8");
        //拿到响应器的输出流
        out = response.getWriter();
        if (result == 1){
            out.print("<font style='color:red;font-size:40'>用户信息注册成功</font>");
        }else{
            out.print("<font style='color:red;fond-size:40'>用户信息注册失败</font>");
        }

    }
    //doGet结束后,Tomcat负责销毁请求对象和响应对象
    //tomcat负责将HTTP协议包推送到发起请求的浏览器上
    //浏览器根据响应头content-type指定编译器对响应体二进制内容编辑
    //浏览器将编辑后的结果在窗口中展示给用户  【互联网通信结束】
}
结果展示:

Ⅰ.在输入框输入注册数据: 在这里插入图片描述 Ⅱ.点击用户注册按钮,弹出注册成功: 在这里插入图片描述 Ⅲ.打开数据库中的t_users表,验证数据插入: 在这里插入图片描述 Ⅳ.插入数据成功,插入功能实现完毕!

改进方案(书写jdbc工具类):

jdbc工具类JDBC_Util:(util包下)

package com.shawnWeb.util;

import java.sql.*;

public class JDBC_Util {
    /*
    工具类中的构造方法都是私有化的,目的是为了防止new对象,因为工具中的方法都是
    静态的,不需要new对象,为了方便起见。
     */
    private JDBC_Util(){}


    //注册驱动(在一个没有结束的程序中,静态代码块内容只执行一次)
    static {
        try{
            Class.forName("com.mysql.jdbc.Driver");
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    //获取数据库连接
    public static Connection createConnection() throws SQLException{
        String url = "jdbc:mysql://localhost:3306/bjpowernode";
        String user = "root";
        String password = "123456";


        Connection conn = DriverManager.getConnection(url,user,password);
        return conn;
    }

    public static void close(Connection conn, Statement stmt, ResultSet rs){
        if (rs != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (stmt != null){
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

JDBC_Util类的使用:(dao包下)

package com.shawnWeb.dao;

import com.shawnWeb.entity.Users;
import com.shawnWeb.util.JDBC_Util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class UserDao {
    //构造方法
    public UserDao(){}
    //用户注册方法
    public int add(Users user){
        Connection conn = null;
        PreparedStatement ps = null;
        int result = 0;
        try {
            //getConnection方法执行时,注册驱动和获取数据库连接操作都已完成;
            conn = JDBC_Util.createConnection();
            //3.获取数据库操作对象
            String sql = "insert into t_users(userName,password,sex,email) values(?,?,?,?)";
            ps = conn.prepareStatement(sql);
            //给?处传值
            ps.setString(1,user.getUserName());
            ps.setString(2,user.getPassword());
            ps.setString(3,user.getSex());
            ps.setString(4,user.getEmail());

            //4.执行SQL语句
            result = ps.executeUpdate();
            //5.处理结果集(由于是增添操作,无需处理结果集)

        }catch(SQLException e){
            e.printStackTrace();
        }finally{
            //6.关闭释放资源
            JDBC_Util.close(conn,ps,null);
        }
        return result;
    }
}

<3>查询注册信息实现:

a.创建出类UserFindServlet:(controller包下)
b.配置xml文件:(web.xml)
<servlet>
        <servlet-name>UserFindServlet</servlet-name>
        <servlet-class>com.shawnWeb.controller.UserFindServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>UserFindServlet</servlet-name>
        <url-pattern>/user/find</url-pattern>
    </servlet-mapping>
c.实现findAll()方法:()(dao包下)
//查询所有用户信息方法
    public List findAll(){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        //创建一个List集合返回所有用户信息
        List<Users> usersList = new ArrayList <>();
        try {
            //注册驱动和获取数据库连接
            conn = JDBC_Util.createConnection();
            //获取数据库操作对象
            String sql = "select * from t_users";
            ps = conn.prepareStatement(sql);
            //执行SQL语句
            rs = ps.executeQuery();
            //处理结果集
            while(rs.next()){
                Integer userId = rs.getInt("userId");
                String userName = rs.getString("userName");
                String password = rs.getString("password");
                String sex = rs.getString("sex");
                String email = rs.getString("email");
                //将以上数据存入实体类
                Users users = new Users(userId,userName,password,sex,email);
                //将所有users传入List集合中
                usersList.add(users);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBC_Util.close(conn,ps,rs);
        }
        return usersList;
    }
d.补充UserFindServlet类:(controller包下)
package com.shawnWeb.controller;

import com.shawnWeb.dao.UserDao;
import com.shawnWeb.entity.Users;

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

public class UserFindServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //初始化变量区
        UserDao dao = new UserDao();
        PrintWriter out = null;

        //[调用DAO]将查询命令推送到数据库服务器上,得到所有用户信息【List】
        List<Users> usersList = dao.findAll();
        //【调用响应对象】将用户信息结合<table>标签以二进制写入响应体
        response.setContentType("text/html;charset=utf-8");
        out = response.getWriter();
        out.print("<table border='2' align='center'>");
        out.print("<tr>");
        out.print("<td>用户编号</td>");
        out.print("<td>用户姓名</td>");
        out.print("<td>用户密码</td>");
        out.print("<td>用户性别</td>");
        out.print("<td>用户邮箱</td>");
        out.print("<td>删除操作</td>");
        out.print("<td>修改数据</td>");
        out.print("</tr>");

        for (Users users:usersList){
            out.print("<tr>");
            out.print("<td>"+users.getUserId()+"</td>");
            out.print("<td>"+users.getUserName()+"</td>");
            out.print("<td>******</td>");
            out.print("<td>"+users.getSex()+"</td>");
            out.print("<td>"+users.getEmail()+"</td>");
            out.print("<td><a href='/myWeb/user/delete?userId="+users.getUserId()
                    +"'>删除用户</a></td>");
        }
        out.print("</table>");
        
    }
}

查询注册信息功能完毕!

(4)浏览界面的实现:

Ⅰ.制作标题:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body style="background-color:green">
<center>
    <font style="color: red;font-size: 40px">在线考试管理系统</font>
</center>
</body>
</html>

Ⅱ.制作索引页:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        <li>用户信息管理
            <ol>
                <li><a href="/myWeb/user_Add.html" target="right">用户信息注册</a></li>
                <li><a href="/myWeb/user/find" target="right">用户信息查询</a></li>

            </ol>
        </li>
        <li>试题信息管理</li>
        <li>在线考试管理</li>
    </ul>
</body>
</html>

Ⅲ.主页面书写:


<html >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<frameset rows="15%,85%">
    <frame name="top" src="/myWeb/top.html"/>
    <frameset cols="15%,85%">
        <frame name="left" src="/myWeb/left.html"/>
        <frame name="right">
    </frameset>
</frameset>
</html>
网页实现效果:

在这里插入图片描述

查询注册结果演示:

在这里插入图片描述

(5)删除数据功能实现

a.创建出UserDeleteServlet类:(controller包下)
b.配置xml文件:(web.xml文件下)
<servlet>
        <servlet-name>UserDeleteServlet</servlet-name>
        <servlet-class>com.shawnWeb.controller.UserDeleteServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>UserDeleteServlet</servlet-name>
        <url-pattern>/user/delete</url-pattern>
    </servlet-mapping>
    <servlet>
c.实现delete()方法:(dao包下)
//删除选定编号的用户信息方法
    public int delete(String userId){
        //初始化参数
        Connection conn = null;
        PreparedStatement ps = null;
        int result = 0;


        try {
            //注册驱动+获取数据库连接
            conn = JDBC_Util.createConnection();
            //获取数据库操作对象
            String sql = "delete from t_users where userId=?";
            ps = conn.prepareStatement(sql);
            //给?处传值
            ps.setString(1,userId);
            //执行SQL语句
            result = ps.executeUpdate();
            //无需处理结果集

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally{
            //释放资源
            JDBC_Util.close(conn,ps,null);
        }
        return result;
    }
d.补全UserDeleteServlet类:(controller包下)
package com.shawnWeb.controller;

import com.shawnWeb.dao.UserDao;

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

public class UserDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userId = null;
        PrintWriter out = null;
        UserDao dao = new UserDao();
        int result = 0;
        //调用请求对象,读取请求头中的”用户编号“参数
        userId = request.getParameter("userId");
        //调用【DAO】将用户编号填充到delete命令并发送到数据库服务器
        result = dao.delete(userId);
        //【调用响应对象】将处理结果以二进制写入响应体,交给浏览器
        response.setContentType("text/html;charset=utf-8");
        out = response.getWriter();
        if (result == 1){
            out.print("<font style='color:red;font-size:40'>用户信息删除成功</font>");
        }else{
            out.print("<font style='color:red;font-size:40'>用户信息删除失败</font>");
        }
    }
}

删除功能结果演示:

Ⅰ.查询注册用户信息操作页面 在这里插入图片描述 Ⅱ.点击Adam后面的删除: 在这里插入图片描述 Ⅲ.删除后查询结果演示: 在这里插入图片描述 删除功能实现完毕!

(6)登录功能实现:

a.制作登录界面和登录失败界面:(web包下)

登陆界面:(login.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<center>
    <form action="/myWeb/login" method="post">
        <table border="2">
            <tr>
                <td>登录名称</td>
                <td><input type="text" name="userName"/></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><input type="password" name="password"/></td>
            </tr>
            <tr>
                <td><input type="submit" name="登录"/></td>
                <td><input type="reset" name="重置"/></td>
            </tr>
        </table>
    </form>
</center>
</body>
</html>

登录失败界面:(login_error.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<center>
    <font style="color:red;font-size: 30px">登录信息有误,请重新登陆</font>
    <form action="/myWeb/login" method="post">
        <table border="2">
            <tr>
                <td>登录名称</td>
                <td><input type="text" name="userName"/></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><input type="password" name="password"/></td>
            </tr>
            <tr>
                <td><input type="submit" name="登录"/></td>
                <td><input type="reset" name="重置"/></td>
            </tr>
        </table>
    </form>
</center>
</body>
</html>
b.创建LoginServlet类:(controller包下)
c.配置xml文件:(web.xml文件下)
<servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.shawnWeb.controller.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
d.实现login方法:(dao包下)
//登陆验证方法
    public int login(String userName,String password){
        //准备参数
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        int result = 0;
        String sql = "select count(*) from t_users where userName=? and password=?";


        try {
            //注册驱动+获取数据库连接
            conn = JDBC_Util.createConnection();
            //获取数据库操作对象
            ps = conn.prepareStatement(sql);
            //给?处传值
            ps.setString(1,userName);
            ps.setString(2,password);
            //执行SQL语句
            rs = ps.executeQuery();
            //处理结果集
            while(rs.next()){
                result = rs.getInt("count(*)");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally{
            //释放资源
            JDBC_Util.close(conn,ps,rs);
        }
        return result;
    }
e.补充LoginServlet类:(controller包下)
package com.shawnWeb.controller;

import com.shawnWeb.dao.UserDao;

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

public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //准备变量
        String userName,password;
        UserDao dao = new UserDao();
        int result = 0;
        //调用请求对象对请求体使用utf-8字符集进行重新编辑
        request.setCharacterEncoding("utf-8");
        //调用请求信息读取请求体参数信息
        userName = request.getParameter("userName");
        password = request.getParameter("password");
        //调用dao将查询验证信息推送到数据库服务器上
        result = dao.login(userName,password);
        //调用响应对象,根据验证结果将不同资源文件地址写入响应头中,交给浏览器
        if (result == 1){
            response.sendRedirect("/myWeb/index.html");
        }else{
            response.sendRedirect("/myWeb/login_error.html");
        }
    }
}

登录成果展示:

Ⅰ.登录界面: 在这里插入图片描述 Ⅱ.输入已注册的账号密码: 在这里插入图片描述 Ⅲ.点击提交,跳转至初始界面: Ⅳ.输入未注册的账号密码: Ⅴ.跳转到login_error.html页面: 在这里插入图片描述 登录功能实现完毕!

(7)修改密码功能实现:

a.修改密码界面:(updatePassword.html)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>updatePassword_Page</title>
</head>
<body>
<center>
    <form action="/myWeb/updatePassword" method="get">
        <table border="2">
            <tr>
                <td>用户名</td>
                <td><input type="text" name="userName"/></td>
            </tr>
            <tr>
                <td>用户密码</td>
                <td><input type="password" name="oldPassword"/> </td>
            </tr>

            <tr>
                <td>新密码</td>
                <td><input type="password" name="newPassword"/> </td>
            </tr>
            <tr>
                <td><input type="submit" value="修改密码(●'◡'●)"/> </td>
                <td><input type="reset" name="重置"/> </td>
            </tr>
        </table>
    </form>
</center>
</body>
</html>
b.在主页面添加修改密码界面:(left.html)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        <li>账号安全管理
            <ol>
                <li><a href="login.html" target="right">登录</a></li>
                <li><a href="updatePassword.html" target="right">修改密码</a></li>
            </ol>
        </li>
        <li>用户信息管理
            <ol>
                <li><a href="/myWeb/user_Add.html" target="right">用户信息注册</a></li>
                <li><a href="/myWeb/user/find" target="right">用户信息查询</a></li>

            </ol>
        </li>
        <li>试题信息管理</li>
        <li>在线考试管理</li>

    </ul>

</body>
</html>
3.建立实体类updatePassword类:(cotroller包下)
4.在xml文件中配置updatePassword类的服务器:(web.xml)
<servlet>
        <servlet-name>updatePassword</servlet-name>
        <servlet-class>com.shawnWeb.controller.updatePassword</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>updatePassword</servlet-name>
        <url-pattern>/updatePassword</url-pattern>
    </servlet-mapping>
5.在dao文件中实现updatePassword方法:(dao包下)
//修改密码方法
    public int updatePassword(String userName,String oldPassword,String newPassword){
        //初始化变量区
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;//储存账号密码验证信息
        int result1 = 0;//存储账号密码验证信息
        int result2 = 0;//存储更新密码的返回值
        String isLoginSQL = "select count(*) from t_users where userName=? and password=?";
        String sql = "update t_users set password=? where userName=?";

        try {
            //注册驱动+获得数据库连接
            conn = JDBC_Util.createConnection();
            //获取数据库操作对象
            ps = conn.prepareStatement(isLoginSQL);
            //给?处传值
            ps.setString(1,userName);
            ps.setString(2,oldPassword);
            //执行SQL语句
            rs = ps.executeQuery();
            //处理结果集
            while(rs.next()){
                result1 = rs.getInt("count(*)");
            }
            //当result1返回1时,证明登录成功,即获得改密码权限
            if (result1 == 1){
                //再次获得数据库操作对象
                ps = conn.prepareStatement(sql);
                //给?处传值
                ps.setString(1,newPassword);
                ps.setString(2,userName);
                //执行SQL语句
                result2 = ps.executeUpdate();
                //无需处理结果集
            }else{
                //登录失败
                result2 = 0;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally{
            JDBC_Util.close(conn,ps,rs);
        }
        return result2;
    }
6.补充updatePassword类即可:
package com.shawnWeb.controller;

import com.shawnWeb.dao.UserDao;

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

public class updatePassword extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //初始化变量区
        String userName,oldPassword,newPassword;
        int result;
        UserDao dao = new UserDao();
        PrintWriter out = null;

        //通过【请求头】拿到所需要的数据:用户名,旧密码,新密码
        userName = request.getParameter("userName");
        oldPassword = request.getParameter("oldPassword");
        newPassword = request.getParameter("newPassword");
        //调用【dao】类的updatePassword方法,拿到结果;
        result = dao.updatePassword(userName,oldPassword,newPassword);
        //通过【响应头】在页面中显示修改密码成功
        response.setContentType("text/html;charset=utf-8");
        out = response.getWriter();
        if (result == 1){
            out.print("<font style='color:red;font-size:40'>用户密码修改成功</font>");
        }else{
            out.print("<font style='color:red;font-size:40'>输入信息有误,用户信息修改失败</font>");
        }
    }
}

修改密码结果演示:

进入修改密码页面: 在这里插入图片描述 填写相关信息 错误情况 在这里插入图片描述 正确情况 在这里插入图片描述 修改密码功能实现完毕!

Servlet

1.资源欢迎文件

概念:

访问网页默认弹出的资源叫作==欢迎资源文件==;

默认欢迎资源文件:

位置: Tomcat9/conf/web.xml--->文件末尾 根据下述源码可知,当未设置具体访问资源时,浏览器会默认访问 index.html,index.htm或者index.jsp。 文件。

或者另外两个文件。

	<welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

自行设置欢迎资源文件:

位置: 网站/web/WEB-INF/web.xml 自行设置之后Tomcat自带的默认欢迎文件将失效。 语法规范:

<!----资源名可以是动态资源文件,也可以是静态资源文件---->
<welcome-file-list>
	<welcome-file>(资源名)(login.html)</welcome-file>
</welcome-file-list>

2.状态码

定义: 由三位数字组成的一个符号(100~599); 位置: Http服务器推送【响应包】前,根据处理结果将状态码写入【响应包】的【状态行】上。 作用: 向浏览器通知处理结果或向浏览器解释不能提供服务的原因。 典例: ==①100==:通知资源文件不完整,需要继续索要缺失部分; ==②200==:通知本次资源文件返回完整无缺失; ==③302==:通知本次返回的不是资源内部而是资源的地址,需浏览器根据返回的地址继续索要资源文件; ==④404==:通知B端S端没有定位到被访问文件; ==⑤405==:通知B端S端定位到被访问文件但无法访问(访问方式错误); ==⑥500==:通知B端S端定位到被访问文件,也存在访问方法,但出现了Java语句的异常

3.多个Servlet的调用规则:

(1).重定向的解决方案:

原理:

用户第一次手动访问OneServlet,访问结束时,将TwoServlet地址写入响应头的【location】中,浏览器接收到响应包时,读取到==302==状态,根据【location】发起第二次请求,访问TwoServlet。

特点:

①浏览器至少发送两条请求; ②该方案的请求方式一定是【Get】;

优缺点:

优点: 该方案能调用当前网站资源或站外的其他网站资源; 缺点: 增加了用户等待时间,效率较低。

实现命令:

//根据相应对象设置location属性
response.sendRedirect("(网站名)");
//网站名格式应为/网站名/资源名

(2).请求转发解决方法:

原理:

用户第一次手动访问OneServlet,放完结束后,通过当前请求对象代替浏览器向Tomcat发送请求,申请调用TwoServlet,完成任务即可。

特点:

①浏览器仅仅发送了一次请求(推送了一个请求包) ②请求方式只取决于第一次请求方式保持不变(因为只有一个请求包)

优缺点:

优点: 无论涉及到多少Servlet,仅发出一次请求,减少浏览器与服务器的交互次数。 缺点: 只能调用当前网站下的资源,无法站外调用。

实现命令:

//通过【请求对象】拿到资源文件申请报告对象
//资源文件名格式写为"/jsp”或“/html"格式
RequestDispatcher report = request.getRequestDispatcher("(资源文件名)");
//将报告对象发送给Tomcat服务器
report.forward((当前请求对象),(当前响应对象));

4.多个Servlet的数据共享

(1).ServletContext接口(全文):

概述:

①存在于Servlet规范中,Tomcat中存在【servlet-api.jar】包下; ②如果两个Servlet来自同一个网络,则可通过网站的【ServletContext实例对象】实现数据共享。 ③开发人员习惯将其称为【全局作用域对象】。

特点:

①每个网站都存在一个全局作用域对象(类似于Map采用键值对储存) ②当前网站所有Servlet都可从中获取到相关数据。

生命周期:

http服务器启动时,自动创建一个【全局作用域对象】; ②http服务器运行时,仅有一个【全局作用域对象】存在且一直存活; ③http服务器关闭时,自动销毁【全局作用域对象】。 核心:【全局作用域对象】周期贯穿整个服务器运行期间。

实现命令: 在OneServlet中:

//通过请求对象向Tomcat服务器索要【全局作用域对象】
ServletContext application = request.getServletContext();
//将共享数据添加到【全局作用域对象中】
application.setAttribute("key1",(值));

在TwoServlet中:

//通过请求对象向Tomcat服务器索要【全局作用域对象】
ServletContext application = request.getServletContext();
//从【全局作用域对象】中获取key1所对应的数据
datatype data = application.getAttribute("key1");

(2).Cookie类:

概述:

①存在于Servlet的工具类中,Tomcat中存在的【servlet-api.jar】包下; ②如果两个Servlet来自同一个网站,且为同一个浏览器提供服务,则可通过【Cookie】对象进行数据共享; ③存放私人数据,为提高服务质量。

原理:

用户通过浏览器向网站发送请求申请OneServlet,OneServlet在运行期间会创建一个【Cookie】对象存当前用户的相关数据,工作完毕后,将Cookie写入响应头交还给浏览器。收到响应包后,将Cookie存入缓存,用户通过同一浏览器再次向Two发送请求时,浏览器将Cookie推给请求头发送过去。(类比会员卡机制)

特点:

①Cookie相当于一个Map存储; ②一个Cookie只能存储一个键值对; ③键值对都只能是String类型,key不能是中文。

实现命令: OneServlet中:

//创建一个Cookie对象,存放共享数据
Cookie cookie = new Cookie("key1","abc");
//将Cookie对象交给响应头,交给浏览器
response.addCookie(cookie);

TwoServlet中:

//调用请求对象从请求头拿到浏览器的Cookie
Cookie[] cookieArray = request.getCookies();
//遍历数据拿到每一个Key和value
for(Cookie c:cookieArray){
	String key = c.getName();
	String value = c.getValue();
	...(对Key和Value做处理即可)...
}

(3).补充请求包和响应包:

请求包:

【请求行】组成规则:方法 /url HTTP/版本号 例:GET /xinwen/2018-07/17/content_5307156.htm HTTP/1.1

【请求头】包含了客户端的环境,例:(地址tools.jb51.net/table/http_…)

【请求体】要发送的数据(一般post方式会使用);例:userName=123&password=123&returnUrl=/

响应包:

【响应行】规则:HTTP/版本号 响应码(状态码) 例:HTTP/1.1 200 OK

【响应头】服务器端的信息

【响应体】 显示在浏览器的内容(与响应头配合,显示出来)

(4).Cookie的项目实例(点餐系统):

a.书写欢迎页面index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>订餐系统欢迎页面</title>
</head>
<body>
<center>
    <font style="color:red;font-size:40px">新会员申请开卡</font>
    <form action="/myWeb/one">
        <table border="2">
            <tr>
                <td>用户名</td>
                <td><input type="text" name="userName"/></td>
            </tr>
            <tr>
                <td>预存金额</td>
                <td><input type="text" name="money"/></td>
            </tr>
            <tr>
                <td><input type="submit" value="申请开卡" /></td>
                <td><input type="reset" value="重置"/></td>
            </tr>
        </table>
    </form>
</center>
</body>
</html>

b.创建OneServlet用来识别会员卡,创建TwoServlet用来划卡消费

c.配置web.xml文件(web.xml文件)

<servlet>
        <servlet-name>OneServlet</servlet-name>
        <servlet-class>OneServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>OneServlet</servlet-name>
        <url-pattern>/one</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>TwoServlet</servlet-name>
        <servlet-class>TwoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TwoServlet</servlet-name>
        <url-pattern>/two</url-pattern>
    </servlet-mapping>

d.书写点餐界面order.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<center>
    <font style="color:red;font-size:40px">点餐页面</font>
    <form action="/myWeb/two">
        食物类型:<input type="checkbox" name="food" value="dumpling"/>饺子(30RMB)
        <input type="checkbox" name="food" value="noodles"/>面条(20RMB)
        <input type="checkbox" name="food" value="rice"/>盖浇饭(15RMB)<br/>
        <input type="submit" value="划卡消费">
    </form>
</center>
</body>
</html>

e.补充完整OneServlet与TwoServlet

OneServlet:

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

public class OneServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //初始化变量区
        String userName,money;
        //通过【请求对象】获取到用户的参数信息
        userName = request.getParameter("userName");
        money = request.getParameter("money");
        //创建两个Cookie对象
        Cookie cookie1 = new Cookie("userName",userName);
        Cookie cookie2 = new Cookie("money",money);
        //将Cookie对象存入响应体中
        response.addCookie(cookie1);
        response.addCookie(cookie2);
        //响应体将点餐页面发送给浏览器(请求转发)
        response.sendRedirect("/myWeb/order.html");
    }
}

TwoServlet:

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

public class TwoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //变量初始化区
        int dumpling_money = 30;
        int noodles_money = 20;
        int rice_money = 15;
        int cost = 0;
        int money = 0;
        int balance = 0;
        String userName;
        String[] food = new String[3];
        Cookie[] cookieArray;
        PrintWriter out = null;
        Cookie newCard = null;
        //①读取请求头参数,得到用户点餐类型

        food = request.getParameterValues("food");
        for (String s:food) {
            if ("dumpling".equals(s)) {
                cost += dumpling_money;
            } else if ("noodles".equals(s)) {
                cost += noodles_money;
            } else if ("rice".equals(s)) {
                cost += rice_money;
            }
        }
        //System.out.println(cost);
        //②读取请求头中的Cookie,得到用户会员卡
        cookieArray = request.getCookies();
        //③根据食物类型进行消费处理
        for (Cookie data : cookieArray) {
            String key = data.getName();
            //拿到用户名和预存金额
            String value = data.getValue();

            if ("userName".equals(key)){
                userName = value;
            }else if ("money".equals(key)){
                money = Integer.valueOf(value);
            }
        }
        //System.out.println(money);
        response.setContentType("text/html;charset=utf-8");
        out = response.getWriter();
        if (cost > money){
            balance = money;
            out.print("<font style='color:red;font-size:40px'>对不起,您的余额不足,请充值(●'◡'●)</font>");
        }else{
            balance = money-cost;
            out.print("<font style='color:blue;font-size:40px'>消费成功(●'◡'●),您的卡上余额剩余"+balance+"元!");
        }
        //④将Cookie交还给用户,并将消费记录写入响应体
        newCard = new Cookie("balance",balance+"");
        response.addCookie(newCard);

    }
}

f.结果演示:

登录会员卡: 在这里插入图片描述 点击申请开卡弹出点餐页面: 在这里插入图片描述 将三种食物全选,点击”划卡消费“: 在这里插入图片描述 如果开始开卡钱数不够,则消费失败: 在这里插入图片描述

g.开发过程总结与反思

本次开发过程中,进行了将案例中的单选框改为复选框,认为返回的值应可以依次存储在数组里,比如,我在三种食物处都打上勾,那么会不会将三种食物以字符串形式存入字符串数组里。原代码:

//初始化字符串数组存储食物名称
int dumpling_money = 30;
int noodles_money = 20;
int rice_money = 15;
int cost = 0;
String[] food = new String[10];
for(int i = 0;i < 3;i++){
	//从输入的复选框中拿到选项参数
	food[i] = request.getParameter("food");
	//如果拿到某种食物,则让花费变量cost加上该种食物的价格
	if("dumpling".equals(food[i])){
		cost+=dumpling_money;
	}else if("noodles".equals(food[i])){
		cost+=noodles_money;
	}else if("rice".equals(food[i])){
		cost+=rice_money;
	}
}

后来发现,这种做法仅能用于单选框情况,如果如图代码会将识别到的第一种食物重复算三次。比如三种食物全选,会得到cost最后的值为饺子价格的三倍(30x3)经过查阅资料,对多选框得到了下面这种解法:

int dumpling_money = 30;
int noodles_money = 20;
int rice_money = 15;
int cost = 0;
Stirng[] food = new String[10];
//直接通过getParameterValues方法拿到整个复选框字符串数组
food = request.getParameterValues("food");
		//再去遍历这个字符串数组,即可拿到多选的每个食物
        for (String s:food) {
            if ("dumpling".equals(s)) {
                cost += dumpling_money;
            } else if ("noodles".equals(s)) {
                cost += noodles_money;
            } else if ("rice".equals(s)) {
                cost += rice_money;
            }
        }

同理,这种代码写法如果三种食物全选时,cost最后的值为三种食物的价格总和(30+20+15),结果合理。

(5).HttpSession接口(会话):

概述:

①存在于Servlet规范中,Tomcat中存在servlet-api.jar中,Tomcat提供了实现类; ②如果两个Servlet来自于同一个网站,且为同一个浏览器提供服务,则可通过HttpSession实现类对象进行数据共享; ③开发人员习惯将其成为【会话作用域对象】。

Session和Cookie的对比:

①Cookie存在于客户端计算机内存; 而Session存在于服务端计算机的内存中; ② Cookie对象仅能存储String类型数据; 而Session实现类对象可以存储任意类型; ③一个Cookie对象只能存一个共享数据; 而Session实现类对象用map进行储存,可存任意数量的对象; ④Cookie相当于用户服务端的【会员卡】; 而Session相当于服务端的【私人保险柜】。

命令实现: OneServlet中:

以下两种方法的区别: 前者:如果用户存在已有的【私人保险柜】,返回对应的【私人保险柜】 如果用户不存在【私人保险柜】,tomcat会创建一个全新的【私人保险柜】。 后者:如果用户存在已有的【私人保险柜】,返回对应的【私人保险柜】 如果用户不存在【私人保险柜】,tomcat拒绝服务,直接返回null。

//调用【请求对象】向Tomcat索要Session
HttpSession session = request.getSession();
//或者
HttpSession session = request.getSession(false);

//将数据添加到【私人保险柜】Session对象中
session.setAttribute("key1",data);

TwoServlet中:

//调用【请求对象】向Tomcat索要Session
HttpSession session = request.getSession();
//从【会话作用域对象】中获取共享数据
Object data = session.getAttribute("key1");

Session的销毁时机:

①用户与Session关联时使用的Cookie仅存在于缓存中; ②浏览器关闭时,Session与用户的联系被切断; ③Tomcat无法得知浏览器是否关闭,所以浏览器关闭时Tomcat并不会销毁Session; ④为了解决③中的问题,Tomcat设置了默认的【空闲时间】30min,到时间后自动销毁Session。 ⑤也可手动设置Session实现类对象的销毁时机。

手动设置Session的销毁时机: (在web.xml下)

<!---手动设置5分种后销毁Session实现类对象--->
<session-config>
	<session-timeout>5</session-timeout>
</session-config>

(6).HttpServletRequest接口(请求):

概述:

①两个Servlet通过【请求转发】互相调用,彼此共享一个请求协议包,此时可共享数据; ②开发人员将其对象叫作【请求作用域对象】。

命令实现: OneServlet中:

//将数据存入【请求作用域对象】中
request.setAttribute("key1",data);
//向Tomcat申请调用TwoServlet
RequestDispatcher report = request.getRequestDispatcher("/two");
report.forward();

TwoServlet中:

//从当前【请求对象】中拿出共享数据
Object data = request.getAttribute("key1");

Servlet的扩展工具及应用

1.监听器接口(Listener)

(1).监听器的概述:

简介:

①来自Servlet规范中,存在共8个接口; ②需要开发人员自行去实现,并无现成的实现类;

作用:

用于监控 【作用域对象生命周期变化时刻】 或者【作用域对象共享数据变化时刻】

(2).作用域对象:

概念:

Servlet中,服务器内存中可存在某些条件下为两个Servlet间提供数据共享的对象,叫作作用域对象

分类:

Ⅰ.ServletContext:全局作用域对象; Ⅱ.HttpSession:会话作用域对象; Ⅲ. HttpServletRequest:请求作用域对象;

监听器接口实现类开发规范:

Ⅰ.根据实际情况,选择适当的作用域对象; Ⅱ.重写监听器接口声明【监听事件处理方法】; Ⅲ.在web.xml文件将监听器接口实现对象注册到Http中。

web.xml文件的注册语法:

<listener>
	<listener-class>(接口实现src下的地址+类名)</listener-class>
</listener>

(3).监听器接口详解:

a.ServletContextListener接口:

作用:

合法的检测【全局作用域对象】被初始化销毁时刻;

语法规则:

//【全局作用域对象】被初始化时被调用
public void contextInitialized();

//【全局作用域对象】被销毁时被调用
public void contextDestroyed();

b.ServletContextAttributeListener接口:

作用:

合法监测全局作用域对象共享数据变化时刻。

语法规则:

//在【全局作用域对象】中添加数据时被调用
public void attributeAdded();

//在【全局作用域对象】中更新数据时被调用
public void attributeReplaced();

//在【全局作用域对象】中删除数据时被调用
public void attributeRemoved();

修改数据的案例:

//拿到【全局作用域对象】
ServletContext application = request.getServletContext();
//增添数据
application.setAttribute("key1",100);
//修改数据
application.setAttribute("key1",200);
//删除数据
application.removeAttribute("key1");

2.过滤器接口(Filter)

(1).过滤器的概述:

简介:

Ⅰ.来自Servlet规范,存在与servlet-api.jar包下; Ⅱ.需开发人员自行实现,无现成实现类;

作用:

Ⅰ.用于服务器调用资源以前,进行拦截; Ⅱ.拦截Http服务器,检测当前请求的合法性; Ⅲ.拦截Http服务器,对当前请求进行增强操作;

(2).使用规范:

Ⅰ.创建一个类,实现Filter接口; Ⅱ.实现doFilter()方法; Ⅲ.在web.xml中注册到Http服务器中;

在web.xml中的注册语法: 需被拦截文件名处的三种泛指: (假设img目录下存储图片ice.jpg) Ⅰ./img/ice.jpg Ⅱ.*.jpg Ⅲ./img/*

<filter>
	<filter-name>(类名)</filter-name>
	<filter-class>(src下地址)</filter-class>
</filter>
<filter-mapping>
	<filter-name>(类名)</filter-name>
	<url-pattern>(需被拦截的文件名)</url-pattern>
</filter-mapping>

(3).使用语法:

//当条件符合时,将【请求对象】和【响应对象】返还给服务器
filterChain.doFilter(request,response);

//过滤器做增强操作
//改变请求体的编码方式
request.setCharacterEncoding("utf-8");

(4).过滤器的应用(防止用户恶意登录)

概述:

用户恶意登录指不经过登陆步骤,直接通过地址栏访问登录后的页面。

令牌机制解决恶意登录: 使用过滤器之前:

Ⅰ.在登录界面给予用户会话作用域对象; HttpSession session = request.getSession(); Ⅱ.在资源文件内添加检测机制: if(session != null){}

缺点: Ⅰ.无法对静态文件进行保护; Ⅱ.如果网站资源较多,增加了开发难度。

使用过滤器之后:

Ⅰ.在登录界面给予用户会话作用域对象; HttpSession session = request.getSession(); Ⅱ.书写过滤器的实现类并重写doFilter()方法: Ⅲ.在web.xml下配置文件。

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
	 /*由于servletRequest中没有getSession方法,必须将其转为其子接口HttpSession才能
        调出getSession方法,response同理*/
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpSession session = null;

        //通过【请求对象】获取到请求行中的uri
        String uri = request.getRequestURI();
        //如果登录信息出现login相关的,过滤器无条件通过
        if (uri.indexOf("login")!=-1 || "/myWeb/".equals(uri)){
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        //如果访问其他资源文件,则需验证用户的session
        session = request.getSession(false);

        if (session != null){
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        request.getRequestDispatcher("login_error.html").forward(servletRequest, servletResponse);
    }

3.通信流程图的总结:

在这里插入图片描述