第 5 课 JSP 页面的访问控制
掌握访问控制实现的流程 掌握 JSP 内置对象的用法 session 对象 application 对象 掌握 include 指令 掌握如何在超链接中传递参数 本章目标
本章任务 完成最终版的新闻发布系统 为新闻发布系统增加访问控制 为新闻发布系统增加已访问人数统计 实现新闻发布系统的分级浏览
生活中的访问控制 下载电子书时,系统会提示用户登录网站 点击下载, 系统转入登录页面 每次下载之前,系统如何判断用户是否已经登录?
如何实现访问控制 ? 系统如何保存不同用户的登录信息? 使用 JSP 会话跟踪机制,可以维持每个用户的会话信息,也就是为 不同的用户保存不同的数据 1 2 访问控制流程图: 用户登录 进入用户注 册页面 系统保存该用 户的登录信息 进入欲访问 的页面 是否是注册用户 否 是 用户直接访 问某个页面 进入用户登录 页面 显示该页面 内容 系统是否保存了 该用户登录信息 否 是
浏览器关闭, 本次会话结束 什么是会话 ? 一个会话就是浏览器与服务器之间的一次通话,它包 含浏览器与服务器之间的多次请求、响应过程。 浏览器 session 对象 请求 1 浏览器 请求 2…n session 是 JSP 内置对象, 与浏览器一一 对应,允许用 户存储和提取 会话状态的信 息 响应 1 响应 2…n session 对象
JSP 内置对象 session session 对象用来存储有关用户会话的所有信息 session 对象常用方法: void setAttribute(String key, Object value) :以键 / 值的 方式,将一个对象的值存放到 session 中 Object getAttribute(String key) :根据名称去获取 session 中存放对象的值 session.setAttribute("name", "admin"); String name = (String) session.getAttribute("name"); 访问控制就是基于 session 来完成的
为新闻发布系统增加访问控制 4-1 升级新闻发布系统,增加访问控制功能,具体要求如下: 提供用户登录页面 用户必须登录之后,才能访问新闻发布系统 登录处理页面 (login.jsp) 1 、获得登录信息 2 、查询数据库,判断该用户是否注册 3 、如果该用户已注册,在 session 中 保存该用户的登录信息,并且跳转到新 闻发布系统的首页面 登录处理页面 (login.jsp) 1 、获得登录信息 2 、查询数据库,判断该用户是否注册 3 、如果该用户已注册,在 session 中 保存该用户的登录信息,并且跳转到新 闻发布系统的首页面 新闻发布系统首页面 (index.jsp) 1 、从 session 中提取该用户信息 2 、如果用户信息存在,显示首页内容 3 、如果用户信息不存在,跳转到登录页面 新闻发布系统首页面 (index.jsp) 1 、从 session 中提取该用户信息 2 、如果用户信息存在,显示首页内容 3 、如果用户信息不存在,跳转到登录页面 用户已注册 session 中无法 提取到用户信息 1 2 3
为新闻发布系统增加访问控制 4-2 在 news 数据库中创建表 userinfo ,负责存储用户名、密码 创建类( User.java ),负责存储用户名、密码 创建登录页面( login.html ) 创建登录处理页面( login.jsp ) 登录处理页面的代码片断 <% if (rs.next()) { // 如果是已注册用户 // 把用户名、密码封装在 User 对象中 User loginedUser = new User(name, pass); session.setAttribute("LOGINED_USER", loginedUser); response.sendRedirect("index.jsp"); } else { response.sendRedirect(“login.html"); } %> 在 session 中存 放用户登录信息
为新闻发布系统增加访问控制 4-3 在新闻发布系统后台首页面 (index1.jsp) 中加 入登录验证 <% User user = (User) session.getAttribute("LOGINED_USER"); if (user == null) { response.sendRedirect(“login.html"); } %> 如果 session 中不存在该 用户的登录信息,转入 登录页面
为新闻发布系统增加访问控制 4-4 访问控制效果验证,步骤如下: 直接在 IE 地址栏中输入 URL ,访问系统首页面 通过登录页面进入系统首页面 重新开启一个 IE 窗口,直接访问系统首页面 每个步骤会发生什么样的结果?为什么会产生这样 的结果? 每个 session 对象都与浏览器一一对应 重新开启一个浏览器,相当于重新创建一个 session 对象 每个 session 对象都与浏览器一一对应 重新开启一个浏览器,相当于重新创建一个 session 对象 演示:访问控制效果验证
include 指令 2-1 除了首页面,其它页面中同样需要加入登录验证, 有没有办法避免冗余代码的出现? 可以将一些共性的内容写入一个单独的文件中,然后通过 include 指令引用该文件,从而降低代码的冗余问题,也便 于修改共性内容
include 指令 2-2 创建登录验证文件 checklogin.jsp 在后台首页面( index.jsp )中使用 include 指令引用登录 验证文件 <% User user = (User) session.getAttribute("LOGINED_USER"); if (user == null) { response.sendRedirect(“login.html"); } %>
小结 1 创建登录页面 login.html 提供用户名输入框、以及登录按钮 创建登录处理页面 login.jsp 如果用户名为 sa ,把用户名存储在 session 中,并跳转进 入 index.jsp 中 否则跳转进入 login.html 页面 创建页面 index.jsp 如果 session 中没有该用户信息,跳转进入 login.html 中 否则显示欢迎信息
为新闻发布系统增加已访问人数统计 升级新闻发布系统,增加已访问人数统计功能, 具体要求如下: 左导航页面中增加超链接:已访问人数统计 已访问人数统计页面:显示已访问人数,以及访问 者的登录名称 登录处理页面 (login2.jsp) 1 、在 session 中保存该用户信息 2 、在全局范围内保存该用户信息 3 、跳转到新闻发布系统的首页面 登录处理页面 (login2.jsp) 1 、在 session 中保存该用户信息 2 、在全局范围内保存该用户信息 3 、跳转到新闻发布系统的首页面
为新闻发布系统增加已访问人数统计 创建登录页面( login2.html ) 创建登录处理页面( login2.jsp ) 登录处理页面代码片断 if (rs.next()) { User logineduser = new User(name, pass); session.setAttribute("LOGINED_USER", logineduser); List loginedUsers = new ArrayList(); // 访问者列表 if (application.getAttribute("LOGINED_USER") != null) loginedUsers = (List) application.getAttribute("LOGINED_USER"); loginedUsers.add(logineduser); // 把新登录用户的信息存入访问者列表中 application.setAttribute("LOGINED_USER", loginedUsers); response.sendRedirect("index.jsp"); } 在全局范围内存入 访问者列表 从全局范围内取出原 有的访问者列表
为新闻发布系统增加已访问人数统计 在新闻发布系统左导航栏中加入超链接( left.jsp ) 创建已访问人数统计页面( showAllLoginedUsers.jsp ) 已访问人数统计页面代码片断 <% List loginedUsers = new ArrayList(); // 访问者列表 if (application.getAttribute("LOGINED_USER") != null) loginedUsers = (List) application.getAttribute("LOGINED_USER"); %> 目前, 有 人已经访问过本网站 ! 访问者的登录名称分别是: <% for (int i = 0; i < loginedUsers.size(); i++) { User logineduser = (User) loginedUsers.get(i); out.print(logineduser.getName()); out.print(" "); } %> 从全局范围内取出访 问者列表 逐行显示每个访问者 的登录名称
已访问人数统计效果验证,步骤如下: 通过登录页面进入系统首页面,查看已访问人数统计 重新开启一个 IE 窗口,使用不同的用户登录进入首页 面,查看已访问人数统计 每个步骤会发生什么样的结果?为什么会产生这样 的结果? 演示:已访问人数统计的效果验证 为新闻发布系统增加已访问人数统计
JSP 内置对象 application application 类似于系统的 “ 全局变量 ” ,用于实现 用户之间的数据共享 application 对象的常用方法: void setAttribute(String key, Object value) :以键 / 值 的方式,将一个对象的值存放到 application 中 Object getAttribute(String key) :根据键去获取 application 中存放对象的值 application.setAttribute("LOGINED_USER", new ArrayList()); if (application.getAttribute("LOGINED_USER") != null) { List loginedUsers = (List) application.getAttribute("LOGINED_USER"); }
新闻发布系统的分级浏览 4-1 实现新闻的分级浏览功能,具体要求如下: 在新闻发布系统的前台首页面上,显示所有新闻一级标题 为所有新闻一级标题设置超链接,点击后,显示下属的新闻二级标题 “ 体育 ” 对应的超链接 “ 体育 ” 下属的新闻二 级标题列表 点击 “ 体育 ”
新闻发布系统的分级浏览 4-2 创建前台首页面( newspre.jsp ) 使用表格把页面分为三块:上栏、左下栏、右下栏 上栏显示图片 左下栏显示新闻一级标题,提取到一个单独的文件 showFirstTitle.jsp 中 右下栏显示新闻二级标题,提取到一个单独的文件 showSecondTitle.jsp 中 使用 include 指令引入这两个文件 上栏 右下栏 左下栏
新闻发布系统的分级浏览 4-3 创建新闻一级标题的浏览页面( showFirstTitle.jsp ) 代码片断 <% // 从数据库中获取所有新闻一级标题,并逐行显示 FirstLeveTitleDbOpreation first = new FirstLeveTitleDbOpreation(); List list1 = first.getAllFirstLevelTitleList(); if (list1!=null && list1.size() != 0) { for (int i = 0; i < list1.size(); i++) { FirstLevelTitle fTitle = (FirstLevelTitle) list1.get(i); %> "> <% } } %> 超链接中传递参数: 新闻一级标题的 ID
新闻发布系统的分级浏览 4-4 在类 SecondLevelTitleDbOpreation 中添加方法 getSecondByFirst() ,根据新闻一级标题的 ID 获取对应的新 闻二级标题 创建新闻二级标题的浏览页面( showSecondTitle.jsp ) 根据新闻一级标题的 ID ,显示对应的新闻二级标题 代码片断 <% String strParentId = request.getParameter("parentId"); if (strParentId!=null){ int parentId = Integer.parseInt(strParentId); // 根据新闻一级标题 ID 获取下属的新闻二级标题列表 List list2 = new SecondLevelTitleDbOpreation().getSecondByFirst(parentId); } %> 处理 URL 中的请求参数: 得到新闻一级标题的 ID
小结 2 创建 JSP 页面 one.jsp 设置一个超链接,链接至 two.jsp 文件 向 two.jsp 传递一个参数,参数名为 str ,其值 为字符串 hello 创建 JSP 页面 two.jsp 在该页面中输出参数的值
总结 启动 IE 窗口运行如下 JSP ,如果连续刷新 5 次,输出结果是 什么? 重新启动一个新的 IE 窗口运行该 JSP ,如果连续刷新 3 次, 输出结果是什么 ? <% Integer ival = (Integer)session.getAttribute("counter"); if (ival == null) ival = new Integer(1); else{ ival = new Integer(ival.intValue() + 1); session.setAttribute("counter", ival); } %> 第一次输出: 5 5 第二次输出: 3 3