Java Web之Java Servlet学习笔记

Java Servlet组件
重点:了解Java Servlet组件的原理及编程;Java Servlet 的配置和生命周期。
概述:
  • Servlet的生命周期:创建servlet对象时,会调用init方法进行初始化;任何来自客户端的请求,都会调用service方法服务;当servlet销毁之前,会调用destory方法进行销毁
  • Servlet原理:Server服务器  let小型程序;运行在服务器端的小型程序,请求是以线程的方式访问目标Servlet,运行原理如下:
  1. 用户通过HTTP协议发送get请求,访问web容器
  2. web容器将http请求封装成Request对象,并创建了response对象
  3. 判断servlet是否被创建,如果没有,初始化目标Servlet
  4. 调用servlet的service方法,并将request和response当成参数传进去
  5. service会根据http请求的类型,自动调用doget/dopost方法
  6. 销毁request和response对象,并将数据通过http返回给用户
  •  request常用的方法:
  1. request.getMethod();获取请求类型
  2. request.getRemoteAddr();获取客户端IP
  3. request.getRequestURL();获取请求的url
  4. request.getRequestURI();获取请求的资源
  • response常用的方法:
  1. response.setCharactorEncoding("utf-8");设置编码
  2. 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>
2,使用注解的方式进行配置
    @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进行上传文件
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);  // 设定contentDispositionnull以禁止浏览器自动打开文件,保证点击链接后是下载文件。若不设定,则下载的文件扩展名为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文档。
 
posted @ 2017-12-10 22:32  jxtx92  阅读(363)  评论(0)    收藏  举报