Javaweb考前复习冲刺(不断更新版)

Javaweb考前复习冲刺

第一章: JavaWeb 入门

JavaWeb是指:以Java作为后台语言的项目工程。

javaweb项目创建的过程:

  1. 首先集成Tomcat服务器环境
  2. 新建dynamic web project
  3. 部署工程
  4. 运行

路由含义:

​ http://localhost:8080/工程项目名/(文件夹)/页面名。

<%=application.getRealPath("") %>  工程部署路径
# D:\java_exerise\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\component\

第二章 静态网页设计:

​ 一个网页是动态网页还是静态网页就是否还有 前端三件套(HTML、CSS、Javascript)之外的内容。

​ 动态网页是指网页中有需要服务器执行的元素,文件扩展名是jsp,动态页面中除了上述静态元素外,还包括服务器端脚本代码(Java)、指令、动作标签,表达式语言等。

动态网页中 静态成分和动态成分的执行顺序:

<%@ page pageEncoding="UTF-8" import="java.util.Date" %>
<html>
<body>
<script>
document.write(new Date());
</script>
<br/>
<%
out.print(new Date());
%>
</body>
</html>
Sun Dec 17 2023 12:43:16 GMT+0800 (中国标准时间)
Sun Dec 17 12:43:15 CST 2023

网页会先执行java代码,再执行js代码。我们可以理解为out.print(new Date()); 属于后台代码,只不过我们的服务器本地而已。

HTML:

网页的基本框架是由一个个标签组成的,标签又分为块级标签和行内标签。

块级标签:

  • 块级标签以新行开始,占据一整行的宽度,不与其他元素并排显示。

  • 常见的块级标签有 <div>、<p>、<h1> - <h6>、<ul>、<ol>、<li>、<table> 等。

行内标签:

  • 内标签不会独占一行,与其他元素并排显示,根据内容的大小自动调整宽度
  • 常见的行内标签有 <span>、<a>、<strong>、<em>、<img>、<input>、<label>
列表:

有序列表:

<ol type="序号类型">
  <li>……</li>
  <li>……</li>
</ol>

无序列表:

<ul type="类型样式">
 <li>…….</li>
 <li>……</li>
</ul>

定义列表:

自定义列表不仅仅是一列项目,而是项目及其注释的组合。

自定义列表以

标签开始。每个自定义列表项以 开始。每个自定义列表项的定义以
开始。

<dl>
  <dt>名词1</dt>
  <dd>解释1</dd>
  <dt>名词2</dt>
  <dd>解释2</dd>
</dl>
<dl>
  <dt>Coffee</dt>
  <dd>- black hot drink</dd>
  <dt>Milk</dt>
  <dd>- white cold drink</dd>
</dl>

在这里插入图片描述

表格:
  • 表格的标题使用了 <thead> 元素,表格的主体数据使用了 <tbody> 元素。

  • <tfoot>:用于定义表格的页脚部分。页脚位于表格主体之后,可以包含汇总信息等内容。

  • <caption>:用于为整个表格添加标题,位于表格的上方。一个表格只能有一个 <caption> 元素。

<table>
  <caption>这是表格标题</caption>
  <thead>
    <tr>
      <th>列标题1</th>
      <th>列标题2</th>
      <th>列标题3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>行1,列1</td>
      <td>行1,列2</td>
      <td>行1,列3</td>
    </tr>
    <tr>
      <td>行2,列1</td>
      <td>行2,列2</td>
      <td>行2,列3</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3">这是表格页脚</td>
    </tr>
  </tfoot>
</table>
表单元素:

文本输入框:

  //  placeholder 设置提示词 
文本框:<input type="text" placeholder="请输入用户名"> 

密码框:

  密码框:<input type="password">
  密码框:<input type="password" placeholder="请输入密码">

上传文件:

 上传文件:<input type="file">
//上传多个文件 
上传文件:<input type="file" multiple>

单选框:

  // 只有radio的时候,无法实现多选,设置name后可以实现单选 一组只能选择一个 
  //checked 默认选中的 
<input type="radio" name="gender"> 男
<input type="radio" name="gender" checked> 女

复选框:

  //多选框 默认选中
  <input type="checkbox"> 敲代码
  <input type="checkbox" checked> 敲前端代码
  <input type="checkbox" checked> 敲前端 HTML 代码下拉框:
//下拉框
  <select>
    <option>北京</option>
    <option>上海</option>
    <option>广州</option>
    <option>深圳</option>
    <option selected>武汉</option>
  </select>

多行文本输入框:

 //多行文本框
<textarea>请输入评论</textarea> 

开发中常使用label和input输入框配套使用,增加用户视觉效果:

<input type="radio" name="gender" id="man"> <label for="man"></label>
  <label><input type="radio" name="gender"></label>

表单:

<form name="表单名" method="提交方法" action="处理程序">
    ……… 
</form>
<form action="">
    用户名:<input type="text">
    密码:<input type="password">
    <!-- 如果省略 type 属性,功能是 提交 -->
    <button type="submit">提交</button>
    <button type="reset">重置</button>
    <button type="button">普通按钮</button>
  </form>
CSS:

​ CSS是用于对html元素进行修饰美化的,颜色背景字体大小透明度等等。

CSS的三种形式:

  <style>
    /* 定义 */
    .red {
      color: red;
    }
</style>
<div style="color: green; font-size: 30px;">这是 div 标签</div>
<link rel="stylesheet" href="./my.css">
背景:
	background-image:url('gradient2.png');
文字对齐:
	text-align:center; //用于设置文字对其 在块元素中 right/left/justify justify每一行的宽度相同
	vertical-align:center;	 垂直居中文字
块元素居中:
	margin: auto;(必须要设置宽度后才有效果)
	.clearfix { 清除浮动的影响
    overflow: auto;}
	
浮动:
	float:right; 如果是图片浮动则文字会在其周围环绕
	clear:both;最后一个元素清除浮动的影响
超链接跳转:
	<a href="https://www.runoob.com/" target="_blank"> _self _blank 默认是在当前页面跳转
取消超链接下划线:
	text-decoration:none;
	text-decoration:overline/line-through/underline  上面/中间/下面
字体大小:
	font-size:20px; 字体大小
