
一、会话管理
1.HTTP协议 2.会话的概念 3.会话跟踪技术 4.会话跟踪技术分类(四种)
二、文件上传与下载
1.上传 2.下载 3.上传和下载合并优化成工具类
三、Ajax
1.JS中Ajax的基本使用 2.jQuery中Ajax的使用
一、会话管理
1.HTTP协议
http协议,就是浏览器和服务器之间进行“沟通”的一种规范。我们在看空间,刷微博…都是在使用http协议,当然,远远不止这些应用。
TCP/IP协议和UDP协议
TCP协议是一种可靠协议,即数据包不会丢失;UDP是一种不可靠协议,丢失几个数据包对它来说无关紧要。
很明显,UDP协议不符合Web应用的需求。
HTTP协议的由来
TCP协议是基于连接和三次握手的,虽然具有可靠性,但人具有一定的缺陷。但试想一下,普通的C/S架构软件,顶多上千个Client同时连接,而B/S架构的网站,十万人同时在线也是很平常的事儿。如果十万个客户端和服务器一直保持连接状态,那服务器如何满足承载呢?
这就衍生出了http协议。基于TCP的可靠性连接。通俗点说,就是在请求之后,服务器端立即关闭连接、释放资源。这样既保证了资源可用,也吸取了TCP的可靠性的优点。
正因为这点,所以大家通常说http协议是“无状态”的,也就是“服务器不知道你客户端干了啥”,其实很大程度上是基于性能考虑的。
所以,Http是无状态的。
2.会话的概念
用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话。会话跟踪技术
3.会话跟踪技术
HTTP是一种无状态协议,每当用户发出请求时,服务器就做出响应,客户端与服务器之间的联系是离散的、非连续的。每当用户在同一个网站的多个页面之间转换时,根本无法知道是否是同一个客户,会话跟踪就可以解决这个问题。当一个客户在多个页面之间切换时,服务器会保存该用户的信息。
4.会话跟踪技术分类(四种)
隐藏表单域
将字段隐藏在HTML表单中,但不在客户端显示。比如在第一张页面中输入用户名和密码登陆,服务器生成响应返回第二张页面。当第二张页面提交时可能仍然需要知道来自第一张页面中的用户名。那么就可以通过隐藏表单域来实现这一连续的过程。当第一张页面提交后,服务器端作出响应返回第二张页面,此页面中用隐藏域记录了来自登陆时的用户名。
①在form表单中添加对应隐藏域:
<input type=“hidden” name=“username” value=“Sunny”>
②在请求中获取值:
String name = request.getParameter(“username”);
Cookie
①Cookie简介:
Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式。Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息。无论何时用户链接到服务器,Web站点都可以访问 Cookie 信息 。
目前有些 Cookie 是临时的,有些则是持续的。临时的 Cookie 只在浏览器上保存一段规定的时间,一旦超过规定的时间,该 Cookie 就会被系统清除 。
原理:将一个文本文件写入客户端的硬盘中,将要记住的内容以键值对的形式写在文本文件中 。
②向客户端添加Cookie:
String nameKey = URLEncoder.encode("姓名", "utf-8") ;// cookie保存中文报错
String nameValue = URLEncoder.encode("张三", "utf-8") ;// cookie保存中文报错
Cookie cookie = new Cookie(nameKey, nameValue);
cookie.setMaxAge(60);// 秒
response.addCookie(cookie);
③Cookie年龄的设置:
cookie.setMaxAge(maxAge);
- 该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。
- maxAge如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。默认为–1。
- maxAge如果为0,表示删除该Cookie。
- 设置Cookie永不过期: 设置年龄参数为Integer.MAX_VALUE
④获取Cookie:
Cookie [] cs = request.getCookies();
if(cs!=null){
for(Cookie c: cs){
// URLDecoder.decode解决中文存取的问题
String cookieKey = URLDecoder.decode(c.getName(), "utf-8");
String cookieValue = URLDecoder.decode(c.getValue(), "utf-8");
}
}
⑤Cookie总结:
- 只能往Cookie中写字符串,不能放对象
- 放在客户端不安全
- 一个WEB程序只支持200多个Cookie
- 客户端可以禁止Cookie
URL重写
①用途:解决了客户端禁止了Cookie,又要传SessionID的问题。
②原理:将sessionID添加到URL的后面,类似查询字符串的方法。
③方法:
方法一String encodeURL(String url)重写给定的url,包含sessionID。
String newUrl = resp.encodeURL(req.getContextPath()+"/new.jsp");
resp.sendRedirect(newUrl);
方法二String encodeRedirectURL(String url)使用sendRedirect方法时,重写给定的url,包含sessionID。
这2个方法只有在客户端禁用了cookie才会生效。
④两种方法的对比:
-
共同点:都对url附加上jsessionid参数进行了处理,如果需要,则在url的path后面附加上;jsessionid=xxx;如果不需要则直接返回传入的url。
-
不同点:encodeURL在附加jsessionid之前还对url做了判断处理:如果url为空字符串(长度为0的字符串),则将url转换为完整的URL(http或https开头的);如果url是完整的URL,但不含任何路径(即只包含协议、主机名、端口,例如http://127.0.0.1 ),则在末尾加上根路径符号/。
也就是encodeURL如果进行了编码,则返回的URL一定是完整URL而不是相对路径;而encodeRedirectURL则不对URL本身进行处理,只专注于添加jsessionid参数(如果需要)。
Session
HttpSession接口实现了会话机制,并用Session来跟踪客户的状态。Session是在一段时间内,单个客户与Web服务器的一连串的相关的交互过程。在一个Session中客户可能会多次请求访问同一个页面,也有可能请求访问不同的服务器资源。
原理:WEB容器为每个客户端会提供一个session,当调用相应的方法时,该session就会产生,并同时产生一个唯一的session ID,通过Cookie发送到客户端进行保存,并可以向session里存数据(对象),那么该客户端在由该页面跳转到 下一个页面后,就可以把前面页面中向session中共享的数据取出来。
①session的常用方法:
| 方法 | 说明 |
|---|---|
| request.getSession() | 得到当前请求相关的Session |
| session.getId() | 得到session的唯一标识ID号 |
| session.getCreationTime() | 得到session的创建时间 |
| session.getLastAccessedTime() | 上次访问时间 |
| session.getMaxInactiveInterval() | 得到最大活动时间 |
| session.setMaxInactiveInterval(int 秒) | 设置最大活动时间 |
| session.setAttribute(“name”,“value”) | 将数据存入session |
| session.getAttribute(“name”) | 将session中的数据取出 |
- request.getSession() 方法会先查看有没有与当前请求相关联的会话对象,如果有,直接返回该会话对象,如果没有,且参数为无参/true,该方法将会新创建一个会话对象并返回,若参数为false,则直接返回null。
- session.setMaxInactiveInterval(int 秒) 方法参数不设置默认为30分钟,-1则为永不过期。
②session的销毁(四种方法):
- web.xml里配置session超时(tomcat的全局web.xml、项目级别的web.xml)
- 在代码中设置超时:
session.setMaxInactiveInterval(30*60) // 单位秒 - 让session内容全部清除:
session.invalidate(); - 服务器关闭
③session总结:
- 所有session存在服务器端,耗服务器资源。
- Session中的数据是对同一个浏览器窗口有效,如果客户端重新打开一个浏览器访问WEB程序,则在第一个窗口中的Session中共享的数据在第二个窗口中取不到。
- sessionID是通过Cookie传递的,如果客户端禁止了Cookie则无法传递sessionID。
二、文件上传与下载
1.上传
在Servlet2.5中,我们要实现文件上传功能时,一般情况下都需要借助其他开源组件。然而在Servlet3.0中提供了对文件上传的直接支持,不需要借助任何第三方上传组件,直接使用Servlet3.0提供的API就能够实现文件上传功能了。
实现步骤:
- 设置表单的行内式属性:
method="post" enctype="multipart/form-data" - 表单里至少写上一个file类型的input框:
<form action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data" >
上传:<input type="file" name="uploadFile1" /> <br/><br/>
上传:<input type="file" name="uploadFile2" /> <br/><br/>
上传:<input type="file" name="uploadFile3" /> <br/><br/>
<input type="submit" />
</form>
- 在servlet中加上@MultpartConfig注解,声明使用了文件上传技术。
- 在servlet中获取:
request.getPart(“参数名”)单个文件
request.getParts()上传的文件的集合 - 获取文件名和后缀
part.getHeader("content-disposition");
p.getSubmittedFileName();(tomcat8及以上版本才有)
文件名为中文的时候需要加上
request.setCharacterEncoding("utf-8");才会不乱码。
- 通过
part.write(filePath+fileName);将文件写到本地指定目录中。
@MultipartConfig
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
private String filePath = "D:\\proFile\\" ;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
Collection<Part> parts = req.getParts();
for (Part p : parts) {
if(p!=null){
String fileName = p.getSubmittedFileName();
p.write(filePath+fileName);
}
}
}
}
2.下载
//设置请求编码为utf-8
req.setCharacterEncoding("utf-8");
//获取需要下载的文件名
String fileName = req.getParameter("fileName");
//查看下载文件是否存在
File file = new File(path + fileName);
if (!file.exists()) {
System.out.println("文件不存在");
return;
}
//告诉http协议,这是一个文件流,请下载它
res.setContentType("application/octet-stream");
//告诉http协议,文件名是啥
res.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("utf-8"), "iso-8859-1"));
//告诉http协议,文件是多大
res.addHeader("Content-Length", file.length() + "");
//打开一个输入流,指向目标文件
FileInputStream in = new FileInputStream(file);
//in.available() 获取输入流目标的大小
byte[] data = new byte[in.available()];
//读取data.length长度的字节数据,读到data这个Byte数组中存放着
in.read(data);
//打开字节流,因为我们要通过二进制流下载文件
ServletOutputStream outputStream = res.getOutputStream();
outputStream.write(data);
outputStream.flush(); //清空缓冲区
//关闭流
outputStream.close();
in.close();
3.上传和下载合并优化成工具类
public class FileUtil {
/**
* 文件上传功能
* @param request
* @param path
* @return 多文件上传的文件名
* @throws Exception
*/
public static List<String> uploadFile(HttpServletRequest request,String path) throws Exception{
Collection<Part> parts = request.getParts();
List<String> fileNameList = new ArrayList<String>();
for (Part p : parts) {
if(p!=null){
String fileName = p.getSubmittedFileName();
p.write(path+fileName);
fileNameList.add(fileName);
}
}
return fileNameList ;
}
/**
* 文件下载
* @param response
* @param pathName
* @throws Exception
*/
public static void downloadFile(HttpServletResponse response,String pathName) throws Exception{
File file = new File(pathName);
if (!file.exists()) {
System.out.println("文件不存在");
response.getWriter().write("文件不存在");
return ;
}
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition","attachment;filename=" + new String(file.getName().getBytes("utf-8"), "iso-8859-1"));
response.addHeader("Content-Length", file.length() + "");
FileInputStream in = new FileInputStream(file);
byte[] data = new byte[1024*100];
int i= 0 ;
ServletOutputStream outputStream = response.getOutputStream();
while((i=in.read(data)) != -1){
outputStream.write(data,0,i);
}
outputStream.flush();
outputStream.close();
in.close();
}
}
三、Ajax
1.JS中Ajax的基本使用
前端代码
<input id="userName" onblur="check()" />
<h1 id="msg"></h1>
...
// 创建异步请求对象
var xmlhttp = new XMLHttpRequest();
// 设置请求类型、请求地址以及参数、是否异步
xmlhttp.open("post","HelloServlet",true);
// 设置请求头部信息
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
// 发送请求
var input = document.getElementById("userName");
xmlhttp.send("userName="+$("input").input.value);
// 状态监听
xmlhttp.onreadystatechange = function(){
// 当状态为4 响应码为200的时则表示请求完成
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
// 获取返回请求结果
var result = xmlhttp.responseText;
// 根据请求结果进行处理
if(result == 1){
$("#msg").text("恭喜你,可以使用此用户名");
}else{
$("#msg").text("对不起,此用户名已被使用");
}
}
};
后台代码
// 获取用户提交的请求参数
String name = request.getParameter("userName");
PrintWriter pw = response.getWriter();
// 当用户名是seven返回字符串0,否则返回字符串1
if("zhangsan".equals(name)){
pw.write("0");
}else{
pw.write("1");
}
2.jQuery中Ajax的使用
通过上面我们可以看到在JS中使用Ajax十分繁琐,好在jQuery中对Ajax使用步骤进行了优化,让其使用变得轻松起来:
$("#userName").on("blur",function(){
// $.ajax 表示jquery中的ajax的调用方式
$.ajax({
"url":"HelloServlet", // 请求地址
"data":"userName="+$("input").val(), //参数
"type":"POST", // 请求类型
"success":function(data){ // 请求成功时的回调函数
if(data == 1){
$("#msg").text("恭喜你,可以使用此用户名");
}else{
$("#msg").text("对不起,此用户名已被使用");
}
},
"error":function(){ // 请求失败时的回调函数
}
});
);
交互数据是json格式时:
前端代码
/*
使用 HTTP GET 请求从服务器加载 JSON 编码的数据
第1个参数为请求地址,第2个参数为请求参数,第3个参数为成功时的回到函数
*/
$.getJSON("HelloServlet",{userName:$("input").val()},function(data){
// 如果返回的json字符串定义了result的键,可以直接通过键取出值进行判断操作
if(data.result){
$("#msg").text("恭喜你,可以使用此用户名");
}else{
$("#msg").text("对不起,此用户名已被使用");
}
});
后台代码
// 获取用户提交的请求参数
String name = request.getParameter("userName");
PrintWriter pw = response.getWriter();
if("zhangsan".equals(name)){
pw.write("{\"result\":false}");
}else{
pw.write("{\"result\":true}");
}
本文介绍了JavaEE中的会话管理,包括HTTP协议、会话概念、会话跟踪技术(隐藏表单域、Cookie、URL重写、Session)。接着讲解了文件上传和下载的实现步骤,以及如何将这些功能整合到工具类中。最后,探讨了JS和jQuery中Ajax的基本使用,展示了前后端代码示例。

555

被折叠的 条评论
为什么被折叠?



