Servlet——学习笔记

Servlet:server applet

  • 概念:运行在服务器端的小程序

    • Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则
    • 将来我们自定义一个类,实现Servlet接口,复写方法
  • 快速入门

    • 创建JavaEE项目,定义一个类实现Servlet接口,实现抽象方法,配置Servlet

    • 配置servlet

      <!--配置servlet-->
      <servlet>
          <servlet-name>demo1</servlet-name>
          <servlet-class>cn.ycl.servlet.ServletDemo1</servlet-class>
      </servlet>
      <servlet-mapping>
          <servlet-name>demo1</servlet-name>
          <url-pattern>/demo1</url-pattern>
      </servlet-mapping>
      
    • 执行原理

      • 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
      • 查找web.xml文件,是否有对应的标签体内容
      • 如果有,则在找到对应的全类名
      • tomcat会将字节码文件加载进内存,并且创建其对象
      • 调用其方法

Servlet中的生命周期方法

  1. 被创建:执行init方法,只执行一次

    • Servlet什么时候被创建?

      • 默认情况下,第一次被访问时,Servlet被创建

      • 可以配置执行Servlet的创建时机

        • 在标签下配置

          1. 第一次被访问时,创建
          	* <load-on-startup>的值为负数
          2. 在服务器启动时,创建
              * <load-on-startup>的值为0或正整数
          
    • Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的

      • 多个用户同时访问时,可能存在线程安全问题
      • 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值
  2. 提供服务:执行service方法,执行多次

    • 每次访问Servlet时,Service方法都会被调用一次。
  3. 被销毁:执行destroy方法,只执行一次

    • Servlet被销毁时执行。服务器关闭时,Servlet被销毁
    • 只有服务器正常关闭时,才会执行destroy方法
    • destroy方法在Servlet被销毁之前执行,一般用于释放资源

Servlet3.0:注解配置

  1. 好处:支持注解配置。可以不需要web.xml了
  2. 步骤:
    • 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
    • 定义一个类,实现Servlet接口
    • 复写方法
    • 在类上使用@WebServlet注解,进行配置
      • @WebServlet(“资源路径”)
  3. Servlet相关配置
    • urlpartten:Servlet访问路径
      • 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
      • 路径定义规则:
      • /xxx:路径匹配
      • /xxx/xxx:多层路径,目录结构
      • *.do:扩展名匹配

Servlet的体系结构

​ Servlet – 接口
​ |
​ GenericServlet – 抽象类
​ |
​ HttpServlet – 抽象类

  • GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
    • 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
  • HttpServlet:对http协议的一种封装,简化操作(推荐
    • 定义类继承HttpServlet
    • 复写doGet/doPost方法

ServletContext对象

  1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信

  2. 获取:

    1. 通过request对象获取

      request.getServletContext();

    2. 通过HttpServlet获取

      this.getServletContext();

  3. 功能:

    1. 获取MIME类型:在互联网通信过程中定义的一种文件数据类型

      • 格式: 大类型/小类型 text/html image/jpeg
      • 获取:String getMimeType(String file)
    2. 域对象:共享数据

      1. setAttribute(String name,Object value)
      2. getAttribute(String name)
      3. removeAttribute(String name)
      • ServletContext对象范围:所有用户所有请求的数据
    3. 获取文件的真实(服务器)路径

      • 方法:String getRealPath(String path)
      String b = context.getRealPath("/b.txt");//web目录下资源访问
      System.out.println(b);
      
      String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
      System.out.println(c);
      
      String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
      System.out.println(a);
      

案例

文件下载需求:

  1. 页面显示超链接
  2. 点击超链接后弹出下载提示框
  3. 完成图片文件下载

步骤:

  1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename

  2. 定义Servlet

    1. 获取文件名称

    2. 使用字节输入流加载文件进内存

    3. 指定response的响应头:

      content-disposition:attachment;filename=xxx

    4. 将数据写出到response输出流

  3. 中文文件问题

    解决思路:

    1. 获取客户端使用的浏览器版本信息
    2. 根据不同的版本信息,设置filename的编码方式不同
  4. 代码实现

@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //1.获取请求参数,文件名称
        String filename = req.getParameter("filename");
        System.out.println(filename);
        //2.使用字节输入流加载文件进内存
        //2.1找到文件服务器存储路径
        ServletContext servletContext = this.getServletContext();
        String realPath = servletContext.getRealPath("/img/" +filename);
        //2.2用字节流关联
        FileInputStream fis = new FileInputStream(realPath);
        //3.设置response的响应头
        //3.1设置响应头类型:content-type
        String mimeType = servletContext.getMimeType(filename);//获取文件的mine类型
        resp.setHeader("content-type",mimeType);
        //3.2设置响应头打开方式:content-disposition
        //解决中文文件名问题
        //1.获取user-agent
        String header = req.getHeader("user-agent");
        //2.使用工具类编码文件名
        filename = DownLoadUtils.getFileName(header, filename);
        resp.setHeader("content-disposition","attachment;filename="+filename);
        //4.将输入流的数据写到输出流中
        ServletOutputStream sos = resp.getOutputStream();
        byte[] buff = new byte[1024*8];
        int len = 0;
        while ((len = fis.read(buff)) != -1){
    
    
            sos.write(buff,0,len);
        }
        fis.close();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        this.doPost(req,resp);
    }
}
public class DownLoadUtils {
    
    

    public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
    
    
        if (agent.contains("MSIE")) {
    
    
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        } else if (agent.contains("Firefox")) {
    
    
            // 火狐浏览器
            BASE64Encoder base64Encoder = new BASE64Encoder();
            filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
        } else {
    
    
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45636641/article/details/108297479
今日推荐