点击:
	a:link {color:#000000;}      /* 未访问链接*/
    a:visited {color:#00FF00;}  /* 已访问链接 */
    a:hover {color:#FF00FF;}  /* 鼠标移动到链接上 */
    a:active {color:#0000FF;}  /* 鼠标点击时 */
边距问题:
	border:1px solid black;
	border-collapse:collapse; 边框折叠成一条线
	border-style:dotted/dotted;	边框演示
	border-style:dotted solid double dashed;
	padding:25px 50px 75px; 上(左右)下
    width: 300px
    margin: 25px;
行内块:
	display:inline; block块元素
可见:
	visibility:hidden;
定位:
    h2{ 
        position:absolute; //绝对定位的位置是相对与最近的父元素(若没有则是相对于html)
        position:relative;//相对定位元素经常被用来作为绝对定位元素的容器块。
        position: sticky; //不会改变位置  
        left:100px;
        top:150px;
    }
溢出:(文字内容大于框的大小是否形成滚动条)
	overflow:visible(呈现在其之外)、scroll(形成滚动条)hidden

	
	
Javascript:

JavaScript(通常简称为JS)是一种广泛用于网页开发的脚本语言。它是一种高级、解释性的编程语言,用于为网页添加交互性和动态功能。就是上网页变的可交互起来。

获取元素常用的几个方法:

  • 根据id获取某个元素:document.getElementById(id); (返回对象)
  • 根据name获取元素:document.getElementsByName(name);(返回对象数组)
  • 根据tagName获取元素:document.getElementsByTagName(tagName);(返回对象数组)
函数定义:
 <script>
    function 函数名(参数列表){
      函数体(返回值使用return语句)
   }
 </script>
获取值:
var inputElement=document.getElementById("card");
var idCard = idCardInput.value;
修改值:
var resultElement=document.getElementById("result");
   resultElement.textContent='邮费:'+fee+"元";
js操控css:
<button type="button" onclick="myFunction()">点我</button>  绑定响应事件
<script>
function myFunction()
{
	document.getElementById("demo").innerHTML="Hello JavaScript!";
}
</script> 
document.getElementById("demo").style.color="#ff0000"; 修改css 
案例分析:
<script>
function f1(){
    var a=document.getElementById("t1").value;  //获取t1标签中的值
    alert("用户在文本框中输入的值为:"+a);// 弹出提示框,显示用户输入的值
}
function f2(){
    var a=document.getElementsByName("sex"); //获取一组标签
    var sex;
    for(var i=0;i<a.length;i++){
        if(a[i].checked){ //如果某个表单元素被选中 则为true
            alert(a[i].value); //提示框输出
            break;
        }
    }   
}
function f3(){
    var a=document.getElementsByName("aihao");
    var aihao="";
    for(var i=0;i<a.length;i++){
        if(a[i].checked){//如果某个复选框元素被选中 则为true
            aihao+=a[i].value+" "; //拼接
        }
             
    }   
     if(aihao==''){
         alert("无爱好");
     }
     else{
         alert("爱好:"+aihao);
     } 
}
function f4(){//下拉框 下拉框无法进行点选 只能滑动 显示最上面的是哪一个
    var a=document.getElementById("jiguan");
    var selectedIndex=a.selectedIndex;//获取是当前是第几个 
    alert(a.options[selectedIndex].value); //获取响应的值
}
</script>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input type="text" id="t1" size="10"/>
<input type="button" id="bt1" value="获取文本框的值" onclick="f1();"/>  // 绑定点击响应函数
<hr>
<input type="radio" name="sex" value="" checked/><input type="radio" name="sex" value=""/><input type="button" id="bt2" value="获取性别" onclick="f2();"/>
<hr>
<input type="checkbox" name="aihao" value="音乐" />音乐
<input type="checkbox" name="aihao" value="画画"/>画画
<input type="checkbox" name="aihao" value="下棋"/>下棋
<input type="button" id="bt3" value="获取爱好" onclick="f3();"/>
<hr>
<select id="jiguan">
<option value="山东">山东</option>
<option value="北京">北京</option>
<option value="广东">广东</option>
</select>
<input type="button" id="bt4" value="获取籍贯" onclick="f4();"/>
</body>
</html>
Jquery:

​ jQuery 是一个广泛使用的 JavaScript 库,它简化了 JavaScript 在网页开发中的操作和处理。jQuery 提供了一组易于使用的函数和方法,使开发者能够更简洁、高效地操作 HTML 元素、处理事件、发送 AJAX 请求等。

引入:
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script src="js/jquery-1.11.1.js"></script>
<%@ page  pageEncoding="UTF-8"%>
<html>
  <head> 
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
    $(function(){
       $("p").click(function(){
       $(this).hide();
    });
   });
</script>
  </head>  
  <body>
   <p>如果你点我,我就会消失。</p>
  </body>
</html>
页面加载
    window.onload=function(){} //原始js写法
    $(function(){
逻辑代码
   });
   //一般使用jquery都将代码放在其中,   $(function(){  })  是让网页全部加载完成后再使用jQuery。

下面是 jQuery 中一些常见操作的简洁示例:

jQuery选择器:
// 通过元素标签名选择元素
$('div')
// 通过class属性值选择元素
$('.class-name')
// 通过ID属性值选择元素
$('#element-id')
// 通过其他属性选择元素
$("div[title='div2']")   $("div[title!='div2']")
// 父 与 子孙们关系
$("#d1 span").css("color","red");
//父子关系
 $("#d1>span").css("color","green");  
//选取紧接在prev元素后的同辈next元素
$("#d1+div").css("color","blue")
//选取所有在prev元素后的同辈siblings元素
$("#d1~div").css("color","gray"); 
//后面两种写法一般不会用到,了解即可。

全(不)选实现:

<%@ page  pageEncoding="UTF-8"%>
<html>
<head> 
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
    $(function(){
      $("#xz").click(function(){
        $(".c1").prop("checked", this.checked);    
          //当全选复选框被点击时,通过 $(".c1").prop("checked", this.checked) 将所有记录复选框(类名为 "c1")的 checked 属性设置为与全选复选框相同的值,从而实现全选或取消全选的功能。
      });
    });
  </script>
</head>  
<body>
  <table border="1">
    <tr>
      <td><input type="checkbox" id="xz"/></td>
      <td>列标题</td>
    </tr>
    <tr>
      <td><input type="checkbox" class="c1"/></td>
      <td>记录1</td>
    </tr>
    <tr>
      <td><input type="checkbox" class="c1"/></td>
      <td>记录2</td>
    </tr>
    <tr>
      <td><input type="checkbox" class="c1"/></td>
      <td>记录3</td>
    </tr>
  </table>
</body>
</html>
$(".c1").prop("checked", this.checked);  
$(".c1").attr("checked", this.checked)

上面两种方法都可以实现全选或者全不选的效果,区别是:从 jQuery 1.6 版本开始,推荐使用 .prop() 方法来设置元素的属性值而不是 .attr() 方法,因为 .prop() 方法更适用于处理属性值的布尔类型。在处理 checked 属性时,使用 .prop() 方法更为准确和可靠。

Jquery操作dom:
//获取元素的HTML内容
 var a=$("#div1").html();
 //获取元素的文本内容。
  var b=$("#div1").text();
  //获取表单元素值
  $("select").val()
 // 插入节点
 var div1=$("<div>div1</div>");
  $("body").append(div1); 
发送 AJAX 请求:
$.ajax({
  url: 'url',
  method: 'GET',
  data: {
    // 请求参数
  },
  success: function(response) {
    // 请求成功后的处理
  },
  error: function(error) {
    // 请求失败后的处理
  }
})
总结:

​ 通过这一小节的学习,我们发现你去手写一个网页属于不简单,前端知识点确实比较多,网上流传着这样一句话前端堪比娱乐圈,一天一个新框架,不过不需要大家都记住,只需要你能懂,在业务层一般都是使用组件开发,大不必过度担心。

第三章 动态网页设计:

jsp基础:

​ JSP(JavaServer Pages)是一种用于创建动态Web页面的Java技术。它是一种服务器端技术,允许开发人员在HTML页面中插入Java代码,以生成动态内容。JSP页面通常包含静态内容和用于动态生成内容的Java代码片段。

​ 在JSP中,Java代码被嵌入在特殊的标签中,通常以"<%“和”%>"括起来。这些标签被称为脚本元素,可以在其中编写Java代码。在JSP页面被访问时,Web服务器会将JSP文件编译为Servlet,并在服务器上执行生成的Servlet来生成动态内容。最终,生成的内容将与静态HTML一起返回给客户端浏览器。

组成:

<%@ page pageEncoding="UTF-8" import="java.util.Date" %>  // jsp指令 如果需要相应的java类库 在这里导入 
<html>
<body>
<script>
document.write(new Date());
</script>
<br/>
<% //这一部分是jsp代码
out.print(new Date());
%>
</body>
</html>

全局变量与局部变量:

<%!int d;%> 带有!是全局变量,<% int a=30;%> 是局部变量,全局变量只有服务器不关就一直生效。

<%@ page pageEncoding="UTF-8" import="java.util.Date" %>
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<%!int  d;%>
<% int a=30;%>
<% int b=30;            
   int c=40;          
   d=d+a+b+c;         
   out.print(d);   
 %>
</body>
</html>

在这里插入图片描述

我们会发现每次刷新依次页面,都会加100,这就说明了这个全局变量没有重复初始化,只要服务器不关就一直++。

 <%@ page pageEncoding="UTF-8"%>
<html>
  <body>
  <%
  request.setCharacterEncoding("UTF-8"); // 告知服务器使用UTF-8编码来解析请求中的字符。
  %>
     1.jsp<br>
     <jsp:include page="2.jsp"> //页面的包含
      <jsp:param name="param1" value="你好"/> // 同时向2.jsp传递 名为param1 值为你好 的参数 
     </jsp:include>
   </body>
</html>
 <%@ page pageEncoding="UTF-8"%>
<html>
  <body>
    2.jsp,获取参数值为:<%=request.getParameter("param1") %> // 获取请求参数
   </body>
</html>

如果我们把上面的代码,改成forword会发送什么呢?

 <%@ page pageEncoding="UTF-8"%>
<html>
  <body>
  <%
  request.setCharacterEncoding("UTF-8");
  %>
     1.jsp<br>
     <jsp:forward page="2.jsp">
      <jsp:param name="param1" value="你好"/>
     </jsp:forward>
   </body>
</html>

在这里插入图片描述

可以发现地址栏没有变化,但是页面数据发送了变化,同时也实现了数据的共享,请求转发(服务器端,客户端地址不变)。

include指令(<%@ include file=“”%>)和标签<jsp:include page=“”/> 有什么区别?

<%@ include file=“”%>) 执行速度块,因为静态,你已经将其在开头的时候写死了,而<jsp:include page=“”/> 属于动态编译,属于可变的。

jsp内部对象:
概述:

​ 这一部分很重要,在web开发中,常常用到数据的共享,那么我们把数据共享的范围限制到哪里呢?本次请求还是本地会话还是本地缓存中的。这就引出了request,session,还是cookie还是application中呢。

​ 先说结论: 地址栏每变化一次就是一次新的请求,网页每关闭一次就是一次新的session会话,Cookie 是存储在客户端本地缓存中,Application 数据存储在服务器内存。

​ 数据资源共享的原则是将范围限制尽可能小,不污染全局。

request

request 是指代表客户端请求的对象。它是 javax.servlet.http.HttpServletRequest 类的一个实例,用于封装客户端发起的 HTTP 请求信息,包括请求方法、URL、头部信息、请求参数等。

​ 在开发的时候尽量不要写绝对路径,可以使用request的相关参数获取某些路径(绝对路径,相对路径)。

 <%@ page pageEncoding="UTF-8"%>
<html>
  <body>
  <%request.setCharacterEncoding("UTF-8");%>
  获取客户端请求的 Servlet 路径:<%=request.getServletPath()%><% out.print("<br>"); %>
  请求所在的绝对路径:<%=request.getRequestURL()%><% out.print("<br>"); %>
  项目工程路径:<%=request.getContextPath()%> <% out.print("<br>"); %>
  请求所在的项目路径(不包括域名和端口):<%= request.getRequestURI()%><% out.print("<br>"); %>
   </body>
</html>

我们一下结果:

在这里插入图片描述

参数传递:

  • get :超链接等等,市面上大部分的操作都是get

  • post:表单提交(因为表单一般含有重要数据,在后台可以对提交的数据进行加密)。

post提交方式,如果参数有中文需要提前设置:

request.setCharacterEncoding("UTF-8")

​ 告知服务器使用 UTF-8 字符编码来解析请求中的参数。

response

​ 它是指代表客户端请求的对象,即 javax.servlet.http.HttpServletRequest 类的实例。该对象封装了客户端发送的 HTTP 请求信息,包括请求方法、URL、头部信息、请求参数等。

​ 这个也很好理解,我们先服务器发送请求(request),服务器给客户端返回的就是响应(response),同时也会向客户端告知一些内容,比如响应头,响应的内容类型,响应的编码等等。

​ 转发与重定向的区别:转发的网页是只能跳转到本应用所有的网页(就是你之前写好的网页),而重定向可以随意跳转,尝试新的请求。

​ 那么我们什么时候使用转发什么时候使用重定向呢?

当涉及到数据共享的时候或者数据传递的时候使用转发,数据传递完毕或者前后事件不同的时候使用重定向。

<%response.sendRedirect("https://www.baidu.com");%>
 response.sendRedirect("main.jsp");//重定向到主页面
session

​ Session 在服务器端存储用户相关的数据,并为每个用户分配一个唯一的会话标识符(Session ID)。该标识符通常通过Cookie在客户端和服务器之间进行传递,或者可以通过URL重写的方式将会话ID附加到URL上。会话对象,用于保存用户的一次“会话”信息。

​ Session 对象是与用户相关联的,因此可以在不同的请求之间共享数据,并且只对特定用户可见。通过使用会话,您可以在用户登录后跟踪其身份、存储购物车数据、实现用户首选项等

session消亡的原因:

  • session.invalidate()手动销毁session对象
  • 用户长时间未进行交互
  • 用户主动关闭浏览器

关于session的时间问题:

在这里插入图片描述

我们发现在不关闭浏览器的情况下,sessionid不会发送变化,不管我们开几个或者刷新都不会改变,其实因为其已经保存在了cookie中,如下图。

在这里插入图片描述

但是我们将所有的浏览器关闭后,重写打开再看看。

在这里插入图片描述

变了吧,因为这是第一次,同时也会把这个sessionid保存起来。

cookie:

​ Cookie对象是由服务器产生并保存到客户端(内存或文件中)的信息,常用它记录用户个人信息及个性化设置。然后以后浏览器会自动携带这个cookie作为请求数据向服务器端发请求。

​ 到这里有的同学可能就会问,session 和cookie有什么区别呢?

​ 我一句话给你说清楚,session是基于cookie实现的,session只能保留当前会话信息,但是如果你得浏览器关闭了,或者长时间没有操作那么session就会更新,而cookie的保留时间更长,当用户访问站点时,可以利用Cookie保存用户首选项或其他信息,这样当用户下次再访问站点时,应用程序就可以检索以前保存的信息。

​ 为什么你登陆淘宝后,下次不用重新登录了?因为在你本机的缓存冲已经保存了你的相关信息,所以浏览器会自动携带这些数据发送请求。很多网站都是这样实现的。

但是Cookie对象并不是Jsp内部对象,需要通过构造函数创建。

​ 现在我们测试一下cookie的创建和访问:

​ 设置:

<%@ page pageEncoding="UTF-8" %>
<%
   Cookie c = new Cookie("name1", "hello");
   response.addCookie(c);
%>
<a href="cookie1.jsp">查看cookie</a>

获取:

<%@ page pageEncoding="UTF-8"  %>
<html>
<body>
<% 
Cookie cookies[] = request.getCookies();
for(int i=0; i<cookies.length; i++) {
         out.print(cookies[i].getName()+":"+cookies[i].getValue()+"<br/>");
}
%>
</body>
</html>

在这里插入图片描述

在这里插入图片描述

我们也可以发现之前设置的cookie可以成功接受,同时这个JSESSIONID 一直没有变,为什么?因为这是一次会话,跳转页面会话不会变。

application

​ Application(应用程序)是指整个 Web 应用程序的上下文环境。它表示在同一个 Web 容器中运行的多个 Servlet、Filter 和其他组件共享的全局环境。Application 上下文数据存储在 Web 服务器的内存中。application是由服务器端产生的,只要服务器端不进行修改,则访问的是同一个!!!

pageContext

pageContext 是在 JavaServer Pages(JSP)中使用的一个对象,它代表当前 JSP 页面的上下文信息。pageContext 对象提供了访问和操作 JSP 页面的各种信息和功能。pageContext 对象是在每个 JSP 页面的请求期间创建的,并且只在当前页面中有效。

pageContext 对象的生命周期与页面的生命周期相同。每次请求访问页面时,都会创建一个新的 pageContext 对象,并且随着请求的完成而销毁。

总结:

数据有效范围对比:

  • <%@ page pageEncoding="UTF-8"  %>
    <html>
    <body>
    <% 
    pageContext.setAttribute("p","pagestr");
    request.setAttribute("r","requeststr");
    session.setAttribute("s","sessionstr");
    application.setAttribute("a","applicationstr");
    %>
    </body>
    </html>
    

分别在链接(或重定向)、转发、换一个浏览器窗口访问、重启服务器后访问讨论其作用域的效果。

pageContext 对象的有效性分析:

  • I:链接(或重定向):当通过链接或重定向跳转到另一个 JSP 页面时,新页面会创建一个新的 pageContext 对象,原页面的 pageContext 对象不再有效,网址发生变化则无效。
  • II:转发:在使用转发将请求从一个 JSP 页面发送到另一个 JSP 页面时,转发目标页面会继承原页面的 pageContext 对象,因此原页面的 pageContext 对象仍然有效,转发网址不变。
  • III:换一个浏览器窗口访问:当在新的浏览器窗口中访问一个 JSP 页面时,该页面会创建一个新的 pageContext 对象,与之前的页面的 pageContext 对象无关。
  • IIII:重启服务器后访问:当服务器重启后,所有的 pageContext 对象都会被销毁,因此之前存在的 pageContext 对象都不再有效。在服务器重启后访问 JSP 页面时,会创建新的 pageContext 对象。

request 对象的有效性分析:

  • I:链接(或重定向):当通过链接或重定向跳转到另一个 JSP 页面时,产生一个新的请求,所以不可以共享。
  • II:转发:在使用转发将请求从一个 JSP 页面发送到另一个 JSP 页面时,不会重新发送一个新的请求,因此原页面的 request 对象仍然有效,可以访问。
  • III:换一个浏览器窗口访问,在 2.jsp 页面中,无法获取在 1.jsp 中存储在 request 对象中的属性值 “requeststr”。因为每个浏览器窗口都有自己独立的会话和请求对象,它们之间的数据不共享。
  • IIII:重启服务器后访问:在 2.jsp 页面中,无法获取在 1.jsp 中存储在 request 对象中的属性值 “requeststr”。因为服务器重启会导致所有请求和会话对象被销毁,之前存储的数据也会丢失。

session 对象的有效性分析:

  • I:链接(或重定向):可以访问。
  • II:转发:在使用转发将请求从一个 JSP 页面发送到另一个 JSP 页面时,不会重新发送一个新的请求,因此原页面的 request 对象仍然有效,可以访问。
  • III:换一个浏览器窗口访问,在 2.jsp 页面中,可以通过 session.getAttribute("s") 来获取属性值 “sessionstr”。因为 session 对象的作用域是跨多个请求和页面的。
  • IIII:重启服务器后访问:在 2.jsp 页面中,无法获取在 1.jsp 中存储在 session 对象中的属性值 “sessionstr”。因为服务器重启会导致所有会话对象被销毁,之前存储的数据也会丢失。

application 对象的有效性分析:

  • I:链接(或重定向):可以访问。
  • II:转发:可以访问。
  • III:换一个浏览器窗口访问:在 2.jsp 页面中,可以通过 application.getAttribute("a") 来获取属性值 “applicationstr”。因为 application 对象的作用域是整个应用程序,可以在不同的浏览器窗口或选项卡之间共享数据。。
  • IIII:重启服务器后访问:在 2.jsp 页面中,无法获取在 1.jsp 中存储在 application 对象中的属性值 “applicationstr”。因为服务器重启会导致所有应用程序的状态被重置,之前存储的数据也会丢失。
EL:

​ EL (Expression Language) 表达式(也称为 JSP EL)是一种用于在JavaServer Pages (JSP) 和 JavaServer Faces (JSF) 中访问和操作数据的简洁语法。EL 表达式提供了一种方便的方式来获取、设置和操作在作用域中可用的变量、属性和方法。

EL 表达式使用 ${} 的语法来引用和操作数据。在 ${} 中可以使用以下几种语法:

  1. 访问变量和属性:${variable}${object.property}例如:${name}${user.name}
  2. 调用方法:${object.method()}${object.method(param1, param2)}例如:${user.getName()}${user.add(5, 3)}
  3. 访问数组和列表元素:${array[index]}${list[index]}
    例如:${array[0]}${list[2]}
  4. 执行算术和逻辑运算:${num1 + num2}${boolean1 && boolean2}
    例如:${2 + 3}${true && false}
  5. 使用条件和循环:${condition ? value1 : value2}${for(item : collection)} 等。
    例如:${age >= 18 ? '成年' : '未成年'}${for(item : list)}

​ 一般用于将数据存到 page、request、session、application四种范围内的对象。实现数据共享。

数据共享案例:

<%@ page import="java.util.*" pageEncoding="UTF-8"%>
<html>
  <head><title>访问集合中的元素</title></head>  
  <body>
   <% String[] firstNames = {"龙","萍","杨"};  //定义数组
    ArrayList<String> lastNames = new ArrayList<String>();  //定义List
    lastNames.add("陈"); lastNames.add("邓"); lastNames.add("于");
    HashMap<String,String> roleNames = new HashMap<String,String>(); //定义Map 类似键值对 
    roleNames.put("volunteer","志愿者");
    roleNames.put("missionary","工作人员");
    roleNames.put("athlete", "运动员");
     // 必须将数据存到响应范围内 才可以使用el表达式
     // pageContext.setAttribute() 是将属性存到页面范围 
      // 数据仅仅在当前页面有效 
    pageContext.setAttribute("first",firstNames);
    pageContext.setAttribute("last",lastNames);
    pageContext.setAttribute("role",roleNames);
   %>
    <h2>EL访问集合</h2>
    <ul>
        
       <li>${last[0]}${first[0]}:${role["volunteer"]}
       <li>${last[1]}${first[1]}:${role["athlete"]}
       <li>${last[2]}${first[2]}:${role["missionary"]}
        // ${role["volunteer"]} 是访问role的volunteer属性对应的值
        //  ${first[2]} 是访问first数组的第二个元素
   </ul>
  </body>
</html>

表单提交案例:

<%@ page import="java.util.*" pageEncoding="UTF-8"%>
<html>
  <head>
      <title>提交信息页面</title>
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
     <form action="2.jsp" method="post">
       姓名 <input type="text" name="name"><br/>
       性别 <input type="text" name="sex"><br/>
       语言 <input type="text" name="lang"><br/>
       电话 <input type="text" name="regTelephone"><br/>
       邮件 <input type="text" name="email"><br/>
       简介<textarea rows="2" cols="30" name="intro"></textarea><br/><br>
       爱好:音乐<input type="checkbox" name="aihao" value="音乐"/>
             篮球<input type="checkbox" name="aihao" value="篮球"/>
             足球<input type="checkbox" name="aihao" value="足球"/><br/><br>
       <input type="submit" value="提交"/>&nbsp;<input type="reset" value="重置"/> 
   </form> 
  </body>
</html>
<%@ page pageEncoding="UTF-8"  %>
<html>
   <head><title>用户注册:使用EL获取用户提交数据</title></head>
   <body>
     <h2>您提交的内容如下:</h2>
     <% request.setCharacterEncoding("UTF-8"); %> 
      姓名:${param.name}<br/>
      性别:${param.sex}<br/>
      外语:${param.lang}<br/>
      电话:${param.regTelephone}<br/>
     email:${param.email}<br/>
      个人简介:${param.intro}<br/>
      爱好:${paramValues.aihao[0]} ${paramValues.aihao[1]} ${paramValues.aihao[2]}
   </body>
</html>

request.setCharacterEncoding("UTF-8") 这一行的目的是对于接受的表单数据使用utf-8进行编码,${param.email} 这个获取表单数据,我们发现这样写,十分简单。

在这里注意区分一下jsp中的内部对象,和EL表达式中的内部对象。

  • jsp:pageContext|request|session|application

  • EL:pageScope|requestScope|sessionScope|applicationScope

  • 注意,如果不加范围获取数据,默认是在pageScope的作用域下。

JSTL:

​ JSTL(JavaServer Pages Standard Tag Library)是用于简化在 JavaServer Pages (JSP) 中编写和管理标记的标准标签库。它提供了一组标签和函数,用于处理常见的任务,如条件判断、循环迭代、格式化日期和数值等。

​ JSTL 的主要目标是将页面逻辑与页面设计和展示分离,以提高 JSP 页面的可维护性和可读性。通过使用 JSTL,开发人员可以避免在 JSP 中编写大量的 Java 代码,而是使用简单的标签和表达式完成常见的任务。

​ 如果大家对Python的web框架Flask和Django框架熟悉的话,可以对jstl会有一个更深层次的理解,jstl的语法类似Jinja2,Jinja2 是一个流行的、现代的 Python 模板引擎,用于生成动态内容,特别是用于 Web 开发中的前端和后端页面渲染。

​ 注意jstl的使用需要相应的jar包和jsp指令:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
   <taglib uri="http://java.sun.com /jsp/jstl/core" prefix="c" /> 

如下图:

在这里插入图片描述

我写几个比较常用的语法:

if语句:

  • <c:if test="condition">...</c:if>:条件语句,根据指定的条件判断是否执行包含的内容。
<c:if test="${user.isAdmin}">
  <p>Welcome, admin user!</p>
</c:if>

循环:

  • <c:forEach var="item" items="collection">...</c:forEach>:循环迭代语句,遍历集合并在每次迭代中执行包含的内容。
<c:forEach var="item" items="${products}">
  <p>${item.name}: ${item.price}</p>
</c:forEach>
//products一般都是一个列表套字典的形式 item表示里面的每一项

还有一种形式:

<c:forEach var="i" begin="10" end="50" step="5" varStatus="status">
  Index: ${status.index}, Count: ${status.count}, First: ${status.first}, Last: ${status.last}<br/>
</c:forEach>

varStatus 对象(在上面的例子中命名为 status)具有以下属性:

  • index:当前循环的索引值,所在位置。
  • count:当前循环的计数值(从 1 开始)。
  • first:一个布尔值,表示当前循环是否为第一个元素。
  • last:一个布尔值,表示当前循环是否为最后一个元素。

​ 我们使用 <c:forEach> 标签创建一个循环,从 10 到 50,每次递增 5。循环变量被命名为 i。通过设置 varStatus="status",我们将循环状态存储在名为 status 的变量中。我们看一下运行结果:

在这里插入图片描述

赋值:

  • <c:set var="variable" value="expression" scope="scope">:变量设定语句,将指定的值赋给变量,并可选择将变量存储在指定的作用域中。
<c:set var="discount" value="${product.price * 0.1}" />
<p>Discounted price: ${product.price - discount}</p>

​ 上述示例中,<c:set> 标签将计算商品价格的 10% 并将结果赋给 discount 变量,然后在 <p> 标签中显示折扣后的价格

多分支选择:

  • <c:choose> <c:when test="condition">...</c:when> <c:otherwise>...</c:otherwise> </c:choose>:选择语句,根据条件选择执行其中一个分支。
<c:choose>
  <c:when test="${user.gender == 'male'}">
    <p>Welcome, Mr. ${user.name}!</p>
  </c:when>
  <c:when test="${user.gender == 'female'}">
    <p>Welcome, Ms. ${user.name}!</p>
  </c:when>
  <c:otherwise>
    <p>Welcome, ${user.name}!</p>
  </c:otherwise>
</c:choose>

输出:

<c:set var="message" value="<script>alert('Hello');</script>" />

<c:out value="${message}" />
相关案例:
表单案例:
<%@ page pageEncoding="UTF-8" %>
<html>
<body>
<form method="post">
输入第一个整数:<input type="text" name="n1"><br>
输入第二个整数:<input type="text" name="n2"><br>
<input type="submit" value="求和"/>
</form>
<%
String sn1=request.getParameter("n1");
if(sn1!=null){
    String sn2=request.getParameter("n2");
    int n1=Integer.parseInt(sn1);
    int n2=Integer.parseInt(sn2);
    out.print("结果为:"+(n1+n2));
}
%>
</body>
</html>

​ 我们分析一下这个页面,注意如果先用jsp或者el表达式获取表单数据,必须把数据放在一个form表单中,还要有一个提交按钮。上面的代码action没有写,那么就是把数据提交给当前页面,然后直接使用jsp在当前页面里面输出,但是点击submit按钮后,后进行页面刷新,因为点击提交按钮后会进行跳转,只不过这个跳转到当前页面。

​ 但是我们如果想保留我们之前输入的值呢?可以使用el表达式,将input标签的value属性赋值,EL表达式还有一个好处,如果没有那个值,什么都不会显示,没有null或者未定义,接下来我们看看效果。

输入第一个整数:<input type="text" name="n1" value="${param.n1}"><br>
输入第二个整数:<input type="text" name="n2" value="${param.n2}"><br>

在这里插入图片描述

<%@ page pageEncoding="UTF-8" %>
<html>
<body>
<form method="post" >
输入第一个整数:<input type="text" name="n1" value="${param.n1}"><br>
输入第二个整数:<input type="text" name="n2" value="${param.n2}"><br>
<input type="submit" value="求和"/>
</form>
<%
String sn1=request.getParameter("n1");
if(sn1!=null){
    String sn2=request.getParameter("n2");
    int n1=Integer.parseInt(sn1);
    int n2=Integer.parseInt(sn2);
    out.print("结果为:"+(n1+n2));
}
%>
</body>
</html>

这里在将一种实现方法:

展示+处理:

在一个页面进行提交,在另一个页面接受,在转到一开始的页面显示?

​ 我们想一想如何实现,我们可以在另一个页面进行jsp相关操作,然后在转发到那个页面,注意必须是转发,而不能能说是重定向,因为重定向会发送一个新的请求,我们保存的请求对象种的数据共享就不合适了,如果想使用重定向,需要你把数据共享范围变成session及其以上。

a1.jsp:

<%@ page pageEncoding="UTF-8" %>
<html>
<body>
<form method="post" action="a2.jsp">
输入第一个整数:<input type="text" name="n1" value="${param.n1}"><br>
输入第二个整数:<input type="text" name="n2" value="${param.n2}"><br>
<input type="submit" value="求和"/>
</form>
${result}
</body>
</html>

上面使用EL表达式的好处是,如果没有相应的值,不会显示null或者报错,这个算是el 表达式的优点。

a2.jsp

<%@ page pageEncoding="UTF-8"%>
<html>
<body>
    <%
        String sn1 = request.getParameter("n1");
        String sn2 = request.getParameter("n2");
        int n1 = Integer.parseInt(sn1);
        int n2 = Integer.parseInt(sn2);
        String s="结果为:" + (n1 + n2);
        request.setAttribute("result", s);
    // 保存在请求范围内
         
    %>
    <jsp:forward page="a1.jsp"></jsp:forward>
    // 注意是转发 
</body>
</html>
自动登录:

​ 要想实现自动登录,一般来说把相关信息放在cookie里面,为什么不放在session中呢?因为cookie相当于保存在客户端的缓存,你如果把信息放在session中,每一次打开浏览器都是一次新的会话,怎么实现自动登录呢?

login.jsp

<%@ page pageEncoding="UTF-8"%>
<html>
<head>
<title>用户登录</title>
</head>
<body>
    <form method="post" action="./logincheck.jsp">
        用户名:<input type="text" size="10" name="username"><br/>
        密 码:<input type="password" name="userpwd" /><br/>
        <input type="submit" value="登录">
    </form>
</body>
</html>

logincheck.jsp

<%@ page pageEncoding="UTF-8"%>
<html>
<head>
<title>登录处理</title>
</head>
<body>
    <%
        request.setCharacterEncoding("UTF-8");
        String un = request.getParameter("username");//获取用户名
        if (un != null) {
            Cookie c = new Cookie("username", un);
            c.setMaxAge(30 * 24 * 3600);
            response.addCookie(c);//将Cookie对象保存到客户端
            response.sendRedirect("main.jsp");//重定向到主页面
        }
    %>
</body>
</html>

ok?我们看看效果。 重点是什么我放在客户端的缓存中!

在这里插入图片描述

聊天场所:

​ 说一下重点吧,重点是把信息共享限制在application中,就是服务器的应用信息中,只要服务器不关,我们就可以访问到,也不能放在cookie里,因为cookie你只能自己用,而且cookie相关字段是有数据长度限制的。

表单提交技巧:

​ 如果我们想实现点击某个操作框,提交表单,而不是每次都使用那个input标签的submit属性,可以这样写:

<html>
<body>
<iframe src="content.jsp" name="content" width="100%" height="80%"></iframe>
<form action="addinfo.jsp" target="content" id="chatform" method="post">
      昵称:<input type="text" name="nicheng" id="nicheng">
       发言:<input type="text" name="info" id="info">
       <input type="button" value="确定" onclick="check()">
    </form>
    <script>
      function check(){
           document.getElementById("chatform").submit();
          }
      }
    </script>
</body>
</html>
路径问题:

关于jsp中的路径问题,不要写 / ,/ 会被任务是从项目路径开始,./ 是在当前文件所在的文件夹下找。

在这里插入图片描述

以下四种写法均可。

 <form method="post" action="/javaweb1/logincheck.jsp"> //绝对路径
<form method="post" action="logincheck.jsp"> // 相对路径
<form method="post" action="./logincheck.jsp"> //相对路径
 <form method="post" action="${pageContext.request.contextPath}/logincheck.jsp> //${pageContext.request.contextPath}是EL表达式 会自动获取当前所在工程名 即/javaweb1
两种获取cookie的方式:

第一种使用jsp:

<% 
Cookie cookies[] = request.getCookies(); //返回的是一个列表 
for(int i=0; i<cookies.length; i++) {
   // getName获取cookie的值 getvalue() 获取cookie对应键的值
         out.print(cookies[i].getName()+":"+cookies[i].getValue()+"<br/>");
}
%>

<% 
Cookie[] cookies = request.getCookies();
if (cookies != null) {
    for (Cookie cookie : cookies) {
        out.print(cookie.getName() + ":" + cookie.getValue() + "<br/>");
    }
}
%>

使用EL表达式:

<c:forEach var="cookie" items="${cookie}">
  Cookie Name: ${cookie.key}<br/>
  Cookie Value: ${cookie.value}<br/><br/>
</c:forEach>
强制类型转化:

如下是通过jsp获取存储应用对象里面的数据,infoList 是一个列表,但是我们最好使用(List<String>) 将其真正转化为java类型的列表。

<%
   List<String> infoList=(List<String>)application.getAttribute("infoList");
    %>
总结:

这一章是考试的重点,也是难点,请大家充分理解jsp内部对象,不管大家从事前端或者后端一定理解数据的隔离性,我这个数据应该存在什么范围内,不要污染全局。

第四章 JDBC:

​ JDBC是Java的一种API,用于与关系型数据库进行连接和交互。它提供了一组用于执行SQL语句、处理结果集和管理数据库连接的类和接口。

​ 我希望大家从基础开始,虽然说写jdbc相对比较麻烦,但是这为ORM(对象关系映射)框架打下来基础,可能很多框架已经不要写sql语句了,某些组件已经继承了jdbc的作用,利于Python的web框架Flask和Django,还有Java的Hibernate和MyBatis,这些框架非常简洁,但是其实就是jdbc的封装。

查询操作:
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:13306/javaweb";
Connection con=DriverManager.getConnection(url,"root","xxx123");
String sql="select * from student";
PreparedStatement pst=con.prepareStatement(sql);
ResultSet rs=pst.executeQuery();
while(rs.next()){

	Int aa=rs.getInt(1);			
    String a=rs.getString(2);
}

​ 获取值: 注意下标是从1开始

删除操作:
		Class.forName("com.mysql.jdbc.Driver");
		String url = "jdbc:mysql://localhost:13306/javaweb";
		Connection con = DriverManager.getConnection(url, "root", "xxx123");
		String sql = "delete from student where id=?";  //占位符
		PreparedStatement pst = con.prepareStatement(sql);
		pst.setInt(1, id);  //放入值
		pst.executeUpdate(); //执行
		pst.close();
		con.close();
		pageContext.forward("query.jsp"); //转到
修改操作:
		Class.forName("com.mysql.jdbc.Driver");
		String url = "jdbc:mysql://localhost:13306/javaweb";
		Connection con = DriverManager.getConnection(url, "root", "xxx123");
		String sql = "update student set sno=?,sname=?,sex=? where id=?";
		PreparedStatement pst = con.prepareStatement(sql);
		pst.setString(1, sno);
		pst.setString(2, sname);
		pst.setString(3, sex);
		pst.setInt(4, id);
		pst.executeUpdate();
		pst.close();
		con.close();
		pageContext.forward("query.jsp");
插入操作:
    Class.forName("com.mysql.jdbc.Driver");
    String url="jdbc:mysql://localhost:3306/student";
    Connection con=DriverManager.getConnection(url,"root","sa");
    String sql="insert into register values (null,?,?)";
    PreparedStatement pst=con.prepareStatement(sql);
    pst.setString(1, account);
    pst.setString(2, password);
    pst.executeUpdate();
    pst.close();
    con.close();
案例:
选择框问题:

选择框是点击操作,我们需要通过js模拟勾选操作,不难直接显示之前的值

var s=document.getElementsByName("sex");
if('${param.sex}'=='男'){
    s[0].checked=true;
}
else{
    s[1].checked=true; 
}

​ 注意:'${param.sex}' 外面的 ‘’ 不可以被去掉,因为EL表达式仅仅是获取那个值,而并没有说类型的问题。

关于转发:

​ 只有如下两种写法:

pageContext.forward("add.jsp")
request.getRequestDispatcher("add.jsp").forward(request, response)

没有request.forword("add.jsp").

细节问题:
package demo;

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

public class query {

	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.cj.jdbc.Driver");// 加载驱动
        // 连接字符串                      ip地址:mysql的端口号 /数据库名     
        String url = "jdbc:mysql://localhost:13306/javaweb"; 
        Connection con = DriverManager.getConnection(url, "root", "hubing123");// 连接数据库
       String id="2";
        // 执行查询语句
        String sql2 = "select * from student where id= ? ";// 准备sql语句
        PreparedStatement pst2 = con.prepareStatement(sql2);// 创建封装语句的对象
        pst2.setString(1, id);
        String fullSql = pst2.toString();
        System.out.println("完整的SQL语句:" + fullSql);

        ResultSet rs = pst2.executeQuery();// 查询结果返回到ResultSet中
        while (rs.next()) {// 利用循环输出ResultSet中的内容
            System.out.println( rs.getString(1) + "," + rs.getString(2)+"," + rs.getString(3));
     
        }
        rs.close();// 关闭结果集
        pst2.close();// 执行sql语句1
        con.close();// 关闭连接
	}

}

在这里插入图片描述

 String id="2";
        // 执行查询语句
        String sql2 = "select * from student where id= ? ";// 准备sql语句
        PreparedStatement pst2 = con.prepareStatement(sql2);// 创建封装语句的对象
        pst2.setString(1, id);
        String fullSql = pst2.toString();
        System.out.println("完整的SQL语句:" + fullSql);

我想看看拼接后的sql语句是 select * from student where id= '2' 还是 select * from student where id= 2 ,结论证明你放入的是什么,他拼接起来就是什么类型。

登录细节:

​ 如何证明用户是登录了还是没有登录,我们可以在登录页面提交成功后,将用户的信息放在session或则cookie中,然后我们下次只要验证sesson或者cookie是否有用户的信息。

session.setAttribute("userid",account);
response.sendRedirect("index.jsp");
SQL注入:

这个问题一般出现在登录页面,登录页面一般是对数据库进行查询,判断这个用户在数据库中的信息是否符合标准,但是如果在查询数据库的时候,使用字符串拼接这种写法可能会出现sql注入的问题,因为如果传入一个恒等式,那么就 符合条件了,如下:

存在sql注入的问题:

<%
      request.setCharacterEncoding("UTF-8");
      String account=request.getParameter("account");
      if(account!=null){
       String pwd=request.getParameter("password");
          try{
         Class.forName("com.mysql.jdbc.Driver");
         String url="jdbc:mysql://localhost:3306/test";
         Connection con=DriverManager.getConnection(url,"root","sa");
         String sql="select * from user where userid='"+account+"' and userpwd='"+pwd+"'";
         System.out.println(sql);
         PreparedStatement pst=con.prepareStatement(sql);
         ResultSet rs=pst.executeQuery();
         %>

修改:

// ...
String sql = "select * from user where userid=? and userpwd=?";
System.out.println(sql);
PreparedStatement pst = con.prepareStatement(sql);
pst.setString(1, account);
pst.setString(2, pwd);
ResultSet rs = pst.executeQuery();
// ...

第五章:JavaBean

简介:

​ JavaBean是Java语言中的一种特殊类,它遵循特定的命名规范和编程规范,用于封装数据和提供访问方法。JavaBean类通常用于在不同组件之间传递数据,例如在MVC架构中的视图、控制器和模型之间。就是我们要进行封装,工具类,实体包,数据库操控包依次分开,各尽其职,利于后期开发和维护。

以下是JavaBean的一些特征和约定:

(1) 实体类(entity.*):实体类用于封装实体数据,通常只包含属性及对应的 getter 和 setter 方法。实体类的目的是表示业务领域中的实际对象,例如数据库表的行或其他业务对象。

样例:

package com.example.entity;

public class User {
    private int id;
    private String username;
    private String email;

    public User() {
        // 无参构造函数
    }

    // Getter和Setter方法
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

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

(2)工具类(util.*):工具类封装了一组通用的方法,这些方法通常是静态的,可以通过类名直接调用。工具类用于提供各种功能,如数据加密/解密、日期处理、文件操作、数据库连接等。

工具类样例:

package com.example.util;

public class EncryptionUtils {
    public static String encrypt(String data) {
        // 实现加密逻辑
        return encryptedData;
    }

    public static String decrypt(String encryptedData) {
        // 实现解密逻辑
        return decryptedData;
    }
}

(3) 数据库操作类(dao.*):数据库操作类封装了基本的数据库操作,如增删改查等。通常,首先设计一个接口来定义数据库操作的方法,然后实现该接口的具体类来实现这些方法并与数据库进行交互。

数据库操控类样例:

package com.example.dao;

import com.example.entity.User;

public interface UserDao {
    void addUser(User user);
    void updateUser(User user);
    void deleteUser(int userId);
    User getUserById(int userId);
}

package com.example.dao.impl;

import com.example.dao.UserDao;
import com.example.entity.User;

public class UserDaoImpl implements UserDao {
    @Override
    public void addUser(User user) {
        // 实现添加用户的逻辑
    }

    @Override
    public void updateUser(User user) {
        // 实现更新用户的逻辑
    }

    @Override
    public void deleteUser(int userId) {
        // 实现删除用户的逻辑
    }

    @Override
    public User getUserById(int userId) {
        // 实现根据ID获取用户的逻辑
        return user;
    }
}
案例:
学生表CURD:

项目结构:

在这里插入图片描述

实体包我就不讲了,就是一个类,然后构造函数还有一些getset的函数。

看一下数据操控包:

在这里插入图片描述

JdbcUtil.java

package util;
import java.sql.*;
import java.util.Properties;
public final class JdbcUtil { // 创建一个不可以修改的类 
	private static String driver ; //驱动
	private static String url ; // 数据库url
	private static String user ; //用户名
	private static String password ;// 密码 
     private static Properties pr=new Properties();//构造一个对象 
	private JdbcUtil() {}
	static { 
	   try {pr.load(JdbcUtil.class.getClassLoader().getResourceAsStream("db.properties")); //读取文本的db.properties配置文件
            //接下来依次获取
		  driver=pr.getProperty("driver");
		  url=pr.getProperty("url");
		  user=pr.getProperty("username");
		  password=pr.getProperty("password");
		  Class.forName(driver);
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
    // 获取连接
	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection(url, user, password);
	}
    //释放关闭连接
	public static void free(ResultSet rs, Statement st, Connection conn) {
		try { if (rs != null) rs.close();
		} catch (SQLException e) {e.printStackTrace();
		} finally {
			try { if (st != null) st.close();
			} catch (SQLException e) {e.printStackTrace();
			} finally {
				  if (conn != null)
				    try { conn.close();
				    } catch (SQLException e) {e.printStackTrace();
				   }
		             }
		     }
	    }
	public static void main(String[] args) throws Exception{
		JdbcUtil.getConnection();
	}
	}

我们接下来主要看这个实体操控包在干什么:

StudentDao.java

package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import util.JdbcUtil;
import entity.Student;
public class StudentDao {
   // 添加操作 
   public void add(Student student) throws Exception{
	 Connection conn = null; //初始化数据库连接对象
	 PreparedStatement ps = null;// 初始化数据库预处理对象
	 try {
		 conn = JdbcUtil.getConnection();
		 String sql = "insert into student  values (null,?,?,?) ";
		 ps = conn.prepareStatement(sql);
         //更新sql语句中的参数设置值
		 ps.setString(1, student.getSno());
		 ps.setString(2,student.getSname());
		 ps.setString(3,student.getSex());
          // student.getSno() student.getSex() student.getSname() 是实体类的对外接口
		 ps.executeUpdate();//执行 
	 }finally {JdbcUtil.free(null,ps, conn);}//释放
   }
   //更新操作
   public void update(Student student) throws Exception{
	Connection conn = null; //初始化数据库连接对象
	PreparedStatement ps = null;// 初始化数据库预处理对象
	try {
		conn = JdbcUtil.getConnection();
		String sql = "update student set sno=?,sname=?,sex=? where id=? ";
		ps = conn.prepareStatement(sql);
        // sql 语句填充
		ps.setString(1,student.getSno());
		ps.setString(2,student.getSname());
		ps.setString(3, student.getSex());
		ps.setInt(4, student.getId());
		ps.executeUpdate();
        // 释放 
	}finally {JdbcUtil.free(null,ps, conn);}
   }
  //删除一条数据
   public void delete(int id) throws Exception{
	 Connection conn = null;
	 PreparedStatement ps = null;
	 try {
		conn = JdbcUtil.getConnection();
		String sql = "delete from student where id=?";
		ps = conn.prepareStatement(sql);
		ps.setInt(1,id);
		ps.executeUpdate();
	}finally {JdbcUtil.free( null,ps, conn);}
   }
   // 根据id主键值查找学生信息 
   public Student findStudentById(int id) throws Exception{
	Connection conn = null;
	PreparedStatement ps = null;
	ResultSet rs = null;
       // 在外面创建是为了 里面可以对student进行修改 
	Student student=null;
	try {
		conn = JdbcUtil.getConnection();
		String sql = "select * from student where id=? ";
		ps = conn.prepareStatement(sql);
		ps.setInt(1, id);
		rs=ps.executeQuery();
		if(rs.next()){
		   student=new Student(); ///构造一个对象 
		   student.setId(rs.getInt(1));
		   student.setSno(rs.getString(2));
		   student.setSname(rs.getString(3));
		   student.setSex(rs.getString(4));
		}
	}finally {JdbcUtil.free(rs, ps, conn);}
	return student;
   }
   //返回 [ student1,student2,......] 形式的列表 
   public List<Student> query() throws Exception{
	Connection conn = null;
	PreparedStatement ps = null;
	ResultSet rs = null;
       //Student形列表
	List<Student> studentList=new ArrayList<Student>();
	try {
		conn = JdbcUtil.getConnection();
		String sql = "select * from student ";
		ps=conn.prepareStatement(sql);
		rs=ps.executeQuery();
		while(rs.next()){
		   Student student=new Student(); 
		   student.setId(rs.getInt(1));
		   student.setSno(rs.getString(2));
		   student.setSname(rs.getString(3));
		   student.setSex(rs.getString(4));
            //放入列表 
		   studentList.add(student);
		}
	}finally {JdbcUtil.free(rs, ps, conn);}
      //将列表返回
	return studentList;
   }
}

我们在看看那个jsp文件:

 body{
      text-align:center;
  }
  th,td{
          border:2px solid gray;
          text-align:center;
          padding:3px 10px;
  }
  table{
          border-collapse:collapse; 
          margin:10px auto;
  }
  #form1{
          padding:20px;
          display:none;
          position:fixed;
          top:50%;
          left:50%;
          width:300px;
          height:200px;
          z-index:1000;
          margin-left:-200px;
          margin-top:-200px;
           background: #88f;}
<%@ page  pageEncoding="UTF-8" import="java.util.*,entity.*,dao.*"%>
 <taglib uri="http://java.sun.com /jsp/jstl/core" prefix="c" /> 
<html>
<head>
</head>
<body>
<%
StudentDao studentDao=new StudentDao(); //创建一个实体操控对象 
request.setCharacterEncoding("UTF-8");//设置请求的字符编码方式为 UTF-8
String op=request.getParameter("op");// 获取操作类型 CURD
if(op!=null){
if("add".equals(op)){ //添加   
    Student student=new Student(request.getParameter("sno"),request.getParameter("sname"),request.getParameter("sex"));
    try{studentDao.add(student);}//通过实体操控类添加对象
    catch(Exception e){
        out.print("<script>alert('学号不唯一')</script>");
    }
}
else if("update".equals(op)){ //更新
Student student=new Student();
student.setId(Integer.parseInt(request.getParameter("id")));
student.setSno(request.getParameter("sno"));
student.setSname(request.getParameter("sname"));
student.setSex(request.getParameter("sex"));
try{studentDao.update(student);}
catch(Exception e){
    out.print("<script>alert('更新失败,学号不唯一')</script>");
}
}
else if("delete".equals(op)){ //根据主键id删除对象 
studentDao.delete(Integer.parseInt(request.getParameter("id")));
}
}
    //操控完 还要获取 所有对象来展示 
List<Student> studentList=studentDao.query();
pageContext.setAttribute("studentList",studentList); //数据共享 
 %>
  <h3><a href="javascript:add()">添加记录</a></h3> 
 <h2>学生信息</h2> 
   <table>
   <tr><th>学号</th><th>姓名</th><th>性别</th><th>修改</th><th>删除</th></tr>
  <c:forEach items="${studentList}" var="student" varStatus="st">
  <tr>
   <td>${student.sno}</td>
   <td>${student.sname}</td>
   <td>${student.sex}</td>
     <td><a href="javascript:update(${student.id},'${student.sno}','${student.sname}','${student.sex}')">修改</a></td>
   <td><a href="query.jsp?op=delete&id=${student.id}" οnclick="return confirm('确实要删除吗?')">删除</a></td>    
  </tr>
 </c:forEach> 
 </table>
 <form method="post" id="form1">
学号<input type="text" name="sno" id="sno"/><br><br>
 姓名<input type="text" name="sname" id="sname"/><br><br>
性别<input type="radio" name="sex" value="男" checked/>男<input type="radio" name="sex" value="女" />女<br><br>
 <input type="hidden" name="op" value="" id="op"/>
 <input type="hidden" name="id" id="id"/>
 <input type="submit" value="" id="bt"/>
 <input type="reset" value="重置"/>
  <input type="button" value="关闭" οnclick="document.getElementById('form1').style.display='none';"/>
 </form>
 <br>
 <script>
 function add(){
     document.getElementById("bt").value="添加";
     document.getElementById("op").value="add";
     document.getElementById("form1").style.display="block";
      document.getElementById('form1').action='query.jsp';
 }
 function update(id,sno,sname,sex){
     document.getElementById("bt").value="修改";
     document.getElementById("op").value="update";
     document.getElementById("id").value=id;
     document.getElementById("sno").value=sno;
     document.getElementById("sname").value=sname;
     var sexs=document.getElementsByName("sex");
     if(sex=='男'){
         sexs[0].checked=true;sexs[1].checked=false;
     }
     else{
         sexs[0].checked=false;sexs[1].checked=true;
     }
     document.getElementById("form1").style.display="block";
     document.getElementById('form1').action='query.jsp';
      
 }
 </script>
</body>
</html>

第六章 servlet/过滤器/监听器

servlet

​ Servlet是一种Java编程语言类,用于扩展Web服务器的功能并为Web应用程序提供动态内容。它是Java企业版(Java EE)的基本组件,常用于开发服务器端的Web应用程序。

​ 当向Web服务器请求一个servlet时,服务器会调用servlet的方法来处理请求并生成响应。Servlet可以执行各种任务,如从数据库检索数据、处理表单提交、生成动态HTML内容以及与其他Web服务交互。

我画一幅图片给大家讲一下上面这句话是什么意思。

在这里插入图片描述

我们可以看到servlet相当于一个中间件,起到了数据处理的功能,同时将处理后的数据保存在请求或者session内,前端页面通过EL表达式展示即可。

servlet创建:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

当客户端向服务器发送HTTP请求时,可以使用不同的HTTP方法,如GET和POST。在Servlet中,可以使用doGet()doPost()方法来处理这些请求。

  1. doGet(HttpServletRequest request, HttpServletResponse response):

    • 用于处理HTTP GET请求。
    • 通常用于从服务器获取数据,如检索数据库记录或执行一些只读操作。
    • 可以通过HttpServletRequest对象获取请求参数、请求头、会话信息等。
    • 可以使用HttpServletResponse对象生成并发送响应给客户端。
  2. doPost(HttpServletRequest request, HttpServletResponse response):

    • 用于处理HTTP POST请求。
    • 通常用于向服务器提交数据,如表单提交或执行一些需要修改服务器状态的操作。
    • 可以通过HttpServletRequest对象获取POST请求中的表单参数、请求头、会话信息等。
    • 可以使用HttpServletResponse对象生成并发送响应给客户端。

    下面是一个默认的servlet的,我们需要对其内部doGet() 和doPost()进行修改。

@WebServlet("/demo") // 如果想要修改URl 可以在这里修改
public class demo extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public demo() {
        super();
    }
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response); //两个函数之间可以相互调用 
	}

}
内部对象:

以下是Servlet中常用的内部对象:

  1. HttpServletRequest:表示HTTP请求的对象。它提供了访问请求的各种属性和数据的方法。一些常见的方法包括:
    • getParameter(name):获取指定名称的请求参数的值。
    • getMethod():获取HTTP请求的方法(如GET、POST等)。
    • getRequestURL():获取请求的URL。
    • getSession():获取与请求关联的会话对象。
    • getHeader(name):获取指定名称的请求头的值。
  2. HttpServletResponse:表示HTTP响应的对象。它提供了生成和发送响应给客户端的方法。一些常见的方法包括:
    • setContentType(type):设置响应的内容类型。
    • getWriter():获取用于写入响应数据的PrintWriter对象。
    • setStatus(status):设置响应的状态码。
    • sendRedirect(url):将响应重定向到指定的URL。
  3. HttpSession:表示与客户端关联的会话对象。它用于在多个请求之间存储和共享数据。一些常见的方法包括:
    • setAttribute(name, value):在会话中设置属性的值。
    • getAttribute(name):获取会话中指定属性的值。
    • removeAttribute(name):从会话中删除指定的属性。
  4. ServletContext:表示Servlet上下文的对象。它提供了与Servlet容器环境相关的信息和功能。一些常见的方法包括:
    • getRealPath(path):获取在服务器上的实际文件路径。
    • getRequestDispatcher(path):获取用于将请求转发到其他资源的RequestDispatcher对象。
    • getInitParameter(name):获取指定名称的初始化参数的值。
  • 输出: PrintWriter out=response.getWriter();
  • session:HttpSession session=request.getSession();
  • application:ServletContext application= this.getServletContext();
路径细节:

不同情况下/ 表示的路径不同:

链接,表单提交、重定向时:

/代表:http://localhost:8080,所以需要在后面写上项目工程所在路径,${pageContext.request.contextPath} 可以项目工程名字,被解释为/项目工程,那么在和http://localhost:8080拼接就变成了 http://localhost:8080/javaweb1.

 <form method="post" action="${pageContext.request.contextPath}/logincheck.jsp> //${pageContext.request.contextPath}是EL表达式 会自动获取当前所在工程名 即/javaweb1

转发、包含以及servlet映射地址:

/ 表示 http://localhost:8080/web项目工程名,不需要写工程名了。

两数之和:

要求:通过servlet实现两数之和,最后转回到求和页面。

a1.jsp:

<%@ page pageEncoding="UTF-8" %>
<html>
<body>
<form method="post" action="add">
输入第一个整数:<input type="text" name="n1" value="${param.n1}"><br>
输入第二个整数:<input type="text" name="n2" value="${param.n2}"><br>
<input type="submit" value="求和"/>
</form>
${result}
</body>
</html>

servlet:

package servlet;

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

@WebServlet("/add") //当前端页面提交到这个 /add的时候 servlet会执行下面
public class add extends HttpServlet {
	private static final long serialVersionUID = 1L;     
    public add() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath()); // Served at: /javaweb1(项目名)
	}
    //执行下面代码 因为时post请求
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int n1=Integer.parseInt(request.getParameter("n1"));//获取值
        int n2=Integer.parseInt(request.getParameter("n2")); //获取值
        String result=n1+"+"+n2+"="+(n1+n2); //拼接字符串
        request.setAttribute("result",result); //在请求范围内保存数据 名为result 值为 result
        request.getRequestDispatcher("/a1.jsp").forward(request,response); //请求转发 
	}

}

