Javaweb考前复习冲刺(不断更新版)
Javaweb考前复习冲刺
第一章: JavaWeb 入门
JavaWeb是指:以Java作为后台语言的项目工程。
javaweb项目创建的过程:
- 首先集成Tomcat服务器环境
- 新建dynamic web project
- 部署工程
- 运行
路由含义:
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 表达式使用 ${}
的语法来引用和操作数据。在 ${}
中可以使用以下几种语法:
- 访问变量和属性:
${variable}
或${object.property}
例如:${name}
或${user.name}
- 调用方法:
${object.method()}
或${object.method(param1, param2)}
例如:${user.getName()}
或${user.add(5, 3)}
- 访问数组和列表元素:
${array[index]}
或${list[index]}
例如:${array[0]}
或${list[2]}
- 执行算术和逻辑运算:
${num1 + num2}
或${boolean1 && boolean2}
例如:${2 + 3}
或${true && false}
- 使用条件和循环:
${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="提交"/> <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:
项目结构:
实体包我就不讲了,就是一个类,然后构造函数还有一些get
、set
的函数。
看一下数据操控包:
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()
方法来处理这些请求。
-
doGet(HttpServletRequest request, HttpServletResponse response)
:- 用于处理HTTP GET请求。
- 通常用于从服务器获取数据,如检索数据库记录或执行一些只读操作。
- 可以通过
HttpServletRequest
对象获取请求参数、请求头、会话信息等。 - 可以使用
HttpServletResponse
对象生成并发送响应给客户端。
-
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中常用的内部对象:
HttpServletRequest
:表示HTTP请求的对象。它提供了访问请求的各种属性和数据的方法。一些常见的方法包括:getParameter(name)
:获取指定名称的请求参数的值。getMethod()
:获取HTTP请求的方法(如GET、POST等)。getRequestURL()
:获取请求的URL。getSession()
:获取与请求关联的会话对象。getHeader(name)
:获取指定名称的请求头的值。
HttpServletResponse
:表示HTTP响应的对象。它提供了生成和发送响应给客户端的方法。一些常见的方法包括:setContentType(type)
:设置响应的内容类型。getWriter()
:获取用于写入响应数据的PrintWriter
对象。setStatus(status)
:设置响应的状态码。sendRedirect(url)
:将响应重定向到指定的URL。
HttpSession
:表示与客户端关联的会话对象。它用于在多个请求之间存储和共享数据。一些常见的方法包括:setAttribute(name, value)
:在会话中设置属性的值。getAttribute(name)
:获取会话中指定属性的值。removeAttribute(name)
:从会话中删除指定的属性。
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之前或响应返回给客户端之前拦截、处理请求和响应的组件。它可以对请求进行预处理、对响应进行后处理,也可以修改请求和响应的内容。过滤器通常用于实现以下功能:
- 认证和授权:验证用户身份,检查访问权限。
- 日志记录和性能监控:记录请求和响应的信息,测量性能指标。
- 数据压缩和加密:对请求和响应进行压缩或加密。
- 请求和响应的修改:修改请求参数、响应内容或头部信息。
- 缓存和资源优化:缓存响应内容或优化资源加载。
过滤器创建过程:
我们主要时修改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应用程序中的事件和状态变化的组件。它可以接收和响应特定事件的发生,以执行相应的逻辑。监听器通常用于以下场景:
- 生命周期事件:监听Servlet、会话或上下文的创建、销毁和属性变化等生命周期事件。
- 请求和会话事件:监听请求的开始和结束,会话的创建和销毁,属性的变化等事件。
- 上下文初始化和销毁:监听Web应用程序的初始化和销毁事件。
- 属性变化:监听属性的增加、修改和删除等变化。
创建过程:
勾选要监听的事件。
在Java Servlet规范中,可以监听多种类型的对象。根据不同的对象类型,可以将监听对象分为以下几类:
-
ServletContext(Web应用程序上下文)(应用对象)相关的监听对象:
- ServletContextListener:用于监听ServletContext的创建和销毁事件。
- ServletContextAttributeListener:用于监听ServletContext属性的添加、删除和替换事件。
-
HttpSession(会话)相关的监听对象:
- HttpSessionListener:用于监听HttpSession的创建和销毁事件。
- HttpSessionAttributeListener:用于监听HttpSession属性的添加、删除和替换事件。
- HttpSessionActivationListener:用于监听HttpSession的活化和钝化事件。
- HttpSessionBindingListener:用于监听HttpSession属性绑定和解绑事件。
- HttpSessionIdListener:用于监听HttpSession ID的改变事件。
-
ServletRequest(请求)相关的监听对象:
- ServletRequestListener:用于监听ServletRequest的创建和销毁事件。
- ServletRequestAttributeListener:用于监听ServletRequest属性的添加、删除和替换事件。
-
异步请求相关的监听对象:
-
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时,通常会遵循以下步骤:
- 编写前端代码:使用JavaScript编写前端代码,在页面中定义事件处理程序,例如按钮点击或表单提交事件。在事件处理程序中,使用Ajax发送HTTP请求到服务器,并定义处理服务器响应的回调函数。
- 编写服务器端代码:使用Java编写一个Servlet来处理Ajax请求。在Servlet中,解析请求参数,并根据请求的内容执行相应的业务逻辑。可以查询数据库、调用其他Java类或服务,生成响应数据,并将其返回给客户端。
- 处理响应数据:在前端的Ajax回调函数中,处理服务器返回的响应数据。可以解析JSON数据、更新页面内容、执行动态操作等。
需要注意的是,Ajax请求是异步的,意味着它们不会阻塞页面加载或用户交互。这使得Ajax非常适合在后台与服务器进行通信,而无需中断用户操作。
步骤:
- 创建xhr对象:
xhr =new XMLHttpRequest();
- 建立连接: open(type,url, asynch) 第三个参数一般不写 默认使true 异步连接
- 发送:xhr.send(content)
- 事件绑定: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
相关属性的含义:
UNSENT
(0): 初始状态,XMLHttpRequest 对象已创建,但尚未调用open()
方法。OPENED
(1):open()
方法已经被调用,请求已准备好发送,但尚未调用send()
方法。HEADERS_RECEIVED
(2):send()
方法已调用,并且头部和状态已经可用。可以通过getResponseHeader()
获取响应头信息,可以通过getAllResponseHeaders()
获取所有响应头信息。LOADING
(3): 响应数据正在接收中。部分响应数据已经可用,但responseText
属性可能还未完全填充。DONE
(4): 响应已经完全接收,且数据可用。此时可以使用responseText
或responseXML
属性来获取完整的响应数据。
status
属性 状态码相关含义:
HTTP 状态码是服务器响应请求时返回的一个三位数的数字代码,用于指示请求的处理结果。常见的 HTTP 状态码包括:
200
:请求成功。表示服务器已成功处理请求并返回所需的数据。404
:未找到。表示请求的资源在服务器上不存在。500
:服务器内部错误。表示服务器在处理请求时遇到了错误。
responseText
和 responseXML
是 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 数据。
-
将对象转换为 JSON 字符串:使用
JSON.stringify()
方法可以将 JavaScript 对象转换为 JSON 字符串。var obj = { name: "John", age: 30 }; var jsonString = JSON.stringify(obj); console.log(jsonString); // 输出:{"name":"John","age":30}
-
将 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
-
处理复杂的 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()
方法可以方便地生成表单提交参数字符串。
- 使用
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开发的人们有所帮助。
最后,我想强调一下,如果在文章中存在任何侵权问题,请您立即与我取得联系,我将及时删除有关内容。