1. 改造OA  54

1.1 使用什么技术改造呢?   54-55

Servlet + JSP + EL表达式 + JSTL标签。进行改造。

- 在前端HTML代码中,有一个标签,叫做base标签,这个标签可以设置整个网页的基础路径。

  - 这不是Java的语法,也不是JSP的语法。是HTML中的一个语法。HTML中的一个标签。通常出现在head标签中。

 < base href="http://localhost:8080/oa/">

- 在当前页面中,凡是路径没有以“/”开始的,都会自动将base中的路径添加到这些路径之前。

    - < a href="ab/def">

    - 等同于:< a href="http://localhost:8080/oa/ab/def">

  - 需要注意:在JS代码中的路径,保险起见,最好不要依赖base标签。JS代码中的路径最好写上全路径。

base标签的写法

<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">

2. 当前的OA项目存在什么缺陷?  56

  - DeptServlet、EmpServlet、OrderServlet。每一个Servlet都是处理自己相关的业务。在这些Servlet执行之前都是需要判断用户是否登录了。如果用户登录了,可以继续操作,如果没有登录,需要用户登录。这段判断用户是否登录的代码是固定的,并且在每一个Servlet类当中都需要编写,显然代码没有得到重复利用。包括每一个Servlet都要解决中文乱码问题,也有公共的代码。这些代码目前都是重复编写,并没有达到复用。怎么解决这个问题?

    - 可以使用Servlet规范中的Filter过滤器来解决这个问题。

3. 实现oa项目中当前登录在线的人数。 61

  - 什么代表着用户登录了?

    - session.setAttribute("user", userObj); User类型的对象只要往session中存储过,表示有新用户登录。

  - 什么代表着用户退出了?

    - session.removeAttribute("user"); User类型的对象从session域中移除了。

    - 或者有可能是session销毁了。(session超时)

代码在com.bjpowernode.oa.bean.

javabean   Dept

package com.bjpowernode.oa.bean;

import java.util.Objects;

//这就是一个普通的java类,这个类可以封装零散的数据,代表了一个部门对象
public class Dept {
    private String deptno;
    private String dname;
    private String loc;

    public Dept() {
    }

    public String getDeptno() {
        return deptno;
    }

    public void setDeptno(String deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    @Override
    public String () {
        return "Dept{" +
                "deptno='" + deptno + '\'' +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Dept dept = (Dept) o;
        return Objects.equals(deptno, dept.deptno) &&
                Objects.equals(dname, dept.dname) &&
                Objects.equals(loc, dept.loc);
    }

    @Override
    public int hashCode() {
        return Objects.hash(deptno, dname, loc);
    }
}

User(展示在线人数的)

package com.bjpowernode.oa.bean;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;

//这个javabean负责展示用户在线人数  61
public class User implements HttpSessionBindingListener {

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        //用户登录了
        //User类型的对象向session域中存放了
        //获取ServletContext域对象
        //因为我们要存储所有的用户,所以放在最大的application域中(application域相当于ServletContext)
        ServletContext application = event.getSession().getServletContext();
        //获取在线人数
        Object onlinecount = application.getAttribute("onlinecount");
        if(onlinecount==null){//第一次取可能为空
            application.setAttribute("onlinecount",1);//如果第一次取空,我们就存入一个
        }else{
            int count = (Integer)onlinecount;
            count++;//用户登录了加1
            application.setAttribute("onlinecount",count);//存入ServletContext域
        }

    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        //用户退出了
        //User类型的对象向session域中删除了
        //获取ServletContext对象
        ServletContext application = event.getSession().getServletContext();
        //获取在线人数
        Integer onlinecount =(Integer) application.getAttribute("onlinecount");
        onlinecount--;//用户退出了登录减1
        application.setAttribute("onlinecount",onlinecount);//存入ServletContext域
    }

    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    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;
    }
}

com.bjpowernode.oa.utils

工具类DBUtil 

package com.bjpowernode.oa.utils;