在这里插入图片描述

过滤器/监听器
简介:

​ 过滤器(Filter)和监听器(Listener)是在Java Web应用程序中用于处理请求和响应的重要组件。它们提供了一种在Web应用程序中对请求和响应进行拦截、处理和修改的机制,以实现一些共享逻辑、增强功能或执行特定任务的需求。

过滤器(Filter)

过滤器是一种用于在HTTP请求被发送到Servlet之前或响应返回给客户端之前拦截、处理请求和响应的组件。它可以对请求进行预处理、对响应进行后处理,也可以修改请求和响应的内容。过滤器通常用于实现以下功能:

  1. 认证和授权:验证用户身份,检查访问权限。
  2. 日志记录和性能监控:记录请求和响应的信息,测量性能指标。
  3. 数据压缩和加密:对请求和响应进行压缩或加密。
  4. 请求和响应的修改:修改请求参数、响应内容或头部信息。
  5. 缓存和资源优化:缓存响应内容或优化资源加载。

过滤器创建过程:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们主要时修改doFilter 来起到拦截作用。

我们先看一下doFilter 函数中的参数

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // ServletRequest 此对象给过滤器提供了对请求信息的完全访问,就是请求对象。
        //ServletResponse  响应对象
        //FilterChain 用于将请求传递给下一个过滤器或目标 Servlet

		chain.doFilter(request, response);
	}

