小汤学编程之JavaEE学习day05——会话管理、文件上传与下载、Ajax

本文介绍了JavaEE中的会话管理,包括HTTP协议、会话概念、会话跟踪技术(隐藏表单域、Cookie、URL重写、Session)。接着讲解了文件上传和下载的实现步骤,以及如何将这些功能整合到工具类中。最后,探讨了JS和jQuery中Ajax的基本使用,展示了前后端代码示例。

在这里插入图片描述

一、会话管理
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的销毁(四种方法):

  1. web.xml里配置session超时(tomcat的全局web.xml、项目级别的web.xml)
  2. 在代码中设置超时:session.setMaxInactiveInterval(30*60) // 单位秒
  3. 让session内容全部清除:session.invalidate();
  4. 服务器关闭

③session总结:

  • 所有session存在服务器端,耗服务器资源。
  • Session中的数据是对同一个浏览器窗口有效,如果客户端重新打开一个浏览器访问WEB程序,则在第一个窗口中的Session中共享的数据在第二个窗口中取不到。
  • sessionID是通过Cookie传递的,如果客户端禁止了Cookie则无法传递sessionID。


二、文件上传与下载

1.上传

在Servlet2.5中,我们要实现文件上传功能时,一般情况下都需要借助其他开源组件。然而在Servlet3.0中提供了对文件上传的直接支持,不需要借助任何第三方上传组件,直接使用Servlet3.0提供的API就能够实现文件上传功能了。

实现步骤:

  1. 设置表单的行内式属性:method="post" enctype="multipart/form-data"
  2. 表单里至少写上一个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>
  1. 在servlet中加上@MultpartConfig注解,声明使用了文件上传技术。
  2. 在servlet中获取:
    request.getPart(“参数名”) 单个文件
    request.getParts() 上传的文件的集合
  3. 获取文件名和后缀
    part.getHeader("content-disposition");
    p.getSubmittedFileName();(tomcat8及以上版本才有)

文件名为中文的时候需要加上request.setCharacterEncoding("utf-8");才会不乱码。

  1. 通过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}");
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值