import java.sql.*;
import java.util.ResourceBundle;

/**
 * JDBC的工具类   27
 */
public class DBUtil {

    // 静态变量:在类加载时执行。
    // 并且是有顺序的。自上而下的顺序。
    // 属性资源文件绑定
    private static ResourceBundle bundle = ResourceBundle.getBundle("resources.jdbc");
    // 根据属性配置文件key获取value
    private static String driver = bundle.getString("driver");
    private static String url = bundle.getString("url");
    private static String user = bundle.getString("user");
    private static String password = bundle.getString("password");

    static {
        // 注册驱动(注册驱动只需要注册一次,放在静态代码块当中。DBUtil类加载的时候执行。)
        try {
            // "com.mysql.jdbc.Driver" 是连接数据库的驱动,不能写死。因为以后可能还会连接Oracle数据库。
            // 如果连接oracle数据库的时候,还需要修改java代码,显然违背了OCP开闭原则。
            // OCP开闭原则:对扩展开放,对修改关闭。(什么是符合OCP呢?在进行功能扩展的时候,不需要修改java源代码。)
            //Class.forName("com.mysql.jdbc.Driver");

            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接对象
     * @return conn 连接对象
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        // 获取连接
        Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }

    /**
     * 释放资源
     * @param conn 连接对象
     * @param ps 数据库操作对象
     * @param rs 结果集对象
     */
    public static void close(Connection conn, Statement ps, ResultSet rs){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (ps != null) {
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

代码在com.bjpowernode.oa.web.action

DeptServlet

package com.bjpowernode.oa.web.action;

import com.bjpowernode.oa.bean.Dept;
import com.bjpowernode.oa.utils.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//使用jsp改造单表的CRUD操作  38
@WebServlet({"/dept/list","/dept/detail","/dept/delete","/dept/save","/dept/modify"})
public class DeptServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 获取session(这个session是不需要新建的)   44
        // 只是获取当前session,获取不到这返回null
        /*HttpSession session = request.getSession(false);
        //这里解释if里面为什么有两个判断条件,因为第一保证session不为null这毋庸置疑
        // ,但是session.getAttribute里的username还要不为空呢,因为系统是默认访问index文件的
        // ,这样默认访问index文件也会产生一个session会话,所以要加上第二个条件
        if(session!=null && session.getAttribute("username")!=null){
            String servletPath = request.getServletPath();//得到路径
            if("/dept/list".equals(servletPath)){
                doList(request,response);
            }else if("/dept/detail".equals(servletPath)){
                doDetail(request,response);
            }else if("/dept/delete".equals(servletPath)){
                doDel(request,response);
            }else if("/dept/save".equals(servletPath)){
                doSave(request, response);
            }else if("/dept/modify".equals(servletPath)){
                doModify(request,response);
            }
        }else{
            //没有登陆过自动跳转登陆页面
            //重定向
            //三种写法
            //response.sendRedirect("/oa/index.jsp");//普通老老实实写法
            //response.sendRedirect("/oa");//省略index.jsp,因为会自动访问index文件
            response.sendRedirect(request.getContextPath()+"/index.jsp");//动态获取根写法,自动找到登录页面
        }*/

        String servletPath = request.getServletPath();//得到路径
        if("/dept/list".equals(servletPath)){
            doList(request,response);
        }else if("/dept/detail".equals(servletPath)){
            doDetail(request,response);
        }else if("/dept/delete".equals(servletPath)){
            doDel(request,response);
        }else if("/dept/save".equals(servletPath)){
            doSave(request, response);
        }else if("/dept/modify".equals(servletPath)){
            doModify(request,response);
        }

    }
    //保存部门信息   40
    private void doSave(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        //获取部门信息
        // 注意乱码问题(Tomcat10不会出现这个问题)
        request.setCharacterEncoding("UTF-8");
        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loc = request.getParameter("loc");

        //连接数据库执行insert语句
        Connection conn = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            conn = DBUtil.getConnection();
            String sql = "insert into dept(deptno, dname, loc) values(?,?,?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1,deptno);
            ps.setString(2,dname);
            ps.setString(3,loc);
            count = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn,ps,null);
        }

        if(count==1) {
            // 这里最好使用重定向(浏览器会发一次全新的请求。)
            // 浏览器在地址栏上发送请求,这个请求是get请求。
            response.sendRedirect(request.getContextPath()+"/dept/list");
        }
    }