拦截用户:

​ 一般就是起到拦截用户的作用,比如说用户没有某个权限,会将其拦截下来,会将网页转到登录页面或者其他页面。

package filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
@WebFilter("/admin/*") //拦截的URL模式为"/admin/*"
public class Filter1 implements Filter {
    public void destroy() {
        //过滤器的销毁方法,在过滤器被销毁时调用。
    }
 // 核心方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain)
            throws IOException, ServletException {
        HttpServletRequest requ = (HttpServletRequest) request;//转化为http请求对象
        HttpServletResponse resp = (HttpServletResponse) response;//转化为http响应对象
        HttpSession session = requ.getSession(true);
       //表示获取与当前请求相关联的会话对象(HttpSession),如果会话不存在,则创建一个新的会话。
        if (session.getAttribute("u_name") == null) { //检查会话中是否存在名为"u_name"的属性
            //响应转发 
            //requ.getContextPath() 当前Web应用程序的上下文路径(/web工程名)
            resp.sendRedirect(requ.getContextPath()+"/login.jsp");
        } else {
            //用于将请求和响应对象传递给过滤器链中的下一个组件,继续处理请求。
            filterchain.doFilter(request, response);
        }
    }
 
    public void init(FilterConfig arg0) throws ServletException {
    }
}
监听器(Listener)

