Java Web之Java Servlet学习笔记
Java Servlet组件
重点:了解Java Servlet组件的原理及编程;Java Servlet 的配置和生命周期。
概述:
- Servlet的生命周期:创建servlet对象时,会调用init方法进行初始化;任何来自客户端的请求,都会调用service方法服务;当servlet销毁之前,会调用destory方法进行销毁
- Servlet原理:Server服务器 let小型程序;运行在服务器端的小型程序,请求是以线程的方式访问目标Servlet,运行原理如下:
- 用户通过HTTP协议发送get请求,访问web容器
- web容器将http请求封装成Request对象,并创建了response对象
- 判断servlet是否被创建,如果没有,初始化目标Servlet
- 调用servlet的service方法,并将request和response当成参数传进去
- service会根据http请求的类型,自动调用doget/dopost方法
- 销毁request和response对象,并将数据通过http返回给用户
- request常用的方法:
- request.getMethod();获取请求类型
- request.getRemoteAddr();获取客户端IP
- request.getRequestURL();获取请求的url
- request.getRequestURI();获取请求的资源
- response常用的方法:
- response.setCharactorEncoding("utf-8");设置编码
- response.getWrite();获取字符输出流
Servlet简介
在学习Servlet之前,先了解下IE与服务器交互过程:

Servlet 是在服务器上运行的小程序。这个词是在 Java applet的环境中创造的,Java applet 是一种当作单独文件跟网页一起发送的小程序,它通常用于在客户端运行,结果得到为用户进行运算或者根据用户互作用定位图形等服务。 最早支持 Servlet 技术的是 JavaSoft 的 Java Web Server。此后,一些其它的基于 Java 的 Web Server 开始支持标准的 Servlet API。
Servlet 的主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。这个过程为:
1) 客户端发送请求至服务器端;
2) 服务器将请求信息发送至 Servlet;
3) Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
4) 服务器将响应返回给客户端。

Servlet流程处理
1、客户端发送请求到服务器
2、服务器获取URL中的URI(/ContextPath/ServletPath)
3、根据URI中的应用名获取ServletContext对象
4、通过ServletContext对象来匹配ServletPath和url-pattern
5、根据匹配的结果获取相应的 类全名
6、一次性加载类封装成ServletConfig对象
7、对象根据多态调用Service()方法
8、将返回结果给用户

Servlet调用图
Servlet生命周期
服务器只创建每个Servlet的单一实例,每个用户请求都会引发新的线程。 创建Servlet实例时,会调用init()方法,针对每个用户请求都会创建一个线程,该线程调用前面创建实例的service()方法,由service()方法依据接收到的HTTP请求的类型,调用相应的doXxx方法,比如doGet(),最后调用destroy()方法销毁。
doGet ()和 doPost() 方法的参数都是 HttpServletRequest 和 HttpServletResponse 对象。其中HttpServletRequest 对象代表了客户端的请求,servlet 通过这个对象获得客户 端 的 请 求 数 据; HttpServletResponse对象代表了servlet对客户端请求的响应,sevlet用这个对象向客户端返回数据。
Servlet优点
高效:传统的CGI程序以进程方式运行,而Servlet以线程方式运行。
方便:Servlet提供了大量的实用工具例程,例如自动地解析和解码HTML表 单数据、读取和设置HTTP头、处理Cookie、跟踪会话状态等。
功能强大:可以完成很多传统的CGI程序很难做到的事情。
可移植性好:Servlet API具有完善的标准。
Servlet交互
浏览器与Web服务器的动态交互:

Method属性指定了数据传送方式,可以是GET或POST。
各种输入控件,接受用户输入;提交按钮,点此Button将把FORM内的数据传送到服务器
GET方式将数据接在URL后面传送给服务器端程序,如:http://url?name1=abc&name2=def;POST方式将数据放在HTTP请求的请求头后面发送。
Servlet 接口
javax.servlet 包的接口为:

ServletConfig——用来封装web.xml中对当前Servlet的配置信息。
getInitParameter()---可以获取初始化参数。Web.xml中: <init-param><param-name/> <param-value/></init-param>
ServletContext——代表当前Servlet运行的上下文环境,Web容器会为每一个Web工程创建一个对应ServletContext对象。
setAttribute()
getAttribute()
removeAttribute()
ServletRequest——为Servlet所发送的请求,用ServletRequest封装。常用子接口HttpServletRequest。
setAttribute()
getAttribute()
removeAttribute()
getParameter()
ServletResponse——Servlet对客户端所做的响应,用ServletResponse描述。子接口HttpServletResponse。
getWriter():获取PrintWriter输出流给客户发送的响应内容
setContentType:设置响应内容的响应类型和字符集信息
sendRedirect:设置重新请求路径
Servlet结构
Servlet的创建:
1,写一个类,继承HttpServlet,覆写 service/doget/dopost方法
2,直接创建Servlet