    //根据部门编号删除相应的部门  40
    private void doDel(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        //获取部门编号
        String deptno = request.getParameter("deptno");
        //连接数据库,查询部门信息
        Connection conn = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            conn = DBUtil.getConnection();
            String sql = "delete from dept where deptno = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,deptno);
            count = ps.executeUpdate();//返回删除受影响的条数
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn,ps,null);
        }
        if(count == 1){
            //删除成功
            //重定向到列表页面
            String contextPath = request.getContextPath();//获取应用的根路径
            response.sendRedirect(contextPath+"/dept/list");
        }
    }

    //根据部门编号获取部门信息   39
    private void doDetail(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        //创建部门对象
        Dept dept = new Dept();

        //获取部门编号
        String dno = request.getParameter("dno");
        //根据部门编号获取部门信息 将部门信息封装成咖啡豆(即javabean)
        //连接数据库,查询部门信息
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtil.getConnection();
            String sql = "select dname,loc from dept where deptno=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,dno);
            rs = ps.executeQuery();
            //这个结果集中只有一条数据,因此不需要while循环,只需要if
            if(rs.next()){
                String dname = rs.getString("dname");
                String loc = rs.getString("loc");
                //封装对象(创建豆子javabean)
                dept.setDeptno(dno);
                dept.setDname(dname);
                dept.setLoc(loc);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn,ps,rs);
        }

        //这个豆子只有一个,所以不需要袋子(也就是不需要集合了),只需要将这个袋子放入到request域当中
        request.setAttribute("dept",dept);

        //转发(不是重定向因为要跳转到JSP做数据展示)
        //request.getRequestDispatcher("/detail.jsp").forward(request,response);

        //获取不同的标识(这个标识是我们再list.jsp修改和详情中自己加的,用来区分修改和详情的操作)
        //因为我们可以根据不同的标记取转发到不同的页面  40
       /* String f = request.getParameter("f");
        if("m".equals(f)){
            //转发到修改页面
            request.getRequestDispatcher("/edit.jsp").forward(request,response);
        }else if("d".equals(f)){
            //转发到详情页面
            request.getRequestDispatcher("/detail.jsp").forward(request,response);
        }*/

        //我们将上述代码简化 这就是一个路径拼接 getParameter("f")得到标记  40
        String forward = "/"+request.getParameter("f")+".jsp";
        //根据得到的拼接的路径进行转发
        request.getRequestDispatcher(forward).forward(request,response);

    }

    //连接数据库,查询所有的部门信息,将部门信息收集好,然后跳转到JSP做页面展示。38
    private void doList(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException{
        //准备一个容器,用来专门存储部门
        List depts = new ArrayList<>();

        //连接数据库,查询所有的部门信息
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //获取连接
            conn = DBUtil.getConnection();
            String sql = "select deptno,dname,loc from dept";
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            //遍历结果集
            while(rs.next()){
                //从结果集中取出
                String deptno = rs.getString("deptno");
                String dname = rs.getString("dname");
                String loc = rs.getString("loc");
                //将以上零散的数据封装成java对象
                Dept dept = new Dept();
                dept.setDeptno(deptno);
                dept.setDname(dname);
                dept.setLoc(loc);

                //将部门对象放入到list集合中
                depts.add(dept);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭连接
            DBUtil.close(conn,ps,rs);
        }

        //将一个集合放入到请求域当中
        request.setAttribute("deptList",depts);
        //转发不要重定向
        request.getRequestDispatcher("/list.jsp").forward(request,response);
    }

    //修改操作   40
    private void doModify(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //解决请求体的中文乱码问题
        request.setCharacterEncoding("UTF-8");
        //获取表单数据
        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loc = request.getParameter("loc");
        //连接数据库执行更新语句
        Connection conn = null;
        ;
        PreparedStatement ps = null;
        int count = 0;
        try {
            conn = DBUtil.getConnection();
            String sql = "update dept set dname = ?,loc = ? where deptno = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1, dname);
            ps.setString(2, loc);
            ps.setString(3, deptno);
            count = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, ps, null);
        }

        if (count == 1) {
            //更新成功
            //重定向
            response.sendRedirect(request.getContextPath() + "/dept/list");
        } 
    }
}