监听器是一种用于监听Web应用程序中的事件和状态变化的组件。它可以接收和响应特定事件的发生,以执行相应的逻辑。监听器通常用于以下场景:

  1. 生命周期事件:监听Servlet、会话或上下文的创建、销毁和属性变化等生命周期事件。
  2. 请求和会话事件:监听请求的开始和结束,会话的创建和销毁,属性的变化等事件。
  3. 上下文初始化和销毁:监听Web应用程序的初始化和销毁事件。
  4. 属性变化:监听属性的增加、修改和删除等变化。

创建过程:

在这里插入图片描述

在这里插入图片描述

勾选要监听的事件。

​ 在Java Servlet规范中,可以监听多种类型的对象。根据不同的对象类型,可以将监听对象分为以下几类:

  1. ServletContext(Web应用程序上下文)(应用对象)相关的监听对象:

    • ServletContextListener:用于监听ServletContext的创建和销毁事件。
    • ServletContextAttributeListener:用于监听ServletContext属性的添加、删除和替换事件。
  2. HttpSession(会话)相关的监听对象:

    • HttpSessionListener:用于监听HttpSession的创建和销毁事件。
    • HttpSessionAttributeListener:用于监听HttpSession属性的添加、删除和替换事件。
    • HttpSessionActivationListener:用于监听HttpSession的活化和钝化事件。
    • HttpSessionBindingListener:用于监听HttpSession属性绑定和解绑事件。
    • HttpSessionIdListener:用于监听HttpSession ID的改变事件。
  3. ServletRequest(请求)相关的监听对象:

    • ServletRequestListener:用于监听ServletRequest的创建和销毁事件。
    • ServletRequestAttributeListener:用于监听ServletRequest属性的添加、删除和替换事件。
  4. 异步请求相关的监听对象:

    • AsyncListener:用于监听异步请求的完成、超时、错误和启动事件。

      框架:

package listen;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class Listener1 implements ServletRequestListener {
    public Listener1() {
    }
    public void requestDestroyed(ServletRequestEvent arg0) {   
    }
    public void requestInitialized(ServletRequestEvent arg0) {      
    }
    public void onStartAsync(AsyncEvent arg0) throws java.io.IOException {   
    }
    public void valueBound(HttpSessionBindingEvent arg0)  { 
    }
 
}
在线人数:

如何监听某个网站的在线人数,可以以是否创建session为标准,新的session则+1。

接下里我们看看实现:

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class OnlineUsersListener implements HttpSessionListener {
    private static int onlineUsersCount = 0;//创建静态变量 

    //新的会话 则+1
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        onlineUsersCount++; 
        System.out.println("New session created. Online users: " + onlineUsersCount);
    }
//会话销毁 则-1
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
   		  onlineUsersCount--;
        System.out.println("Session destroyed. Online users: " + onlineUsersCount);
    }
    //设置对外接口 用于返回人数
    public static int getOnlineCount(){
                return onlineUsersCount;
        }
}
%@ page pageEncoding="UTF-8" import="listener.OnlineUsersListener" %> //使用监听器接口 一定要导入相应的包 
<html>
<body>
当前在线人数:<%=OnlineListener.getOnlineCount() %>
</body>
</html>
一人登录:

​ 思路:用监听器监听应用对象,创建一个记录每个会话信息,判断是否存在,如果存在在更新用户信息,不然将该用户信息加入应用。

监听器:

package listener;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession; 
// 实现 ServletContextListener  应用对象上下文接口 
@WebListener
public class ApplicationListener implements ServletContextListener {
    public ApplicationListener() {    
    }
    /**
      ServletContextEvent是ServletContextListener的监听事件 
       Web 应用程序上下文销毁时被调用。在该方法中,从 ServletContext 中获取存储的 userList,并清空其中的数据,释放资源。
     */
    public void contextDestroyed(ServletContextEvent event) {
        Map<String, HttpSession> userList = (Map<String, HttpSession>) event.getServletContext().getAttribute("userList"); // 获取
        if (userList != null) { //清空
            userList.clear();
        }
    }
    /**
 Web 应用程序上下文初始化时被调用。在该方法中,创建一个 LinkedHashMap 类型的 userList,用于存储用户会话对象。
 ServletContextEvent 是监听事件 
     */
    public void contextInitialized(ServletContextEvent event) {
        //HttpSession session=request.getSession();   HttpSession 是一个session类型
        Map<String, HttpSession> userList = new LinkedHashMap<String, HttpSession>();
       // 将 userList 存储在 ServletContext(相当于servlet类型的应用对象) 
        event.getServletContext().setAttribute("userList", userList);
    }
 
}

后台处理:

<%@ page pageEncoding="UTF-8" import="java.util.Map"%>
<html>
<body>
    <%
        String userid = request.getParameter("userid");
        String userpwd= request.getParameter("userpwd");
        if("zhangsan".equals(userid)&&"123".equals(userpwd)){
            session.setAttribute("userid", userid);// 保存会话信息 
            /*
   此时已经有userList对象了,因为我的服务器已经打开了,应用对象会创建
            */
            Map<String,HttpSession> userList=(Map<String,HttpSession>)application.getAttribute("userList");
//注意一下:这里为什么要进行 强制类型转化即(Map<String,HttpSession>) 因为application是从ServletContext获取的,可以理解为一个servlet类型的应用对象
            HttpSession oldSession=userList.get(userid);// 根据userid获取旧的session对象
            if(oldSession!=null){ //如果之前有 
                try{oldSession.invalidate();}catch(Exception e){} 
                //oldSession.invalidate() 是使旧的应用对象失效 
            }
            //记录新的session 
            userList.put(userid,session);
            response.sendRedirect("main.jsp");// 转发 
        }
        else{
            //登录失败
            request.setAttribute("msg","用户名或密码错误");
            pageContext.forward("login.jsp");
        }
          
    %>
      
</body>
</html>

第七章 Ajax

简介:

​ 在JavaWeb中,Ajax(Asynchronous JavaScript and XML)是一种用于在Web应用程序中实现异步通信的技术。它允许客户端通过JavaScript向服务器发送请求,并在后台进行处理,而无需刷新整个页面。使用Ajax,可以实现动态更新页面内容、异步加载数据、实时验证表单等功能,提升用户体验和性能。

在使用Ajax时,通常会遵循以下步骤:

  1. 编写前端代码:使用JavaScript编写前端代码,在页面中定义事件处理程序,例如按钮点击或表单提交事件。在事件处理程序中,使用Ajax发送HTTP请求到服务器,并定义处理服务器响应的回调函数。
  2. 编写服务器端代码:使用Java编写一个Servlet来处理Ajax请求。在Servlet中,解析请求参数,并根据请求的内容执行相应的业务逻辑。可以查询数据库、调用其他Java类或服务,生成响应数据,并将其返回给客户端。
  3. 处理响应数据:在前端的Ajax回调函数中,处理服务器返回的响应数据。可以解析JSON数据、更新页面内容、执行动态操作等。

需要注意的是,Ajax请求是异步的,意味着它们不会阻塞页面加载或用户交互。这使得Ajax非常适合在后台与服务器进行通信,而无需中断用户操作。

步骤:
  1. 创建xhr对象:xhr =new XMLHttpRequest();
  2. 建立连接: open(type,url, asynch) 第三个参数一般不写 默认使true 异步连接
  3. 发送:xhr.send(content)
  4. 事件绑定:xhr.readyState=4 且 xhr.status=200 绑定一个函数

封装一下函数:

function callback(){
  if (xmlHttpRequest.readyState == 4){
    if (xmlHttpRequest.status == 200){
        事件响应代码
    }
  }
}
请求属性:
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
 //Content-Type 设置请求体类型 application/x-www-form-urlencoded  参数查询字符串的类型

readyState 相关属性的含义:

  1. UNSENT (0): 初始状态,XMLHttpRequest 对象已创建,但尚未调用 open() 方法。
  2. OPENED (1): open() 方法已经被调用,请求已准备好发送,但尚未调用 send() 方法。
  3. HEADERS_RECEIVED (2): send() 方法已调用,并且头部和状态已经可用。可以通过 getResponseHeader() 获取响应头信息,可以通过 getAllResponseHeaders() 获取所有响应头信息。
  4. LOADING (3): 响应数据正在接收中。部分响应数据已经可用,但 responseText 属性可能还未完全填充。
  5. DONE (4): 响应已经完全接收,且数据可用。此时可以使用 responseTextresponseXML 属性来获取完整的响应数据。

status属性 状态码相关含义:

HTTP 状态码是服务器响应请求时返回的一个三位数的数字代码,用于指示请求的处理结果。常见的 HTTP 状态码包括:

  • 200:请求成功。表示服务器已成功处理请求并返回所需的数据。
  • 404:未找到。表示请求的资源在服务器上不存在。
  • 500:服务器内部错误。表示服务器在处理请求时遇到了错误。

responseTextresponseXML 是 XMLHttpRequest 对象的两个属性,用于获取服务器响应的数据。

  • responseText: responseText 属性返回服务器响应的文本数据,以字符串的形式表示。它可以用于获取服务器返回的纯文本数据,如 JSON、HTML 等。你可以使用 responseText 属性来处理和操作这些文本数据。
  • responseXML: responseXML 属性返回服务器响应的 XML 数据,以 Document 对象的形式表示。它将服务器返回的 XML 数据解析为一个完整的 Document 对象,使你能够使用 DOM 方法和属性来操作和遍历 XML 数据。
response.setContentType("text/xml;charset=UTF-8");

为了后续不用花时间写一样的代码,我们把Ajax封装成以下js文件,以便于直接调用。

var httpRequest=null;
function createXHR(){          
         if(window.XMLHttpRequest){ //Mozilla,Safari,Opera,IE7等
                    httpRequest = new XMLHttpRequest();
         }else if(window.ActiveXObject){
                    try{httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); //IE较新版本
                    }catch(e){
                 try {httpRequest = new ActiveXObject("Microsoft.XMLHTTP");//IE较老版本
                    }catch(e){httpRequest = null;}
                   }                 
         }       
         if(!httpRequest){ 
                   alert("fail to create httpRequest");             
         }
}
function sendRequest(url,params,method,handler){   
         createXHR();       //创建XHR对象 
         if(!httpRequest) return false;  
         httpRequest.onreadystatechange = handler;    // 事件绑定  
if(method == "GET"){        
    		// 参数:类型 url地址 是否异步
    	//注意get请求的参数 是作为url路径的一部分
           httpRequest.open(method,url+ '?' + params,true);   
           httpRequest.send(null);
         }
if(method == "POST"){
    //参数:类型 url地址 
         httpRequest.open(method,url,true);
                   httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
                   httpRequest.send(params); //发送参数
}     
}

如果post请求没有参数则这样写:sendRequest(“query”,null,‘POST’,show);

JSON:

​ JSON(JavaScript Object Notation)是一种常用的数据交换格式,它以文本的形式表示结构化数据。在 JavaScript 中,可以使用内置的 JSON 对象来解析和生成 JSON 数据。

  1. 将对象转换为 JSON 字符串:使用 JSON.stringify() 方法可以将 JavaScript 对象转换为 JSON 字符串。

    var obj = { name: "John", age: 30 };
    var jsonString = JSON.stringify(obj);
    console.log(jsonString);
    // 输出:{"name":"John","age":30}
    
  2. 将 JSON 字符串转换为对象:使用 JSON.parse() 方法可以将 JSON 字符串解析为 JavaScript 对象。

    var jsonString = '{"name":"John","age":30}';
    var obj = JSON.parse(jsonString);
    console.log(obj.name);
    console.log(obj.age);
    // 输出:John
    // 输出:30
    

    在这里插入图片描述

  3. 处理复杂的 JSON 结构:对于包含嵌套对象或数组的复杂 JSON 结构,可以使用适当的方法进行遍历和访问。

    var jsonString = '{"name":"John","age":30,"address":{"city":"New York","country":"USA"},"hobbies":["reading","traveling"]}';
    var obj = JSON.parse(jsonString);
    console.log(obj.name);
    console.log(obj.address.city);
    console.log(obj.hobbies[0]);
    // 输出:John
    // 输出:New York
    // 输出:reading
    

