JavaWeb学习笔记02 - Servlet,Cookie,Session

Servlet

Servlet是sun公司开发的处理动态web的技术

Servlet有两个默认的实现类:HttpServlet、GenericServlet

开发Servlet程序的步骤:

  1. 编写一个类,实现Servlet接口
  2. 把开发好的Java类部署到web服务器中

实现了Servlet接口的java程序称为Servlet

创建HelloServlet项目

  1. 构建一个普通的maven项目,删除src文件夹,这个空的工程作为maven主工程
  2. 引入servlet jsp依赖到pom.xml

    
      
      
        javax.servlet
        javax.servlet-api
        4.0.1
      
      
        javax.servlet.jsp
        javax.servlet.jsp-api
        2.3.3
      
    

    或手动下载jar包到文件夹中

    依赖下载地址:https://mvnrepository.com/

  3. 新建Module子模块servlet01(maven-archetype-webapp)

​ 父项目中的java子项目可以直接使用,反之不可以

​ 问题1:子项目pom中没有parent标签

​ 解决:在子项目的pom.xml中手动添加parent标签并刷新maven

  1. 
      cn.itxiaoma
      HelloMaven
      1.0-SNAPSHOT
    

    问题2:子项目pom文件有一条横线并变灰

    解决:file -->setting–>maven–>Ignored Files 将清单中对应项目的pom.xml文件取消选中

  2. 将servlet01中的web.xml改为最新,在main目录下新建java和resources

    
    
    
  3. 在java目录下新建package包cn..itxiaoma.servlet
  4. 在包下新建java类HelloServlet,并实现Servlet接口(继承HttpServlet)

    package cn.itxiaoma.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class HelloServlet extends HttpServlet {
        //get和post只是请求实现的不同方式,业务逻辑一样,因此可以互相调用
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            PrintWriter printWriter = resp.getWriter();
            printWriter.print("Hello Servlet");
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
  5. 编写Servlet的映射

    浏览器连接的是web服务,因此需要在web服务中注册我们写的Servlet,并配置浏览器能够访问的路径

    
    
      hello
      cn.itxiaoma.servlet.HelloServlet
    
    
    
      hello
      /hello
    
  6. 配置Tomcat

    Run > Edit Configurations > + > Tomcat Server - Local > Application server:选择Tomcat目录

    Deployment > + > servlet01:war exploed

    Application Context: /servlet01_war_exploded

  7. 启动测试

    http://localhost:8081/servlet...

    Servlet原理

  8. 浏览器发送http请求(service)到web容器(Tomcat)
  9. 首次访问的请求会加载Servlet类到内存
  10. web容器生成请求(Request)和响应(Response)两个对象,并调用Servlet的service方法
  11. Request会从service拿到请求,并执行我们重写的处理方法,得到响应信息传给Response
  12. web容器读取响应信息传回浏览器

    Servlet Mapping问题

    指定映射路径

    
      hello
      /hello
    

    多映射路径

    
      hello
      /hello/*
    

    默认请求路径(会覆盖首页)

    
      hello
      /*
    

    指定后缀/前缀

    
      hello
      *.test
    

    注:自定义后缀/前缀 * 前不能有映射路径

    自定义异常处理ErrorServlet

    cn/itxiaoma/servlet/ErrorServlet.java
    package cn.itxiaoma.servlet;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class ErrorServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         resp.setContentType("text/html");
         resp.setCharacterEncoding("utf-8");
         PrintWriter pw = resp.getWriter();
         pw.print("

    404

    "); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
    src/main/webapp/WEB-INF/web.xml
    
    
      
     hello
     cn.itxiaoma.servlet.HelloServlet
      
      
     hello
     /hello
      
    
      
     error
     cn.itxiaoma.servlet.ErrorServlet
      
      
     error
     /*
      
    

    优先级问题:制定了固有的映射路径优先级最高,找不到再走默认的映射

    ServletContext对象

    web容器在启动的时候,它会为每个web程序创建一个ServletContext对象,代表当前的web应用
    1. 共享数据
    在一个Servlet中保存的数据,可以在其他Servlet中获取

    web.xml

    
      get
      cn.itxiaoma.servlet.GetServlet
    
    
      get
      /get
    

    HelloServlet.java

    package cn.itxiaoma.servlet;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    public class HelloServlet extends HttpServlet {
     //get和post只是请求实现的不同方式,业务逻辑一样,因此可以互相调用
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         ServletContext context= this.getServletContext();
         String username = "Apple";
         context.setAttribute("username", username);
         System.out.println(username);
     }
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         doGet(req, resp);
     }
    }

    GetServlet.java

    package cn.itxiaoma.servlet;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class GetServlet extends HttpServlet {
     //get和post只是请求实现的不同方式,业务逻辑一样,因此可以互相调用
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         ServletContext context = this.getServletContext();
         PrintWriter printWriter = resp.getWriter();
         resp.setContentType("text/html");
         resp.setCharacterEncoding("utf-8");
         printWriter.print("Username:" + context.getAttribute("username"));
     }
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         doGet(req, resp);
     }
    }
    2. 获取初始化参数

    web.xml

    
      url
      jdbc:mysql://localhost:3306/testdb
    

    HelloServlet.java

    package cn.itxiaoma.servlet;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class HelloServlet extends HttpServlet {
     //get和post只是请求实现的不同方式,业务逻辑一样,因此可以互相调用
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         ServletContext context= this.getServletContext();
         String url = context.getInitParameter("url");
         resp.getWriter().print(url);
     }
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         doGet(req, resp);
     }
    }
    3. 请求转发
    ServletContext context= this.getServletContext();
    RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的请求路径
    requestDispatcher.forward(req, resp);
    4. 读取资源文件

    resources文件夹下新建db.properties(会打包到classes路径下,称为classpath)

    username=root
    password=123456

    读取资源文件

    ServletContext context= this.getServletContext();
    InputStream inputStream = context.getResourceAsStream("/WEB-INF/classes/db.properties");
    Properties properties = new Properties();
    properties.load(inputStream);
    String username = properties.getProperty("username");
    String password = properties.getProperty("password");
    resp.getWriter().print(username + password);

    HttpServletResponse

    web服务器接收到客户端的http请求,针对这个请求,分表创建一个代表请求的HttpServletRequest对象,和一个代表响应的HttpServletResponse对象

    javax/servlet/ServletResponse.java

    负责向浏览器发送数据的方法
    public ServletOutputStream getOutputStream() throws IOException;
    public PrintWriter getWriter() throws IOException;
    负责向浏览器发送响应头的方法
    public void setCharacterEncoding(String charset);
    public void setContentLength(int len);
    public void setContentLengthLong(long len);
    public void setContentType(String type);
    常见应用
  13. 向浏览器输出消息
  14. 下载文件

    1. 获取下载文件路径,文件名
    2. 获取下载文件的输入流
    3. 创建缓冲区
    4. 获取OutputStream对象
    5. 将FileOutputStream流写入Buffer缓冲区
    6. 使用OutputStream将缓冲区中的数据输出到客户端
    String realPath = "/Users/4wheels/Downloads/test.jpg";
    String filename = realPath.substring(realPath.lastIndexOf("/") + 1);
    resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
    //获取文件输入流
    FileInputStream inputStream = new FileInputStream(realPath);
    //缓冲区
    int len = 0;
    byte[] buffer = new byte[1024];
    ServletOutputStream servletOutputStream = resp.getOutputStream();
    while ((len = inputStream.read(buffer)) > 0) {
        servletOutputStream.write(buffer, 0, len);
    }
    inputStream.close();
    servletOutputStream.close();
  15. 验证码功能

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //浏览器3秒自动刷新
        resp.setHeader("refresh", "3");
        //在内存中创建图片
        BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        //绘制图片
        Graphics2D g = (Graphics2D) image.getGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, 80, 20);//绘制填色矩形
        g.setColor(Color.BLACK);
        g.setFont(new Font(null, Font.BOLD, 20));
        g.drawString(makeNum(), 2, 20);
        resp.setContentType("image/jpeg");
        resp.setDateHeader("expires", -1);//浏览器不缓存
        resp.setHeader("Cache-COntrol", "no-cache");
        resp.setHeader("Pragma", "no-cache");
        ImageIO.write(image, "jpg", resp.getOutputStream());
    }
    
    private String makeNum() {
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7 - num.length(); i++) {
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }
  16. 重定向

    resp.sendRedirect("/test");

    HttpServletRequest

    处理登录请求
    
    
    
    Username
    Password
    Hobby

    web.xml

    
    
      
     login
     cn.itxiaoma.servlet.LoginServlet
      
      
     login
     /login
      
    

    LoginServlet.java

    package cn.itxiaoma.servlet;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Arrays;
    public class LoginServlet extends HttpServlet {
     //get和post只是请求实现的不同方式,业务逻辑一样,因此可以互相调用
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         req.setCharacterEncoding("utf-8");
         resp.setCharacterEncoding("utf-8");
         String username = req.getParameter("username");
         String password = req.getParameter("password");
         String[] hobby = req.getParameterValues("hobby");
         System.out.println(username);
         System.out.println(password);
         System.out.println(Arrays.toString(hobby));
    //        req.getRequestDispatcher("/success.jsp").forward(req, resp);
     }
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         doGet(req, resp);
     }
    }

    Cookie

  17. cookie只能保存字符串,不能保存对象
  18. 一个cookie只能保存一个信息,最大4kb
  19. 一个web站点可以给浏览器发送多个cookie,一个站点最多20个
  20. 浏览器最多存300个左右cookie
  21. cookie不设置有效期或设为0,关闭浏览器自动失效

    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter printWriter = resp.getWriter();
    Cookie[] cookies = req.getCookies();
    if (cookies != null) {
     printWriter.print("Last Time:");
     for (int i = 0; i < cookies.length; i++) {
         Cookie cookie = cookies[i];
         if (cookie.getName().equals("lastLoginTime")) {
             long lastLoginTime = Long.parseLong(cookie.getValue());
             Date date = new Date(lastLoginTime);
             printWriter.write(date.toLocaleString());
         }
     }
    } else {
     printWriter.print("First Visit.");
    }
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
    resp.addCookie(cookie);

    Session

    服务器会给每个用户(浏览器)创建一个Session,只有浏览器没有关闭,session就存在

    Session和Cookie的区别:Cookie由客户端创建在浏览器保存,Session在服务器端创建和保存

    Session和ServletContext区别:ServletContext作用域是全局(Web应用),Session作用域是会话(浏览器)

    
      setSession
      cn.itxiaoma.servlet.SetSession
    
    
      setSession
      /set
    
    
      getSession
      cn.itxiaoma.servlet.GetSession
    
    
      getSession
      /get
    
    
      delSession
      cn.itxiaoma.servlet.DelSession
    
    
      delSession
      /del
    
    
    
      
      15
    

    SetSession.java

    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter printWriter = resp.getWriter();
    HttpSession session = req.getSession();
    session.setAttribute("name", "test");
    String sessionId = session.getId();
    if (session.isNew()) {
     printWriter.write("Session创建成功,Id:" + sessionId);
    } else {
     printWriter.write("Session已存在,Id:" + sessionId);
    }

    GetSession.java

    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter printWriter = resp.getWriter();
    HttpSession session = req.getSession();
    String sessionId = session.getId();
    String sessionName = (String) session.getAttribute("name");
    printWriter.write("Session Id:" + sessionId);
    printWriter.write("Session Name:" + sessionName);

    DelSession.java

    HttpSession session = req.getSession();
    //删除指定session
    session.removeAttribute("name");
    //手动注销session

你可能感兴趣的