UserServlet

package com.bjpowernode.oa.web.action;

import com.bjpowernode.oa.bean.User;
import com.bjpowernode.oa.utils.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//专门处理用户登录  41
//Servlet负责业务处理
//JSP负责页面展示
@WebServlet({"/user/login","/user/exit"})
public class UserServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String servletPath = request.getServletPath();
        if("/user/login".equals(servletPath)){
            doLogin(request,response);//调用登录
        }else if("/user/exit".equals(servletPath)){
            doExit(request,response);//调用退出
        }
    }

    //退出   45
    protected void doExit(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获取session对象,销毁session
        HttpSession session = request.getSession(false);
        if (session !=null){

            //从session域中删除user对象
            session.removeAttribute("user");
            //手动销毁session对象
            session.invalidate();

            //销毁cookie    54-55
            Cookie[] cookies = request.getCookies();
            if(cookies != null){
                for (Cookie cookie : cookies) {//循环遍历cookie
                    //设置cookie的有效时间为0,表示删除cookie
                    cookie.setMaxAge(0);
                    //设置一下cookie的路径
                    cookie.setPath(request.getContextPath());//删除cookie是注意路径问题
                    //响应cookie给浏览器,浏览器端会将之前的cookie覆盖
                    response.addCookie(cookie);
                }
            }

            //跳转登录页面
            //这是重定向
            response.sendRedirect(request.getContextPath());
        }
    }
    //登录
    protected void doLogin(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        boolean success = false;//登录成功标志

        //验证用户名和密码是否正确
        //获取用户名和密码
        // 前端你是这样提交的:username=admin&password=123
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //连接数据库验证用户名和密码
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtil.getConnection();
            String sql = "select * from t_user where username=? and password=?";
            //编译sql
            ps = conn.prepareStatement(sql);
            //给?赋值
            ps.setString(1,username);
            ps.setString(2,password);
            //执行sql
            rs = ps.executeQuery();
            //这个结果集中做多只有一条数据
            if (rs.next()) {
                //登录成功
                success = true;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(conn,ps,rs);
        }
        if(success){
            // 获取session对象(这里的要求是:必须获取到session    44
            // ,没有session也要新建一个session对象。)
            HttpSession session = request.getSession();//session对象一定不为空null
            //session.setAttribute("username",username);//将用户名存入

            //这两行是为了展示在线人数的(上面那个写法也对就是没有这个功能)  61
            User user = new User(username, password);
            session.setAttribute("user",user);

            //登陆成功了,并且用户选择了十天内免登录
            String f = request.getParameter("f");
            if("1".equals(f)){
                //创建cookie对象存储登录名
                Cookie cookie1 = new Cookie("username",username);
                //创建cookie对象存储密码
                Cookie cookie2 = new Cookie("password", password);
                //设置cookie的有效时间为十天
                cookie1.setMaxAge(60*60*24*10);
                cookie2.setMaxAge(60*60*24*10);
                //设置cookie的path(只要访问这个应用,浏览器就一定携带这两个cookie)
                cookie1.setPath(request.getContextPath());
                cookie2.setPath(request.getContextPath());
                //响应cookie给浏览器
                response.addCookie(cookie1);
                response.addCookie(cookie2);
            }

            //登陆成功,跳转到用户列表页面
            response.sendRedirect(request.getContextPath()+"/dept/list");
        }else{
            //登录失败,跳转到失败页面
            response.sendRedirect(request.getContextPath()+"/error.jsp");
        }
    }
}