​ 请注意,JSON 必须具有有效的语法。属性名称和字符串值必须使用双引号括起来。使用 JSON.stringify()JSON.parse() 方法时,请确保数据格式正确以避免出现错误。

Java对象转json字符串:

​ 很多时候,在Ajax中需要传递一个java对象,但是Ajax只能传递字符串,所以需要使用第三方库,例如JSon-lib,这个大家自行去网上下载即可。

  • JSONObject.fromObject();//java对象=>json字符串
  • JSONArray.fromObject(); //java对象数组=>json字符串
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class JsonlibTest {
public static void main(String[] args){
     Student student1=new Student("20181234","张三","男");
     System.out.print("将student1对象转换成json字符串:");
     JSONObject jso1=JSONObject.fromObject(student1);
     System.out.println(jso1.toString());          
     System.out.println();
     System.out.print("将studentList1对象转换成json字符串:");
     Student student2=new Student("20185678","李四","女");
     List<Student> studentList1=new ArrayList<Student>();
     studentList1.add(student1);studentList1.add(student2);
     JSONArray jsa1=JSONArray.fromObject(studentList1);   
     System.out.println(jsa1.toString()); 
     System.out.println();
     System.out.print("将Map转换为json字符串:");
     Map<String,String> map1=new HashMap<String,String>();
     map1.put("sno", "20181111");
     map1.put("sname","王五");
     map1.put("sex","男");
     JSONObject jso2=JSONObject.fromObject(map1);  
     System.out.println(jso2.toString());          
     System.out.println();
     System.out.print("将json字符串转换成student3对象:");
     String jsonStr1="{'sex':'男','sname':'张三','sno':'20181234'}";
     JSONObject jso3=JSONObject.fromObject(jsonStr1);
     Student student3=(Student)JSONObject.toBean(jso3,Student.class);
     System.out.println(student3); 
     System.out.println();
     System.out.print("将json字符串转换成studentList2对象:");
     String jsonStr2="[{'sex':'男','sname':'张三','sno':'20181234'},{'sex':'女','sname':'李四','sno':'20185678'}]";
     JSONArray jsa2=JSONArray.fromObject(jsonStr2);
     List<Student> studentList2=(List<Student>)JSONArray.toCollection(jsa2,Student.class);
     for(Student student:studentList2){
               System.out.print(student+";");                           
     }       
}
}import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class JsonlibTest {
public static void main(String[] args){
     Student student1=new Student("20181234","张三","男"); //java对象
     System.out.print("将student1对象转换成json字符串:");
     JSONObject jso1=JSONObject.fromObject(student1);
     System.out.println(jso1.toString());          
     System.out.println();
     System.out.print("将studentList1对象转换成json字符串:");
     Student student2=new Student("20185678","李四","女");
     List<Student> studentList1=new ArrayList<Student>();
     studentList1.add(student1);studentList1.add(student2);
     JSONArray jsa1=JSONArray.fromObject(studentList1);   
     System.out.println(jsa1.toString()); 
     System.out.println();    
}
}

在这里插入图片描述

JQuery:
load()

​ jQuery 中的 load() 方法用于从服务器加载数据,并将加载的内容放置到指定的 HTML 元素中。它是一个简单而强大的方法,可以实现动态加载内容,无需手动编写 AJAX 请求和处理逻辑

$(selector).load(url [, data] [, completeCallback])

  • selector:要将加载的内容放置到的目标元素选择器。
  • url:加载数据的 URL 地址。
  • data(可选):要发送到服务器的数据。可以是字符串、对象或函数。
  • completeCallback(可选):加载完成后执行的回调函数。

load.jsp:

<%@ page pageEncoding="UTF-8"%>
<html>
  <head>
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
   function jiazai(){
     $("#div1").load("load","p=jsp程序设计");  //后台请求的数据放在div中
   }
</script> 
  </head>  
  <body>
    <input type="button" value="加载数据" οnclick="jiazai()">
    <div id="div1"></div>
  </body>
</html>

servlet:

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/load")
public class load extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public load() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 response.setContentType("text/html;charset=UTF-8");
	        PrintWriter out = response.getWriter();
	        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
	        out.println("<HTML>");
	        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
	        out.println("  <BODY>");
	        out.print("    This is ");
	        out.print(this.getClass());
	        out.println(", using the GET method" + request.getParameter("p"));
	        out.println("  </BODY>");
	        out.println("</HTML>");
	        out.flush();//强制将缓冲区中的内容立即发送到客户端 但是输出流仍然保持打开状态。
	        out.close();//关闭输出流,并且会自动刷新缓冲区。 无法在进行输出
	}
		protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("我走的是doPost(),传递过来的参数为:" + request.getParameter("p"));
        out.flush();
        out.close();
	}

}

在这里插入图片描述
很明显,后台servlet走的是doGet()方法,为什么呢,因为提交数据是这样写的 $("#div1").load("load","p=jsp程序设计"); ,第二个参数是 参数查询字符串的类型,而不是键值对的形式,那么我们如果改成 $("#div1").load("load",{"p":"jsp程序设计"}); ,应该会执行servlet里面的doPost方法吧,我们看一下结果。

在这里插入图片描述

get():

$.get() 是 jQuery 中的一个 AJAX 方法,用于发送 HTTP GET 请求并从服务器获取数据。它提供了一种简单的方式来执行异步的GET请求,无需刷新整个页面。

$.get() 方法的语法如下:

$.get(url [, data] [, successCallback] [, dataType])
  • url:要发送 GET 请求的 URL 地址。
  • data(可选):要发送到服务器的数据。可以是字符串、对象或函数。
  • successCallback(可选):请求成功时执行的回调函数。
  • dataType(可选):预期从服务器返回的数据的类型,例如 "text""json""xml" 等。
<%@ page pageEncoding="UTF-8"%>
<html>
  <head>
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
   function getF(){
   //执行servlet的get方法
     $.get("get",{"p":"abc"},function(data,status){// 回调函数
      $("#div1").html("数据为:"+data+",状态为"+status);
         //.html() 是调用了 jQuery 的 html() 方法,它用于设置所选元素的 HTML 内容
     });  
   }
</script> 
  </head>  
  <body>
    <input type="button" value="get方式请求数据" οnclick="getF()">
    <div id="div1"></div>
  </body>
</html>

servlet:

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/get")
public class get extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public get() {
        super();     
    }
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		response.setContentType("text/html;charset=UTF-8");//设置响应内容类型
        PrintWriter out = response.getWriter();//获取 PrintWriter 对象,用于将结果写入响应
        out.print("发送的参数为:"+request.getParameter("p"));
        out.flush();//刷新输出流,将缓冲区中的内容立即发送到客户端
        out.close();//关闭输出流
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

在这里插入图片描述

也可以使用查询字符串的方式进行参数传递,因为已经显示指定类型为get了,如下。

   function getF(){
   //执行servlet的get方法
     $.get("get","p=abc",function(data,status){
      $("#div1").html("数据为:"+data+",状态为"+status);
     });  
   }
post():
$.post("url", { param1: "value1", param2: "value2" }, function(data, status) {
  // 处理返回的数据
});
  • "url":要发送 POST 请求的 URL 地址。
  • { param1: "value1", param2: "value2" }:要发送到服务器的数据,可以是一个对象或字符串。
  • function(data, status):请求成功后执行的回调函数,其中 data 是从服务器返回的数据,status 是请求的状态。
<%@ page pageEncoding="UTF-8"%>
<html>
  <head>
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
   function postF(){
   //执行servlet的post方法
//      $.post("post",{"p":"我真是帅极了"},function(data,status){
//       $("#div1").html("数据为:"+data+",状态为"+status);
//      });  
        $.post("post","p=我真是帅极了",function(data,status){
      $("#div1").html("数据为:"+data+",状态为"+status);
     });  
   }
</script> 
  </head>  
  <body>
    <input type="button" value="post方式请求数据" οnclick="postF()">
    <div id="div1"></div>
  </body>
</html>
package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/post")
public class post extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public post() {
        super();
        // TODO Auto-generated constructor stub
    }


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print("传递过来的参数值为:"+request.getParameter("p"));
        out.flush();
        out.close();
	}
}

在这里插入图片描述

ajax():

通过 jQuery 的 $.ajax() 方法,可以使用简洁的语法来发送 Ajax 请求。

$.ajax({
  url: "your-url",
  type: "GET", // 或 "POST"、"PUT"、"DELETE" 等
  data: { param1: "value1", param2: "value2" },
  dataType: "json", // 服务器返回的数据类型 可不写
  success: function(data, status, xhr) {
    // 请求成功时的处理逻辑
  },
  error: function(xhr, status, error) {
    // 请求失败时的处理逻辑
  }
});
  • url:请求的 URL 地址。
  • type:请求的类型(GET、POST 等)。
  • data:要发送到服务器的数据,可以是一个对象或字符串。
  • dataType:预期的服务器响应数据类型,例如 "json""xml""html" 等。这有助于 jQuery 在接收响应时自动解析数据。
  • success:请求成功时的回调函数,其中 data 是从服务器返回的数据,status 是请求的状态,xhr 是 XMLHttpRequest 对象。
  • error:请求失败时的回调函数,其中 xhr 是 XMLHttpRequest 对象,status 是错误的状态码,error 是错误的描述。
<%@ page pageEncoding="UTF-8"%>
<html>
  <head>
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
    function ajaxF(){
     //执行servlet的post方法
     $.ajax({
     url:"post",
     type:"post",
     data:{"p":"我了个豆"},
     success:function(data,status){
       $("#div1").html("数据为:"+data+",状态为"+status);
     }
     });  
   }
</script> 
  </head>  
  <body>
    <input type="button" value="ajax方式请求数据" οnclick="ajaxF()">
    <div id="div1"></div>
  </body>
</html>

在这里插入图片描述

表单序列化:

​ 我们发现之前Ajax实现都是静态,一般业务都是根据表单输入的值,提交到后台进行处理,现在介绍两个方法,使用 jQuery 的 serialize()serializeArray() 方法可以方便地生成表单提交参数字符串。

  1. 使用 serialize() 方法生成表单提交参数字符串:
var formData = $('#myForm').serialize();
console.log(formData);

​ 假设你有一个表单的 id 为 “myForm”。通过调用 serialize() 方法,可以将表单中的所有字段序列化为一个字符串。该字符串的格式为 “name1=value1&name2=value2”,其中 “name1” 和 “name2” 是表单字段的名称,“value1” 和 “value2” 是对应字段的值,获得的值是查询字符串拼接.

​ 2.使用 serializeArray() 方法生成表单提交参数数组

var formDataArray = $('#myForm').serializeArray();
console.log(formDataArray);

结果类型:

[
  { name: "username", value: "John Doe" },
  { name: "email", value: "johndoe@example.com" },
  { name: "subscription", value: "1" },
  { name: "subscription", value: "2" },
  { name: "gender", value: "male" },
  { name: "country", value: "uk" }
]
<%@ page pageEncoding="UTF-8"%>
<html>
  <head>
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
  function f1(){
   $("#result1").text($("#form1").serialize());
  }
  function f2(){
  $("#result2").text(JSON.stringify($("#form1").serializeArray()));
      //JSON.stringify()是转化为json字符串 不能直接串列表
  }
</script> 
  </head>  
  <body>
  <form id="form1">
    学号: <input type="text" name="sno"  /><br>
    姓名: <input type="text" name="sname"  /><br>
    性别: 男<input type="radio" name="sex" value="男" checked />
    女<input type="radio" name="sex" value="女" />
    <br>
 </form>
 <input type="button" value="serialize序列化表单值" οnclick="f1()">
 <input type="button" value="serializeArray序列化表单值" οnclick="f2()">
 <div id="result1"></div>
 <div id="result2"></div>
 </body>
</html>

在这里插入图片描述

案例:
两数之和:
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/ajax.js"></script>
<script type="text/javascript">
      function add(){        
        var url="sum";
        var num1=document.getElementById("num1").value;
        var num2=document.getElementById("num2").value;
        var params="num1="+num1+"&num2="+num2;
          //参数一:后台servlet地址 参数二:参数
          //参数三:类型  参数四:处理完的数据执行的回调函数
        sendRequest(url,params,'POST',showresult);  //调用Ajax 
          
    }
    function showresult(){ //这个相当于回调函数 
        if (httpRequest.readyState == 4) { 
            if (httpRequest.status == 200) {
                var info=httpRequest.responseText;   //获取servlet处理后的数据       
                document.getElementById("result").innerHTML=info;
            }
        }
}
</script>
</head>
 <body>  
   num1:<input type="text" name="num1" id="num1" /><br/>
   num2:<input type="text" name="num2" id="num2" /><br/>
   <input type="button" value="求和 " onclick="add()"/> //点击求和执行AJax
   <div id="result"></div>
 </body>
</html>

servlet:

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/sum")
public class sumservlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       

    public sumservlet() {
        super();
    
    }


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {	
        //用于设置响应的内容类型和字符编码。
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		  int num1=Integer.parseInt(request.getParameter("num1"));
	        int num2=Integer.parseInt(request.getParameter("num2"));
	        String result="和为:"+(num1+num2);
	        out.print(result);
		
//		doGet(request, response);
	}

}

在这里插入图片描述

页面没有进行刷新,因为通过Ajax请求数据进行数据填充。

省市级联菜单
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script type="text/javascript" src="js/ajax.js"></script>
<script type="text/javascript">
   function refresh(){
      var p=document.getElementById("prov").value;//获取省级所选的值
      var city=document.getElementById("city");//定位到城市标签
      if(p==""){ 
         city.options.length=0;//一开始城市大小为0
         city.options.add(new Option("--请选择城市--"))//添加一个
      }
      else{
        var url="list";//后台servlet地址 
        var params="proc="+p ;//查询字符串拼接 
        sendRequest(url,params,'POST',show);//发送AJax请求 
      }
   }
   function show(){
   var city=document.getElementById("city");
      if (httpRequest.readyState == 4) { 
         if (httpRequest.status == 200) {
            var citylist=httpRequest.responseText.split(",");//因为后台处理完是一个字符串 "a,c,b"类型
            var citynum=citylist.length;
            city.options.length=0;//清空城市标签
            for(i=0;i<citynum;i++)
               city.options.add(new Option(citylist[i]))//根据获取的城市名创建标签
            }
       }
   }
   
</script>
</head>
   <body>
       
       <select name="prov" id="prov" onchange="refresh();">
 <!--
οnchange="refresh();":指定了当选择框的选项发生改变时要执行的 JavaScript 函数 "refresh()"
-->
         <option value="">--请选择省份--</option>
         <option value="山东">山东</option>
         <option value="江苏">江苏</option>
         <option value="广东">广东</option>
      </select>
      <select name="city" id="city">
         <option>--请选择城市--</option>
      </select>
   
   </body>