Servlet部署
1,在web.xml中进行配置
<servlet> <servlet-name>名字</servlet-name> <servlet-class>包名+类名</servlet-class> </servlet> <servlet-mapping> <servlet-name>名字</servlet-name> <url-pattern>虚拟URL:/根目录</url-pattern> </servlet-mapping>
@WebServlet(name="",urlPatterns={"url","url"})
@WebServlet("url")
Servlet会话技术
掌握Servlet跳转方式:
forward跳转:用户发送请求后,服务器获取请求并处理,在服务器内部跳转到指定请求路径上,并响应到浏览器的一个过程。
redirect跳转(重定向):用户发送请求后,服务器获取请求并处理,将结果响应给客户端浏览器,浏览器检测到响应的请求中有一个特殊的头信息location,并指向一个地址,浏览器会自动发送第二次请求到服务器,并响应到客户端。
servlet通信方法:
Servlet访问网络资源以满足客户端请求,使用RequestDispatcher接口的forward()和include()方法访问网络资源:
public void forward(ServletRequest req, ServletResponse res);——将请求从一个Servlet转送到同一个服务器上的另一个Servlet。
public void include(ServletRequest req, ServletResponse res);——在一个Servlet中包含另一个Servlet的内容。
cookie的创建获取与session的创建过程:
session的创建过程:session的创建采用赖汉式,当用户获取session的时候,服务器会首先到客户端获取cookie name值为jsessionid的cookie, 如果找到,获取对应的value并在服务器端返回对应的session,如果当前session是有效的,则返回给用户。反之当服务器在浏览器中未找到name=jsessionid的cookie,服务器会调用 getSession创建session,并将session的id写入到浏览器cookie中。
Servlet作用域
作用域就是能够保存命名属性的内存空间 主要包括 生命周期 和 共享范围
Servlet下载文件思路:
* 1,获取文件在服务器端的路径和文件的名称
* 2,需要告诉浏览器,以下载文件的方式运行
* 3,创建输入流和输出流、缓冲区
* 4,输入流读取文件、输出流响应文件
上传文件方式一:利用SmartUpload进行上传文件
jspsmartupload.jar包下载地址:http://note.youdao.com/noteshare?id=f79ca27ccc874d90fe877b325b724b6c&sub=4DAEFFD16E234887BDF6A26FA0AA2FF0
1.导入 jspsmartupload.jar(GBK版) 或 smartupload-utf8.jar (UTF-8)包,form表单 添加 encType="multipart/form-data" 因此表单是以二进制数据发送。
2.创建 SmartUpload 实例 SmartUpload su = new SmartUpload();
3. 初始化上传下载环境 su.initialize(getServletConfig(),request, respone);
4.过滤限制
su.setMaxFileSize(10000); // 限制每个文件上传的最大长度
su.setTotalMaxFileSize(20000); // 限制总上传数据的长度
su.setAllowedFilesList("jpg,dmp,gif,jpeg"); // 设置允许上传的后缀名
su.setDeniedFilesList("exe,bat,jsp,htm,html,doc,txt,,"); // 设置不允许的后缀名
5.准备上传 su.upload();
6.获取上传的文件个数 int count = su.getFiles().getCount();
7.获取上传的文件 com.jspsmart.upload.Files files = su.getFiles();
对files进行遍历获取单个File对象
File file = files.getFile(i);
String fieldName = file.getFieldName();
String fileName = file.getFileName();
8.复制文件 file.saveAs(destFilePathName,option);
例如:file.saveAs("/upload/"+fileName,su.SAVE_VIRTUAL);
/**
* destPathName为文件保存目录,option为保存选项,它有三个值,
* 分别是SAVE_PHYSICAL,SAVE_VIRTUAL和 SAVE_AUTO。
* SAVE_PHYSICAL指示组件将文件保存到以操作系统根目录为文件根目录的 目录下,
* SAVE_VIRTUAL指示组件将文件保存到以Web工程根目录为文件根目录的目录下,
* 而SAVE_AUTO则表示由组件自动选择。
*/
9.获取表单的其他内容(注意之前的request获取表单无效)com.jspsmart.upload.Request req = su.getRequest();
从以上看出,SmartUpload的代码量不会特别多,比较方便。
文件下载
1.初始化环境
SmartUpload su = new SmartUpload();
2.执行上传下载的初始化工作,必须第一个执行
su.initialize(getServletConfig(),request, respone);
3.设置下载文件
su.downloadFile("F:\\workcell\\AsaFood\\AsAFood_src\\AsAFood(包结构文档).xls");
su.setContentDisposition(null); // 设定contentDisposition为null以禁止浏览器自动打开文件,保证点击链接后是下载文件。若不设定,则下载的文件扩展名为doc时,浏览器将自动用word打开它。扩展名为pdf时,浏览器将用acrobat打开。
上传方式二:利用apache 的 commons-fileupload进行上传文件。
1.导入jar包,commons-fileupload-1.2.2.jar,commons-io-xxx.jar, form表单 添加 encType="multipart/form-data"
2.判断form表单是否 encType="multipart/form-data"
ServletFileUpload.isMultipartContent(request)
3.创建临时文件夹和要保存的文件夹,比如工程根目录下 temp和 upload
4.创建硬盘文件工厂类 DiskFileItemFactory factory = new DiskFileItemFactory();
5.指定上传文件的临时目录 factory.setRepository(new java.io.File(tem));
6.指定在内存中缓存数据大小,以byte为单位 factory.setSizeThreshold(1024*1024*1);
7.创建文件上传类 ServletFileUpload upload = new ServletFileUpload(factory);
8.设置单个上传文件的最大长度 upload.setFileSizeMax(1024*1024*150);
9.设置上传多个文件的总长度 upload.setSizeMax(1024*1024*200);
10.获取到form表单中的元素 List<FileItem> list = upload.parseRequest(request);
11.判断FileItem的类型,file.isFormField() true:表示普通类型,false 为上传文件类型
file.getName() 获取文件名,
file.getSize() 获取文件大小
12.写入目标文件, file.write(target);
文件上传具体实现
1,JSP页面
<center> <h1>文件上传</h1> <form name="uploadform"method="post" action="adddata" ENCTYPE="multipart/form-data"> <table border="1"width="450"cellpadding="4" cellspacing="2"bordercolor="#9BD7FF"> <tr><td width="100%"colspan="2"> 文件:<input name="file1"size="40"type="file"> </td></tr> </table> <table> <tr><td align="center"><input name="upload" type="submit"value="上传"/></td></tr> </table> </form> </center>
实现文件上传,在form标签内必须包含 ENCTYPE="multipart/form-data" 才可以实现(RFC1867协议:http://www.faqs.org/rfcs/rfc1867.html),且必须以 POST 方式上传。
2,web.xml 配置
<servlet> <servlet-name>AddDataServlet</servlet-name> <servlet-class>kxjh.AddDataServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AddDataServlet</servlet-name> <url-pattern>/adddata</url-pattern> </servlet-mapping>
3,Servelt 实现(commons-fileupload-1.2.1、commons-io-1.4)
// 解析 request,判断是否有上传文件 boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { // 创建磁盘工厂,利用构造器实现内存数据储存量和临时储存路径 DiskFileItemFactory factory = new DiskFileItemFactory(1024 * 4, new File("D:\\Temp")); // 设置最多只允许在内存中存储的数据,单位:字节 // factory.setSizeThreshold(4096); // 设置文件临时存储路径 // factory.setRepository(new File("D:\\Temp")); // 产生一新的文件上传处理程式 ServletFileUpload upload = new ServletFileUpload(factory); // 设置路径、文件名的字符集 upload.setHeaderEncoding("UTF-8"); // 设置允许用户上传文件大小,单位:字节 upload.setSizeMax(1024 * 1024 * 100); // 解析请求,开始读取数据 // Iterator<FileItem> iter = (Iterator<FileItem>) upload.getItemIterator(request); // 得到所有的表单域,它们目前都被当作FileItem List<FileItem> fileItems = upload.parseRequest(request); // 依次处理请求 Iterator<FileItem> iter = fileItems.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField()) { // 如果item是正常的表单域 String name = item.getFieldName(); String value = item.getString("UTF-8"); System.out.println("表单域名为:"+name+"表单域值为:"+value); } else { // 如果item是文件上传表单域 // 获得文件名及路径 String fileName = item.getName(); if (fileName != null) { // 如果文件存在则上传 File fullFile = new File(item.getName()); if (fullFile.exists()) { File fileOnServer = new File("D:\\My Documents\\" + fullFile.getName()); item.write(fileOnServer); System.out.println("文件" + fileOnServer.getName() + "上传成功"); } } } } }
利用ccommons-fileupload-1.2.1实现上传,其实现必须包含commons-io-1.4,以上为实现上传文件所使用的方法和所用到包的版本。
总结:以正常实现文件上传功能,在实现过程中如果form未配置 ENCTYPE="multipart/form-data" 元素,
则上传文件为本地的绝对路径,而非正常的文件。
详细使用参考api文档。