WelcomeServlet

package com.bjpowernode.oa.web.action;

import com.bjpowernode.oa.bean.User;
import com.bjpowernode.oa.utils.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//十天内免登录欢迎页  48
@WebServlet("/welcome")
public class WelcomeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //先获取cookie
        //这个cookie[]数组可能是null,如果不是null,数组的长度一定是大于0的
        Cookie[] cookies = request.getCookies();//得到cookie数组
        String username = null;
        String password = null;
        if (cookies != null) {//如果cookie不为null
            for (Cookie cookie : cookies) {//循环遍历cookie数组
                String name = cookie.getName();//先得到cookie的name,然后在得到value
                //因为有两个cookie,所以根据不同的cookie的name得到不同的value
                if("username".equals(name)){
                    username = cookie.getValue();
                }else if("password".equals(name)){
                    password = cookie.getValue();
                }
            }
        }

        //要在这里使用username和password变量
        if(username != null && password != null){
            //验证用户名和密码是否正确
            Connection conn =null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            boolean success = false;
            try {
                conn = DBUtil.getConnection();
                String sql = "select * from t_user where username = ? and password = ?";
                ps = conn.prepareStatement(sql);
                ps.setString(1,username);
                ps.setString(2,password);
                rs = ps.executeQuery();
                if(rs.next()){
                    //登陆成功
                    success = true;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtil.close(conn,ps,rs);
            }

            if(success){
                //获取session对象
                HttpSession session = request.getSession();
                //session.setAttribute("username",username);

                //这两行是为了展示在线人数的(上面那个写法也对就是没有这个功能)  61
                User user = new User(username, password);
                session.setAttribute("user",user);

                //正确,表示登陆成功
                response.sendRedirect(request.getContextPath()+"/dept/list");
            }else{
                //错误,表示登录失败
                response.sendRedirect(request.getContextPath()+"/index.jsp");
            }

        }else{
            //跳转登录页面
            //这里使用重定向
            response.sendRedirect(request.getContextPath()+"/index.jsp");
        }

    }
}

OrderServlet

package com.bjpowernode.oa.web.action;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

//管理的登录的类  57
public class OrderServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //要想进入这个servlet,一定会右这个servlet自己的路径,但是当我们输入这个servlet的路径时
        //会被过滤器拦截,因为我们设置的过滤器任何路径都拦截(除了那几种情况)
    }
}

EmpServlet

package com.bjpowernode.oa.web.action;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

//员工的登录的类  57
public class EmpServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //要想进入这个servlet,一定会右这个servlet自己的路径,但是当我们输入这个servlet的路径时
        //会被过滤器拦截,因为我们设置的过滤器任何路径都拦截(除了那几种情况)
    }
}

代码在com.bjpowernode.oa.web.filter

LoginCheckFilter

package com.bjpowernode.oa.web.filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;