</html>
package servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/list")
public class list extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public list() {
        super();
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at:").append(request.getContextPath());
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		Map<String, String> pm = new HashMap<String, String>();
        pm.put("山东", "济南,青岛,泰安,潍坊,烟台,聊城,枣庄,菏泽,莱芜,临沂");
        pm.put("江苏", "南京,苏州,无锡,徐州,南通,连云港,镇江,常州,淮安,扬州");
        pm.put("广东", "广州,深圳,珠海,汕头,佛山,东莞,湛江,江门,中山,惠州");
        response.setContentType("text/html;charset=UTF-8");//语句用于设置响应的内容类型和字符编码。
        request.setCharacterEncoding("UTF-8");//告知对获取来的数据以utf-8编码
        PrintWriter out = response.getWriter();//创建一个用于向客户端发送文本数据的 PrintWriter 对象。
        String s1 = request.getParameter("proc");//获取前端选择的省份
        out.print(pm.get(s1));//将对应城市返回回去
    }
//		doGet(request, response);
	

}

在这里插入图片描述

在这里插入图片描述

XML型字符串:
package servlet;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/searchsuggest")
public class SearchSuggest extends HttpServlet {   
     
public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
   response.setContentType("text/xml;charset=UTF-8");
   PrintWriter out = response.getWriter();
   HashMap map = new HashMap();
   map.put("a","<words><word>a</word><word>ab</word><word>abc</word><word>abcd</word><word>abcde</word></words>");
   map.put("ab","<words><word>ab</word><word>abc</word><word>abcd</word><word>abcde</word></words>");
   map.put("abc","<words><word>abc</word><word>abcd</word><word>abcde</word></words>");
   map.put("abcd","<words><word>abcd</word><word>abcde</word></words>");
   map.put("abcde","<words><word>abcde</word></words>");
   String inputWord= request.getParameter("inputWord");//前端页面输入的值 
   if(!map.containsKey(inputWord)){
        out.println("<words></words>"); //在map中匹配对应的键
   }else{
       out.println(map.get(inputWord).toString());
   }
}
 
}

​ 很有意思的是,这个返回的不是字符串,而是XML类型的字符串,所以前端不能使用responseText 而要使用 responseXML,可能大家不太了解XML是啥,如果想了解更多,可以看一下我之前那篇文章,讲的比较 透彻:深度剖析Ajax实现方式(原生框架、JQuery、Axios,Fetch)-CSDN博客,XML是一个类型HTML的标签类型,如下:

<words>
  <word>abcde</word>
</words>

现在我给大家说一下怎么解析,获取数据。

在这里插入图片描述

var responseXml="<words><word>abcde</word></words>"
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(responseXml, "text/xml");

// 获取 <word> 元素
var wordElement = xmlDoc.querySelector("word");

// 提取搜索建议值
var suggestion = wordElement.textContent;

console.log(suggestion); // 输出 "abcde"

在这里插入图片描述

responseXml="<words><word>a</word><word>ab</word><word>abc</word><word>abcd</word><word>abcde</word></words>"
// 假设 responseXml 是从服务器响应中获取的 XML 字符串
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(responseXml, "text/xml");

// 获取所有 <word> 元素
var wordElements = xmlDoc.querySelectorAll("word");

// 遍历所有 <word> 元素,提取搜索建议值
var suggestions = [];
for (var i = 0; i < wordElements.length; i++) {
  var suggestion = wordElements[i].textContent;
  suggestions.push(suggestion);
}

console.log(suggestions); // 输出 ["ab", "abc", "abcd", "abcde"]

当然也可以使用node.js来执行:

var xml2js = require('xml2js');

//var responseXml = "<words><word>abcde</word></words>";
var responseXml = "<words><word>a</word><word>ab</word><word>abc</word><word>abcd</word><word>abcde</word></words>";

var parser = new xml2js.Parser();
parser.parseString(responseXml, function (err, result) {
  if (err) {
    console.error(err);
    return;
  }

  // 提取搜索建议值  //返回的是一个列表
  var one= result.words.word[0];
  var list = result.words.word;
console.log(one);
console.log(list);
});

在这里插入图片描述

对象传递:
package servlet;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import vo.Student;
@WebServlet("/query")
public class Query extends HttpServlet {
    public Query() {
        super();
    }
 
    public void destroy() {
        super.destroy();
    }
     
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8"); //设置相应内容类型
        PrintWriter out = response.getWriter();//PrintWriter 是用于向客户端发送文本数据的输出流。
        Student student1=new Student("20181234","张三","男");        
        Student student2=new Student("20185678","李四","女");
        List<Student> studentList1=new ArrayList<Student>();
        studentList1.add(student1);studentList1.add(student2);
        JSONArray jsa=JSONArray.fromObject(studentList1);  //转化为json字符串类型
        out.print(jsa.toString());
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 
            this.doGet(request,response);
    }
    public void init() throws ServletException {

    }
 
}
function show(){        
   if (httpRequest.readyState == 4) { 
      if (httpRequest.status == 200) {
           var tBody=document.getElementById("tBody");
           tBody.innerHTML="";
            var studentList=JSON.parse(httpRequest.responseText); //转化为json对象   
            for(var st in studentList){               
               var newTr=tBody.insertRow();
               var newTd1=newTr.insertCell();newTd1.innerHTML=st.sno;
               var newTd2=newTr.insertCell();newTd2.innerHTML=st.sname;
               var newTd3=newTr.insertCell();newTd3.innerHTML=st.sex;
             }
            }
       }
表单提交:
<%@ page pageEncoding="UTF-8"%>
<html>
  <head>
  <script src="js/jquery-1.11.1.js"></script>  
  <script>
  function add(){
   $.post("add",$("#form1").serialize(),function(data){
      $("#result").text(data); //后台处理过的数据放在result里面 
    }
    );
  }
   
</script> 
  </head>  
  <body>
  <form id="form1">
    学号: <input type="text" name="sno"  /><br>
    姓名: <input type="text" name="sname"  /><br>
    性别: 男<input type="radio" name="sex" value="男" checked />
    女<input type="radio" name="sex" value="女" />
    <br>
 </form>
 <input type="button" value="添加记录" οnclick="add()"> 
 <div id="result"></div> 
 </body>
</html>
package servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/add")
public class add extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public add() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String sno=request.getParameter("sno");
        String sname=request.getParameter("sname");
        String sex=request.getParameter("sex");
        out.print("要添加的记录为:学号:"+sno+",姓名:"+sname+",性别:"+sex);
        out.flush();
        out.close();
	}

}

在这里插入图片描述

细节问题:
    </script>
function jump1(url){
        $("#right").load(url);
    }
    </script>

再看接下里的代码:

<div id="left">
     <ul>
      <li><a href="javascript:jump1('1.jsp')">班级管理</a></li>   
       <li><a href="javascript:jump1('2.jsp')">学生管理</a></li>     
     </ul>
    </div> 

​ 很明显是想通过load加载数据,a href="javascript:jump1('1.jsp')"为什么要加上 javascript:前缀呢,因为一般的网页js都写在script标签里面,或者单独一个js文件,你想在html标签元素上使用javascript中的函数,使用javascript:前缀并调用特定函数的方式,可以直接在链接中执行JavaScript代码,实现链接点击时的特定操作,但是如果你 a href="jump1('1.jsp'),当直接写入 JavaScript 代码时,可能会受到浏览器的安全策略限制。有些浏览器可能会阻止执行这种内联的 JavaScript 代码,因为这可能会引起安全问题。

温馨提示:

PrintWriter 对象的方法 print() 用于输出文本数据,而不会在输出的文本后自动添加换行符。如果需要在输出的文本后添加换行符,可以使用 println() 方法。

第八章 开发模式

简介:

jsp+javabean模式:

​ 在JSP和JavaBean模式中,JSP页面通常用于呈现动态内容和与用户进行交互,而JavaBean类用于处理业务逻辑和数据操作。JSP页面可以通过使用JavaBean类的getter方法获取数据并进行展示,也可以通过表单提交数据并使用JavaBean类的setter方法进行处理。这种模式将业务逻辑和数据操作与页面展示分离,提高了代码的可维护性和可重用性。

Jsp+Servlet+Javabean模式:

​ 在JSP+Servlet+JavaBean模式中,JSP页面负责展示和用户交互,Servlet负责接收和处理请求,并调用JavaBean进行业务逻辑的处理和数据的操作。JavaBean封装了数据和具体的业务逻辑,Servlet和JSP页面通过JavaBean进行数据交互和通信。这一种模式最最类似MVC开发模式,M有Model由JavaBean实现,V代表视图(View)由Jsp来实现,C(控制器)由Servlet来实现,在业务逻辑上MVC开发模式是相对较为高效的。

下面画一个流程图展示给大家:

在这里插入图片描述

实战案例:
一:

jsp+javabean实现学生信息管理:

在这里插入图片描述

没有用到servlet,所有的业务逻辑都写在jsp中,如下:

<style>
  body{
      text-align:center;
  }
  th,td{
  border:2px solid gray;
  text-align:center;
  padding:3px 10px;
  }
  table{
  border-collapse:collapse; 
  margin:10px auto;
  }

  #form1{
  padding:20px;
  display:none;
  position:fixed;
  top:50%;
  left:50%;
  width:300px;
  height:200px;
  z-index:1000;
  margin-left:-200px;
  margin-top:-200px;
   background: #88f;
  }
 </style>
<%@ page  pageEncoding="UTF-8" import="java.util.*,entity.*,dao.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!--jstl库  -->
<html>
<head>
<!--把上面的css文件加进来  -->
</head>

<body>
<%
StudentDao studentDao=new StudentDao();//创建一个学生操控类
request.setCharacterEncoding("UTF-8");//设置请求类型的参数 因为涉及到表单 
String op=request.getParameter("op");//获取操作类型 
System.out.println(op);//输出一下操作类型(为了检验)
if(op!=null){
if("add".equals(op)){//添加
	Student student=new Student(request.getParameter("sno"),request.getParameter("sname"),request.getParameter("sex"));
	try{studentDao.add(student);//加入新对象

	}
	catch(Exception e){
		out.print("<script>alert('学号不唯一')</script>");
	}
}
else if("update".equals(op)){// 更新操作 
Student student=new Student();
student.setId(Integer.parseInt(request.getParameter("id")));
student.setSno(request.getParameter("sno"));
student.setSname(request.getParameter("sname"));
student.setSex(request.getParameter("sex"));
//调用学生dao类更新 
try{studentDao.update(student);}
catch(Exception e){
	out.print("<script>alert('更新失败,学号不唯一')</script>");
}
}
else if("delete".equals(op)){//删除
studentDao.delete(Integer.parseInt(request.getParameter("id")));
response.sendRedirect("query.jsp");//重定向使页面更新
}
}

List<Student> studentList=studentDao.query();//从数据库获取所有对象
pageContext.setAttribute("studentList",studentList);//保存属性 
 %>
  <h3><a href="javascript:add()">添加记录</a></h3> //调用add函数
 <h2>学生信息</h2> 
   <table>
   <tr><th>学号</th><th>姓名</th><th>性别</th><th>修改</th><th>删除</th></tr>
      <!--使用EL表达式循环不断创建学生信息 -->
  <c:forEach items="${studentList}" var="student" varStatus="st">
  <tr>
   
   <td>${student.sno}</td>
   <td>${student.sname}</td>
   <td>${student.sex}</td>
     <td><a href="javascript:update(${student.id},'${student.sno}','${student.sname}','${student.sex}')">修改</a></td>
   <td><a href="query.jsp?op=delete&id=${student.id}" οnclick="return confirm('确实要删除吗?')">删除</a></td>    
          <!--注意${student.sname} 使EL表达式取出来的值,仅仅是值,不是字符串类型  -->
  </tr>
 </c:forEach> 
 </table>
 <form method="post" id="form1">
学号<input type="text" name="sno" id="sno"/><br><br>
 姓名<input type="text" name="sname" id="sname"/><br><br>
性别<input type="radio" name="sex" value="男" checked/>男<input type="radio" name="sex" value="女" />女<br><br>
 <input type="hidden" name="op" value="" id="op"/> 
 <input type="hidden" name="id" id="id"/>
 <input type="submit" value="" id="bt"/>
 <input type="reset" value="重置"/>
  <input type="button" value="关闭" οnclick="document.getElementById('form1').style.display='none';"/>
 </form>
 <br>
 <script>
 function add(){
	 document.getElementById("bt").value="添加";
	 document.getElementById("op").value="add";
	 document.getElementById("form1").style.display="block";
	 
 }
 function update(id,sno,sname,sex){
	 document.getElementById("bt").value="修改";
	 document.getElementById("op").value="update";
	 document.getElementById("id").value=id;
	 document.getElementById("sno").value=sno;
	 document.getElementById("sname").value=sname;
	 var sexs=document.getElementsByName("sex");
	 if(sex=='男'){
		 sexs[0].checked=true;sexs[1].checked=false;
	 }
	 else{
		 sexs[0].checked=false;sexs[1].checked=true;
	 }
	 document.getElementById("form1").style.display="block";
	 
 }
 </script>
</body>
</html>

在这里插入图片描述

​ 我们会发现,jsp+javabean 这种开发模式过于冗余,不符合高内聚低耦合,也不利于后期的开发和维护。

二:

jsp+servlet+javabean实现学生管理:

项目结构:

在这里插入图片描述

index.html

<%@ page  pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>  
    <meta charset="utf-8"/>  
    
    <title>Home</title>  
    <style>  
       html,body{
       height:90%;
       }
        #left{  
            width: 15%;  //左侧占15%
            height: 100%;  
            float: left;  //向左浮动
            border-right:1px solid gray;
        }  
        #right{  
            width: 80%;  
            height: 100%;  
            border:0;
        }  
    </style> 
 </head> 
<body>  
   
    <h2>学生信息管理</h2><hr>
    
    <div id="left">
     <ul><!--studentServlet 跳转到servlet  -->
         <!--target="right"表示链接将在名为"right"的窗口或框架中打开  -->
            <!-- 超链接相当于向servlet发送get请求,所以会走doGet  -->
      <li><a href="studentServlet" target="right">学生管理</a></li>   
        
     </ul>
    </div>  
     <!--iframe 相当于一个子网页,可以实现网页嵌套网页的作用-->
    <iframe id="right" name="right"  src=""></iframe>  
  
</body>  
</html>

我们接下来看一看后台servlet是怎么写的。

package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.StudentDao;
import entity.Student;
@WebServlet("/studentServlet")
public class StudentServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
      StudentDao studentDao=new StudentDao(); 
    public StudentServlet() {
        super();
    }
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");//设置请求来的参数类型 
			try {
				String op=request.getParameter("op");	//获取操作类型
				if(op!=null) {
					if("add".equals(op)){
						Student student=new Student(request.getParameter("sno"),request.getParameter("sname"),request.getParameter("sex"));
						studentDao.add(student);
					}
					else if("update".equals(op)) {
						Student student=new Student();
					student.setId(Integer.parseInt(request.getParameter("id")));
						student.setSno(request.getParameter("sno"));
						student.setSname(request.getParameter("sname"));
						student.setSex(request.getParameter("sex"));
						studentDao.update(student);
					}
					else if("delete".equals(op)) {
						studentDao.delete(Integer.parseInt(request.getParameter("id")));
					}
						
				}
				//一开始点击操作 没有传递操作类型 会直接到这里
				List<Student> studentList = studentDao.query();
				request.setAttribute("studentList",studentList);//请求范围内保存属性
				request.getRequestDispatcher("query.jsp").forward(request, response);//请求转发 
			} catch (Exception e) {
		
				response.setContentType("text/html;charset=UTF-8");//用于设置响应的内容类型为"text/html",并指定字符编码为UTF-8。这告诉浏览器响应的内容是HTML格式
				PrintWriter out=response.getWriter();//获取一个可以向客户端发送内容的输出流
				out.print(e.toString());//异常对象 e 转换为字符串,并通过输出流向客户端发送
			}
			
		}
		
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {	
		doGet(request, response);
	}

}

接下来我们看看他转发后的页面query.jsp:

<style>
  body{
      text-align:center;
  }
  th,td{
  border:2px solid gray;
  text-align:center;
  padding:3px 10px;
  }
  table{
  border-collapse:collapse; 
  margin:10px auto;
  }

  #form1{
  padding:20px;
  display:none;
  position:fixed;
  top:50%;
  left:80%;
  width:300px;
  height:200px;
  z-index:1000;
  margin-left:-200px;
  margin-top:-200px;
   background: #88f;
  }
 </style>
<%@ page  pageEncoding="UTF-8" import="java.util.*,entity.*,dao.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<!--将上面的CSS文件放入进来  -->
</head>
<body>
  <h3><a href="javascript:add()">添加记录</a></h3> 
 <h2>学生信息</h2> 
   <table>
   <tr><th>学号</th><th>姓名</th><th>性别</th><th>修改</th><th>删除</th></tr>
  <c:forEach items="${studentList}" var="student" varStatus="st">
      <!-- 获取之前存在请求范围内的数据 然后循环填充表格-->
  <tr>
   
   <td>${student.sno}</td>
   <td>${student.sname}</td>
   <td>${student.sex}</td>
     <td><a href="javascript:update(${student.id},'${student.sno}','${student.sname}','${student.sex}')">修改</a></td>
   <td><a href="studentServlet?op=delete&id=${student.id}" οnclick="return confirm('确实要删除吗?')">删除</a></td>    
  </tr>
 </c:forEach> 
 </table>
 <form method="post" id="form1" action="studentServlet">
学号<input type="text" name="sno" id="sno"/><br><br>
 姓名<input type="text" name="sname" id="sname"/><br><br>
性别<input type="radio" name="sex" value="男" checked/>男<input type="radio" name="sex" value="女" />女<br><br>
 <input type="hidden" name="op" value="" id="op"/>
 <input type="hidden" name="id" id="id"/>
 <input type="submit" value="" id="bt"/>
 <input type="reset" value="重置"/>
  <input type="button" value="关闭" οnclick="document.getElementById('form1').style.display='none';"/>
 </form>
 <br>
 <script>
 function add(){
	 document.getElementById("bt").value="添加";
	 document.getElementById("op").value="add";
	 document.getElementById("form1").style.display="block";//使提交表单可以显示出来
	 
 }
 function update(id,sno,sname,sex){
	 document.getElementById("bt").value="修改";
	 document.getElementById("op").value="update";
	 document.getElementById("id").value=id;
	 document.getElementById("sno").value=sno;
	 document.getElementById("sname").value=sname;
	 var sexs=document.getElementsByName("sex");
	 if(sex=='男'){
		 sexs[0].checked=true;sexs[1].checked=false;
	 }
	 else{
		 sexs[0].checked=false;sexs[1].checked=true;
	 }
	 document.getElementById("form1").style.display="block";
	 
 }
 </script>
</body>
</html>

在这里插入图片描述

在这里插入图片描述

三:

​ 这个案例就是在二的基础上加入了查询和分页操作。

在这里插入图片描述

项目结构:

在这里插入图片描述

主页面index.jsp:

<%@ page  pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>  
    <meta charset="utf-8"/>  
    
    <title>Home</title>  
    <style>  
       html,body{
       height:90%;
       }
        #left{  
            width: 15%;  
            height: 100%;  
            float: left;  
            border-right:1px solid gray;
        }  
        #right{  
            width: 80%;  
            height: 100%;  
            border:0;
        }  
    </style>  
<body>  
<p>${pageContext.request.contextPath}<p>
 <%=request.getContextPath() %>
    <h2>学生信息管理</h2><hr>
    
    <div id="left">
     <ul>
         <!--${pageContext.request.contextPath}通常返回的是Web应用程序的上下文路径,例如/myapp,这个上下文路径是相对于域名和端口的。 -->
         <!-- 点击之后 会right显示 -->
        <li><a href="${pageContext.request.contextPath}/student?action=query1" target="right">模糊查询</a></li> 
         <li><a href="${pageContext.request.contextPath}/student?action=query2" target="right">分页浏览</a></li>
          <li><a href="${pageContext.request.contextPath}/student?action=query3" target="right">分页查询</a></li> 
         <!--在名为"right"的窗口或框架中显示目标页面。 -->
         
     </ul>
    </div>  
    <iframe id="right" name="right"  src=""></iframe>  
  
</body>  
</html>

我们看一下后台的servlet是怎么写的

package servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.StudentDao;
import entity.Student;
@WebServlet("/student")
public class StudentServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    StudentDao studentDao=new StudentDao();
    public StudentServlet() {
        super();
     
    }
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);// 这一行一定要写 因为你前端的超链接发送到servlet是get请求
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");//对请求来的参数进行编码
		String operationType=request.getParameter("action");//获取是那一中查询方式
		if("query1".equals(operationType)) {
			this.query1(request, response);
		}
		else if("query2".equals(operationType)) {
			this.query2(request, response);
		}
		else if("query3".equals(operationType)) {
			this.query3(request, response);
		}
	}
	
	private void query1(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
		try {
			String condition=" where 1=1 "; //恒等条件
			String sno=request.getParameter("sno");
			String sname=request.getParameter("sname");
			String sex=request.getParameter("sex");
            //下面模糊查询
			if(notEmpty(sno)) {
				condition+=" and sno like '%"+sno+"%' ";
			}
			if(notEmpty(sname)) {
				condition+=" and sname like '%"+sname+"%' ";
			}
			if(notEmpty(sex)) {
				condition+=" and sex like '%"+sex+"%' ";
			}
            //将数据保存到请求中
			request.setAttribute("studentList",studentDao.query(condition));		request.getRequestDispatcher("/student/query1.jsp").forward(request,response);
            //请求转发 数据共享
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void query2(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
		try {
			int pageNo=1;//定义初始页码
			try {
				pageNo=Integer.parseInt(request.getParameter("pageNo"));//获取前端那个地方是第几页
			} catch (Exception e) {
			}
			int pageSize=10;//定义每一页有多少条数据 
			int recordCount=studentDao.getRecordCount("");
			if(recordCount>0){
				 List<Student> studentList=studentDao.query("","",pageNo,pageSize);	
					int t1=recordCount%pageSize;
					int t2=recordCount/pageSize;
					int pageCount=(t1==0?t2:t2+1);
					request.setAttribute("pageNo", pageNo);//当前是第几页
					request.setAttribute("pageCount", pageCount);//总共多少页
					request.setAttribute("studentList", studentList);//学生列表
			}
			request.setAttribute("recordCount", recordCount);//一共多少条记录
			request.getRequestDispatcher("/student/query2.jsp").forward(request,response);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private void query3(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
		try {
			String condition=" where 1=1 ";
			String sno=request.getParameter("sno");
			String sname=request.getParameter("sname");
			String sex=request.getParameter("sex");
            //模糊查询
			if(notEmpty(sno)) {
				condition+=" and sno like '%"+sno+"%' ";
			}
			if(notEmpty(sname)) {
				condition+=" and sname like '%"+sname+"%' ";
			}
			if(notEmpty(sex)) {
				condition+=" and sex like '%"+sex+"%' ";
			}
			int pageNo=1;
			try {
				pageNo=Integer.parseInt(request.getParameter("pageNo"));//获取页数
			} catch (Exception e) {
			}
			int pageSize=10;
			int recordCount=studentDao.getRecordCount(condition);
			if(recordCount>0){
				 List<Student> studentList=studentDao.query(condition,"",pageNo,pageSize);						
					int t1=recordCount%pageSize;;
					int t2=recordCount/pageSize;
					int pageCount=(t1==0?t2:t2+1);
					request.setAttribute("pageNo", pageNo);
					request.setAttribute("pageCount", pageCount);
					request.setAttribute("studentList", studentList);
			}
			request.setAttribute("recordCount", recordCount);
			request.getRequestDispatcher("/student/query3.jsp").forward(request,response);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private boolean notEmpty(String s) {
		return s!=null&&!"".equals(s.trim());
	}
}

query1.jsp 模糊查询

<%@ page   pageEncoding="UTF-8" import="java.util.List,dao.StudentDao,entity.Student"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head><title>模糊</title>
<script>
function qingchu(){
	document.getElementById("sno").value='';
	document.getElementById("sname").value='';
	document.getElementById("sex").value='';
}
</script>
<style>
th,td{
border:2px solid gray;
padding:3px;
text-align:center;
}
table,form{
border-collapse:collapse;
margin:0 auto;
text-align:center;
}
</style>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/student">
学号<input type="text" name="sno" id="sno" value="${param.sno}"><!--保留上次输入记录-->
姓名<input type="text" name="sname" id="sname" value="${param.sname}">
性别<input type="text" name="sex" id="sex" value="${param.sex}">
<input type="button"  value="清除" οnclick="qingchu()"/>
<input type="hidden" name="action" value="query1"/>
<input type="submit" value="查询"/>
</form>
<br>
<table>
<tr><th>序号</th><th>学号</th><th>姓名</th><th>性别</th><th>修改</th><th>删除</th></tr>
<c:forEach items="${studentList}" var="student" varStatus="status"><!--循环创建-->
<tr>
<td>${status.index+1}</td> <!--序号从0开始,所以要加1-->
<td>${student.sno}</td>
<td>${student.sname}</td>
<td>${student.sex}</td> 
<td><a href="${pageContext.request.contextPath}/student/edit.jsp?id=${student.id}&sno=${student.sno}&sname=${student.sname}&sex=${student.sex}">修改</a></td>
<td><a href="${pageContext.request.contextPath}/student?id=${student.id}&action=delete" οnclick="return confirm('确实要删除该记录吗?')">删除</a></td>
</tr>
</c:forEach> 
</table>
</body>
</html>

在这里插入图片描述

query2.jsp 分页浏览

<%@ page   pageEncoding="UTF-8" import="java.util.List,dao.StudentDao,entity.Student"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head><title>模糊</title>
<script>
function qingchu(){
	document.getElementById("sno").value='';
	document.getElementById("sname").value='';
	document.getElementById("sex").value='';
}
</script>
<style>
th,td{
border:2px solid gray;
padding:3px;
text-align:center;
}
table,form{
border-collapse:collapse;
margin:0 auto;
text-align:center;
}
#pageSwitch{
margin:5px;
text-align:center;
}
</style>
<script>
function jump1(pageNo){  //跳转到第几页
	location.href="${pageContext.request.contextPath}/student?action=query2&pageNo="+pageNo;
}
</script>
</head>
<body>
    <!--如果请求范围内(servlet会传递过来) recordCount =0 -->
<c:if test="${requestScope.recordCount==0}">
无记录
</c:if>
    
<c:if test="${requestScope.recordCount>0}">
<table>
<tr><th>序号</th><th>学号</th><th>姓名</th><th>性别</th><th>修改</th><th>删除</th></tr>
<c:forEach items="${studentList}" var="student" varStatus="status">
<tr>
<td>${status.index+1}</td>
<td>${student.sno}</td>
<td>${student.sname}</td>
<td>${student.sex}</td> 
<td><a href="${pageContext.request.contextPath}/student/edit.jsp?id=${student.id}&sno=${student.sno}&sname=${student.sname}&sex=${student.sex}">修改</a></td>
<td><a href="${pageContext.request.contextPath}/student?id=${student.id}&action=delete" οnclick="return confirm('确实要删除该记录吗?')">删除</a></td>
</tr>
</c:forEach> 
</table>
<div id="pageSwitch">
    <!--recordCount记录数-->   <!--pageNo当前页数--> <!--pageCount总页数-->
 共有记录${recordCount}条, 第${pageNo}/${pageCount}页,
<c:if test="${pageNo>1}">
 <a href="javascript:jump1('1')">首页</a>
 <a href="javascript:jump1('${pageNo-1}')">上页</a>
</c:if>
       <!--如果是第一页的话,把上一页和首页固定主 而且不能点击--> 
<c:if test="${pageNo==1}">
  首页  上页
</c:if>

 <c:if test="${pageNo<pageCount}">
   <a href="javascript:jump1('${pageNo+1}')">下页</a>
   <a href="javascript:jump1('${pageCount}')">末页</a>
</c:if>
      <!--如果是第后一页的话,把下一页和尾页固定主 而且不能点击--> 
 <c:if test="${pageNo==pageCount}">
   下页   末页
</c:if>
 
 </div>

</c:if>
</body>
</html>

在这里插入图片描述

query3.jsp 分页查询

<style>
th,td{
border:2px solid gray;
padding:3px;
text-align:center;
}
table,form{
border-collapse:collapse;
margin:0 auto;
text-align:center;
}
#pageSwitch{
margin:5px;
text-align:center;
}
</style>
<%@ page   pageEncoding="UTF-8" import="java.util.List,dao.StudentDao,entity.Student"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head><title>模糊</title>
<script>
function qingchu(){
	document.getElementById("sno").value='';
	document.getElementById("sname").value='';
	document.getElementById("sex").value='';
}
function jump1(pageNo){
	var queryForm=document.getElementById("queryForm");
    queryForm.pageNo.value=pageNo;
	queryForm.submit();
}
</script>
    <!-- 将上面css代码放到这里-->

</head>
<body>
<h>${requestScope.recordCount}</h> <!--使用EL表达式获取存在请求范围内的数据-->
<form method="post" action="${pageContext.request.contextPath}/student" id="queryForm">
学号<input type="text" name="sno" id="sno" value="${param.sno}">
姓名<input type="text" name="sname" id="sname" value="${param.sname}">
性别<input type="text" name="sex" id="sex" value="${param.sex}">
<input type="button"  value="清除" οnclick="qingchu()"/>
<input type="hidden" name="action" value="query3"/>
<input type="hidden" name="pageNo" value="1"/>
<input type="submit" value="查询"/>
</form>
<br>
  <!--判断是否查询到记录-->
<c:if test="${requestScope.recordCount==0}">
<div style="text-align:center">无记录</div>
</c:if>
<c:if test="${requestScope.recordCount>0}">
<table>
<tr><th>序号</th><th>学号</th><th>姓名</th><th>性别</th><th>修改</th><th>删除</th></tr>
<c:forEach items="${studentList}" var="student" varStatus="status">
<tr>
<td>${status.index+1}</td>
<td>${student.sno}</td>
<td>${student.sname}</td>
<td>${student.sex}</td> 
<td><a href="${pageContext.request.contextPath}/student/edit.jsp?id=${student.id}&sno=${student.sno}&sname=${student.sname}&sex=${student.sex}">修改</a></td>
<td><a href="${pageContext.request.contextPath}/student?id=${student.id}&action=delete" οnclick="return confirm('确实要删除该记录吗?')">删除</a></td>
</tr>
</c:forEach> 
</table>
    
<div id="pageSwitch">
 共有记录${recordCount}条, 第${pageNo}/${pageCount}页,
    <!--对首页进行特殊判断--->
<c:if test="${pageNo>1}">
 <a href="javascript:jump1('1')">首页</a>
 <a href="javascript:jump1('${pageNo-1}')">上页</a>
</c:if>
<c:if test="${pageNo==1}">
  首页  上页
</c:if>
    <!--对尾页进行特殊判断--->
 <c:if test="${pageNo<pageCount}">
   <a href="javascript:jump1('${pageNo+1}')">下页</a>
   <a href="javascript:jump1('${pageCount}')">末页</a>
</c:if>
 <c:if test="${pageNo==pageCount}">
   下页   末页
</c:if>
 </div>
 </c:if>
</body>
</html>

在这里插入图片描述

总结:

​ 在这篇文章中,我尽力提供了清晰的解释和相关示例,以帮助读者更好地理解JavaWeb的关键概念和技术。我希望这篇复习总结对那些正在学习或回顾JavaWeb开发的人们有所帮助。

​ 最后,我想强调一下,如果在文章中存在任何侵权问题,请您立即与我取得联系,我将及时删除有关内容。