//这是一个过滤器 负责过滤登陆代码的 57
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res
            , FilterChain chain) throws IOException, ServletException {

        //以下两行是强制类型转换
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;

        //获取请求路径
        String servletPath = request.getServletPath();

        // 获取session(这个session是不需要新建的)   44
        // 只是获取当前session,获取不到这返回null
        HttpSession session = request.getSession(false);

        //这里解释if里面为什么有两个判断条件,因为第一保证session不为null这毋庸置疑
        // ,但是session.getAttribute里的username还要不为空呢,因为系统是默认访问index文件的
        // ,这样默认访问index文件也会产生一个session会话,所以要加上第二个条件
        /**
         * 什么情况下不能拦截?  57
         *      目前写的路径是:/* 表示所有的请求均拦截。
         *
         *      用户访问 index.jsp的时候不能拦截
         *      用户已经登录了,这个需要放行,不能拦截。
         *      用户要去登录,这个也不能拦截。
         *      WelcomeServlet也不能拦截。
         */
        //不拦截(就是不用登录了)
        //这个if表示什么时候什么样的请求不进行拦截,
        // /index.jsp是要去登陆,如果进行拦截,那么我们的登录界面就显示不出来(因为chain是继续执行下面的代码的
        // ,你都被拦截了,index.jsp中的代码还没执行呢)
        // /welcome是欢迎界面(程序开始第一个执行的界面,如果对他进行拦截那么它后面的代码就无法执行)
        // /user/login是判断登陆是都成功的,如果对他进行拦截,那么就无法判断了(因为我本来是去判断,你一拦截
        // 却是又要我取登录界面)
        // /user/exit是判断退出的,如果对他进行拦截,那么就无法判断了()就会导致session和cookie无法被销毁
        //因为拦截后被你拉去又要登陆了
        //(session != null && session.getAttribute("username") != null)这个表示登陆过了
        // ,就不需要拦截了
        /*if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
                "/user/login".equals(servletPath) || "/user/exit".equals(servletPath)
                || (session != null && session.getAttribute("username") != null)){*/

        if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
                "/user/login".equals(servletPath) || "/user/exit".equals(servletPath)
                || (session != null && session.getAttribute("user") != null)){
            //在session和提交的username不为空的情况下,继续往下走
            chain.doFilter(request,response);

        }else{
            //进行拦截(就是让去登录)
            //没有登陆过自动跳转登陆页面
            //重定向
            //三种写法
            //response.sendRedirect("/oa/index.jsp");//普通老老实实写法
            //response.sendRedirect("/oa");//省略index.jsp,因为会自动访问index文件
            response.sendRedirect(request.getContextPath()+"/index.jsp");//动态获取根写法,自动找到登录页面
        }
    }
}

配置文件 src.resources

jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/bjpowernode
user=root
password=lzl

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
<!--    配置欢迎页面  48-->
    <welcome-file-list>
        <welcome-file>welcome</welcome-file>
    </welcome-file-list>

<!--    配置登录检查的过滤器,过滤所有的路径  57-->
    <filter>
        <filter-name>loginFilter</filter-name>
        <filter-class>com.bjpowernode.oa.web.filter.LoginCheckFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>loginFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

index.jsp

<%@page contentType="text/html;charset=UTF-8"%>
<%--进行jsp更改   38   把这个页面改成登录页面   41--%>
<%--访问jsp时不生成session对象   44--%>
<%@page session="false" %>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>欢迎使用OA系统</title>
  </head>
  <body>
    <%-- 前端发送请求路径的时候,如果请求路径是绝对路径,要以 / 开始,加项目名。--%>
    <%-- 以下这样写代码,oa项目名写死了。这种设计显然是不好的。--%>
    <%--    <a href="/oa/list.jsp">查看部门列表</a>--%>
    <%--  <a href="<%=request.getContextPath()%>/list.jsp">查看部门列表</a>--%>

    <%--  执行一个Servlet,查询数据库,收集数据--%>
    <%--  <a href="<%=request.getContextPath() %>/dept/list">查看部门列表</a>--%>

    <%--  <hr>--%>
    <%--  调用方法获取应用的根路径--%>
    <%--  <%=request.getContextPath()%>  <%–类似于out.print(request.getContextPath());   –%>--%>

<%--    画一个用户登录页面   41--%>
    <h1>用户登录</h1>
    <hr>
    <form action = "${pageContext.request.contextPath}/user/login" method="post">
        username:<input type="text" name="username"/><br>
        password:<input type="password" name="password"/><br>
        <input type="checkbox" name="f" value="1"/>十天内免登录<br>
        <input type="submit" value="login"/>
    </form>

  </body>
</html>


list.jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html;charset=UTF-8"%>

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>部门列表页面</title>
		<%--	设置整个网页的基础路径为http://localhost:8080/oa/     54--%>
<%--		<base href="http://localhost:8080/oa/">--%>
<%--		写成动态的  55--%>
		<base href="${pageContext.request.scheme}://${pageContext.request.serverName}
:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
	</head>
<body>

	<%--	显示一个登录名 和在线人数  44--%>
	<h3>欢迎${user.username},在线人数${onlinecount}人</h3>

	<%--	写一个安全退出的功能   45--%>
	<a href="user/exit">[退出系统]</a>

<script type="text/javascript">
	function del(dno){
		//弹出确认框,用户点击确定,返回true,点击取消返回false
		var ok = window.confirm("亲,删了不可恢复哦");
		if(ok){
			//发送请求进行删除数据操作
			//在js代码当中如何发送请求给服务器
			//四种写法想服务器发送请求
			//document.location.href = "请求路径"
			//document.location = "请求路径"
			//window.location.href = "请求路径"
			//window.location = "请求路径"
			/*注意html的base标签可能对JS代码不起作用。所以JS代码最好前面写上"/oa" */
			document.location.href="${pageContext.request.contextPath}/dept/delete?deptno="+dno;
		}
	}
</script>

	<h1 align="center">部门列表</h1>
	<hr >
	<table border="1px" align="center" width="50%">
		<tr>
			<th>序号</th>
			<th>部门编号</th>
			<th>部门名称</th>
			<th>操作</th>
		</tr>

		<c:forEach items="${deptList}" varStatus="deptStatus" var="dept">
			<tr>
				<td>${deptStatus.count}</td>
				<td>${dept.deptno}</td>
				<td>${dept.dname}</td>
				<td>
					<a href="javascript:void(0)" onclick="del(${dept.deptno})">删除</a>
					<a href="dept/detail?f=edit&dno=${dept.deptno}">修改</a>
					<a href="dept/detail?f=detail&dno=${dept.deptno}">详情</a>
				</td>
			</tr>
		</c:forEach>


	</table>


	<hr >
	<a href="add.jsp">新增部门</a>

</body>
</html>


add.jsp

<%@page contentType="text/html;charset=UTF-8"%>

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>新增部门</title>
	</head>
	<body>
	<%--	显示一个登录名   44--%>
	<h3>欢迎${username}</h3>
	<h1>新增部门</h1>
		<hr >
		<form action="${pageContext.request.contextPath}/dept/save" method="post">
			部门编号<input type="text" name="deptno"/><br>
			部门名称<input type="text" name="dname"/><br>
			部门位置<input type="text" name="loc"/><br>
			<input type="submit" value="保存"/><br>
		</form>
	</body>
</html>

detail.jsp

<%@page contentType="text/html;charset=UTF-8"%>

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>部门详情</title>
	</head>
	<body>
	<%--	显示一个登录名   44--%>
	<h3>欢迎${username}</h3>

	<h1>部门详情</h1>
		<hr >
		部门编号:${dept.deptno} <br>
		部门名称:${dept.dname}<br>
		部门位置:${dept.loc}<br>

		<input type="button" value="后退" onclick="window.history.back()"/>
	</body>
</html>

edit.jsp

<%@page contentType="text/html;charset=UTF-8"%>

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>修改部门</title>
	</head>
	<body>
	<%--	显示一个登录名   44--%>
	<h3>欢迎${username}</h3>
	<h1>修改部门</h1>
		<hr >
		<form action="${pageContext.request.contextPath}/dept/modify" method="post">
			部门编号<input type="text" name="deptno" value="${dept.deptno}" readonly /><br>
			部门名称<input type="text" name="dname" value="${dept.dname}"/><br>
			部门位置<input type="text" name="loc" value="${dept.loc}"/><br>
			<input type="submit" value="修改"/><br>
		</form>
	</body>
</html>

error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录失败</title>
</head>
<body>
<%--登录失败页面  41--%>
登陆失败,请<a href="${pageContext.request.contextPath}/index.jsp">重新登录</a>
</body>
</html>