zoukankan      html  css  js  c++  java
  • Http协议和Servlet

    1. http协议

    1. 什么是协议:双方再交互通信时候,遵守的一种规范,规则

    http协议:针对网络上的客户端和服务器端在执行http请求时遵守的一种规范,其实就是规定了客户端在访问服务器端和服务器返回数据时,需要带上什么东西。

    2. http协议版本:

    1.0版本:请求数据,服务器返回后,回断开连接

    通用1.1版本:请求数据,服务器返回后,连接会继续保持,除非服务器和客户端关闭。有一定的时间限制,如果一直空着连接,会自动关闭。

    在地址栏中键入网络地址,或者注册按钮,浏览器会显示一些内容,浏览器和服务器如何通讯呢。

    使用浏览器打开http://localhost:8082/examples/servlets/servlet/RequestParamExample

    3. http请求数据解析

    a. 请求行:

    POST:请求的方式
    /examples/servlets/servlet/RequestParamExample  请求的URL地址
    HTTP/1.1:协议的版本

    b. 请求头:

    Host: localhost:8082
    Connection: keep-alive
    Content-Length: 28
    Cache-Control: max-age=0
    Origin: http://localhost:8082
    Upgrade-Insecure-Requests: 1
    Content-Type: application/x-www-form-urlencoded
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Referer: http://localhost:8082/examples/servlets/servlet/RequestParamExample
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d

    Accept:客户端告诉服务端能支持什么类型的数据

    Referer:真正请求的全地址路径

    Accept-language:支持的语言格式

    User-Agent:向服务器表名,当前来访的客户端信息

    Content-Type:提交的数据类型,经过urlencoding编码的form表单数据

    Accept-Encoding:gzip,deflate:压缩算法

    Content-Length:数据长度

    Connection:Keep-Alilve 保持连接

    Cache-Control:对缓冲的操作

    c. 请求体:

    firstname=wang&lastname=jing

    浏览器真正发送给服务器的数据

    发送的数据时key=value的格式,如果存在多个数据,那么使用&

    http响应数据解析

    响应的数据里面包含三部分的内容:响应行,响应头,响应体

    HTTP/1.1 200
    Content-Type: text/html;charset=UTF-8
    Content-Length: 711
    Date: Wed, 17 Oct 2018 07:07:10 GMT

    响应行:HTTP/1.1 200  协议版本,状态码

    200:成功,正常处理,得到数据

    403:forbidden:拒绝

    404:Not Found

    500:服务器异常

    响应头

    Content-Type:服务器返回给客户端的内容类型

    Content-Lenght:返回的数据的长度

    Date:响应的时间

    4. Post和Get请求的数据的区别

    http://localhost:8082/examples/servlets/servlet/RequestParamExample?firstname=wang&lastname=jing可以得到Get请求

    Get:
    GET /examples/servlets/servlet/RequestParamExample?firstname=wang&lastname=jing HTTP/1.1
    Host: localhost:8082
    Connection: keep-alive
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d
    
    Post:
    POST /examples/servlets/servlet/RequestParamExample HTTP/1.1
    Host: localhost:8082
    Connection: keep-alive
    Content-Length: 28
    Cache-Control: max-age=0
    Origin: http://localhost:8082
    Upgrade-Insecure-Requests: 1
    Content-Type: application/x-www-form-urlencoded
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Referer: http://localhost:8082/examples/servlets/servlet/RequestParamExample
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d

    a. 请求的地址不同

    b. 带的数据不同

    Post采用流的方式携带数据

     5. Web资源

    在http协议当中,规定了请求和响应双方,客户端和服务器端,与web相关的资源有两类:

    静态资源:html,js,css

    动态资源:servlet/jsp

    2. Servlet

    servlet:一个java程序,运行在web服务器上面,用于接收和响应,客户端的http请求

    更多的是配合动态资源来做,当然静态资源也需要使用Servlet,不过是Tomcat里面已经定义好了一个DefaultServlet

    1. 定义一个Hello Servlet工程

    a. 新建一个工程,配置服务器

    b. 测试运行Web工程

      新建一个类,实现Servlet接口

      配置Servlet:告诉服务器,我们的应用有这些Servlet,配置文件webContent/WEB-INF/web.xml

      <!-- 向tomcat报告,这个应用中有此servlet,名称为HelloServlet,全路径 /HelloServlet/src/-->
      <servlet>
          <servlet-name>HelloServlet</servlet-name>
          <servlet-class>day_01.HelloServlet</servlet-class>
      </servlet>
      
      <!-- 注册servlet的映射,servletName:找到上面注册的具体的servlet,url-pattern:地址栏中的路径  -->
      <servlet-mapping>
          <servlet-name>HelloServlet</servlet-name>
          <url-pattern>/hello</url-pattern>
      </servlet-mapping>

    使用http://localhost:8082/HelloServlet/hello访问该java类

    执行过程:

    1. 找到tomcat应用

    2. 找到项目

    3. 找web.xml,然后在里面找到url-pattern,有没有哪一个pattern的内容是hello

    4. 找到servlet-mapping中的哪个servlet-name

    5. 找到上面定义的Servlet元素中的servlet-name中的HelloServlet

    6. 找到下面定义的Servlet-class然后开始创建该类的实例

    7. 继而执行该Servlet的service方法

    2. Servlet的通用写法

    servlet(接口)------>GenericServlet-------->HttpServlet(用于处理Http的请求)

    定义一个类,继承HttpServlet复写doGet和doPost

    public class HelloServlet02 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("get...");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("post");
        }
    }

    3. Servlet的生命周期

    生命周期:从创建到销毁的时间

    生命周期方法:从创建到销毁,所调用的方法

    public class HelloServlet03 implements Servlet {
        // 创建servlet实例时,调用该方法,初次使用servlet,创建实例,init()方法只能执行一次
        @Override
        public void init(ServletConfig config) throws ServletException {
            System.out.println("HelloServlet03...init...");
        }
    
        // 客户端来一个请求,执行一次该方法
        @Override
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            System.out.println("HelloServlet03...service...");
        }
    
        // 该项目从tomcat里面移除,正常关闭服务器,shutdown.bat
        @Override
        public void destroy() {
            System.out.println("HelloServlet03...destroy...");
        }
    
        @Override
        public ServletConfig getServletConfig() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public String getServletInfo() {
            // TODO Auto-generated method stub
            return null;
        }
    
    }

     4. 让servlet创建实例的时机提前

    a. 默认情况下,只有在初次访问servlet时候,才会执行init方法,有时候,可能需要在这个方法中执行一些初始化工作,甚至时做一些比较耗时的逻辑

    b. 这个时候,初次访问,可能会在Init方法中逗留太久的时间,那么有没有办法让时间提前一些呢。

      <servlet>
          <servlet-name>HelloServlet04</servlet-name>
          <servlet-class>day_01.HelloServlet04</servlet-class>
          
          <load-on-startup>2</load-on-startup>    //值越小越提前执行
      </servlet>

    服务器重启或者部署项目时就会执行

    c. 配置时候,使用load-on-startup来执行,给的数字越小,启动的时机越早,一般不写负数,从2开始即可

    5. servletConfig

    servletConfig使用方法

    package day_01;
    
    import java.io.IOException;
    import java.util.Enumeration;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class HelloServletConfig extends HttpServlet{
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // ServletConfig:可以获得servlet在配置时的一些信息
            ServletConfig config = getServletConfig();
            
            // 获取配置servlet里面servlet-name的文本内容
            String servletName = config.getServletName();
            System.out.println("servletname:" + servletName);
            
            // 获取配置时具体的参数
            String initParameter = config.getInitParameter("address");
            System.out.println("initparameter:" + initParameter);
            
            System.out.println("-----------");
            
            // 获取所有的名称
            Enumeration<String> names = config.getInitParameterNames();
            while (names.hasMoreElements()){
                String name = (String)names.nextElement();
                String initpara = config.getInitParameter(name);
                System.out.println(name + ":" + initpara);
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
        
    }
    
    
      <servlet>
          <servlet-name>HelloServletConfig</servlet-name>
          <servlet-class>day_01.HelloServletConfig</servlet-class>
          <!-- 可以添加初始化参数 -->
          <init-param>
              <param-name>name</param-name>
              <param-value>Feng_Ying</param-value>
          </init-param>
          
          <init-param>
              <param-name>age</param-name>
              <param-value>20</param-value>
          </init-param>
          
          <init-param>
              <param-name>address</param-name>
              <param-value>Beijing_University</param-value>
          </init-param>
          
      </servlet>
      
      <servlet-mapping>
          <servlet-name>HelloServletConfig</servlet-name>
          <url-pattern>/hello5</url-pattern>
      </servlet-mapping>

    1. 未来我们开发了一些应用,使用到了一些技术,或者一些代码,但是我们不会,但是有人写出来了,它的代码放置在servlet类里面

    2. 刚好这个servlet里面有一个数字或者变量,但是不是固定的,所以要求使用到servlet时,注册servlet时候,必须要在web.xml,声明init-params

    servlet的配置方式

    1. 全路径匹配:/a/b

    2. 路径匹配:以/开始,但是以*结束,/a/*,/*是任意匹配,*是一个通配符

    3. 以扩展名匹配,没有/:*.扩展名,*的内容可以是任意的

    6. ServletContext

    Servlet上下文:每个web工程都只有一个ServletContext对象,不管在那个servlet里面,获取到的这个类的对象都是同一个

    1. 可以获取全局配置参数

      <!-- 可以配置全局的参数 -->
      <context-param>
          <param-name>address</param-name>
          <param-value>深圳东莞</param-value>
      </context-param>
      
      <servlet>
          <servlet-name>ServletContextDemo</servlet-name>
          <servlet-class>day_01.ServletContextDemo</servlet-class>
      </servlet>

    所有的servlet对象都可以用全局变量

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1. 获取ServletContext对象
            ServletContext context = getServletContext();
            String address = context.getInitParameter("address");
            System.out.println("address:" + address);
        }

    2. 可以获取web应用中的资源

    package day_01;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletContextDemo2 extends HttpServlet{
        private static final long serialVersionUID = 1L;
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Properties prop = new Properties();
    //        InputStream is = ServletContextDemo2.class.getClassLoader().getResourceAsStream("config.properties");
            ServletContext context = getServletContext();
            // 获取给定文件在服务器上的绝对路径
            String path = context.getRealPath("/CONFIG/config.properties");
            System.out.println(path);
            InputStream is = new FileInputStream(path);
            prop.load(is);
            String address = prop.getProperty("address");
            System.out.println("address:" + address);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }

    输出:

    D:Wang_Filemyeclipse_workspace.metadata.me_tcat85webappsHelloServletCONFIGconfig.properties
    address:shengzhengdongguan

    另一种更加简洁的方法

    private void method_other(){
            try {
                Properties prop = new Properties();
                //        InputStream is = ServletContextDemo2.class.getClassLoader().getResourceAsStream("config.properties");
                ServletContext context = getServletContext();
                // 获取给定文件在服务器上的绝对路径,获取web工程下的资源,转换成流对象
                InputStream is = context.getResourceAsStream("CONFIG/config.properties");
                prop.load(is);
                String address = prop.getProperty("address");
                System.out.println("address:" + address);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    第三种方法:通过classLoader获取资源文件:默认的getClassLoader()路径:D:Wang_Filemyeclipse_workspace.metadata.me_tcat85webappsHelloServletWEB-INFclasses

    目标目录:D:Wang_Filemyeclipse_workspace.metadata.me_tcat85webappsHelloServletCONFIG

        private void method_another(){
            try {
                Properties prop = new Properties();
                InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../CONFIG/config.properties");
                // 获取给定文件在服务器上的绝对路径
                prop.load(is);
                String address = prop.getProperty("address");
                System.out.println("address:" + address);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    3. 存取数据:servlet间共享数据,域对象

    a. 定义一个登陆的html页面,定义一个form表单

    b. 定义一个Servlet,名为LoginServlet

    c. 针对成功和失败,跳转到不同的页面

    package com.wang.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class LoginServlet
     */
    @WebServlet("/LoginServlet")
    // localhost/HelloServlet/LoginServlet
    public class LoginServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
        
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 设置请求体里面的编码,这句话对于post没有作用,应为get数据在url上面
            request.setCharacterEncoding("UTF-8");
            String username = request.getParameter("username");
            // 本处不需要解码,应该是版本比较高tomcat-8.5
            // 常用的解码形式:username = new String(username.getBytes("ISO-8859", "UTF-8"))
            String password = request.getParameter("password");
            System.out.println("username:" + username + ",password:" + password);
        
            PrintWriter pw = response.getWriter();
            if("风影".equals(username) && "wang".equals(password)){
                Object obj = getServletContext().getAttribute("count");;
                int totalCount = 0;
                
                if(obj != null){
                    totalCount = (int)obj;
                }
                getServletContext().setAttribute("count", totalCount + 1);
                System.out.println("登陆成功的次数:" + (totalCount + 1));
                // 用户名密码校验成功登陆  设置状态码,重新定位
                response.setStatus(302);
                // 定位跳转的位置是哪一个页面
                response.setHeader("Location", "success.html");
            }else{
                pw.write("login fail...");
            }
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    package com.wang.servlet;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class CountServlet
     */
    @WebServlet("/CountServlet")
    public class CountServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            int count = (int)getServletContext().getAttribute("count");
            response.getWriter().write("当前网站成功登陆:" + count + "次");
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    <!DOCTYPE html>
    <!-- -http://localhost:8082/HelloServlet/login.html -->
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Login</title>
        </head>
        <body>
            <h2>请输入以下的内容,完成登陆</h2>
        
            <form action = "LoginServlet" method = "post">
                账号:<input type="text" name="username" /><br> 
                密码:<input type="text" name="password" /><br> 
                <input type="submit" value="登陆" />
            </form>
        </body>
    </html>
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>success</title>
        </head>
        <body>
            Login successful...    <br/>
            <a href = "CountServlet">网站登陆成功的次数</a>
        </body>
    </html>

    ServletContext何时创建,何时销毁

    服务器启动的时候,会为每个web应用程序,创建一个ServletContext,当服务器关闭或者从服务器移除托管,会销毁

    ServletContext的作用范围:本项目中都可以使用

    7. HttpServletRequest

    这个对象封装了客户端提交过来的所有信息

    1. 可以获取客户端请求的头信息

    Enumeration<String> headerNames = request.getHeaderNames();
    while(headerNames.hasMoreElements()){
        String name = (String)headerNames.nextElement();
        String value = request.getHeader(name);
        System.out.println(name + ":" + value);
    }
    
    host:localhost:8082
    connection:keep-alive
    upgrade-insecure-requests:1
    user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
    accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    accept-encoding:gzip, deflate, br
    accept-language:zh-CN,zh;q=0.9
    cookie:pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d

    2. 获取客户端提交过来的数据

    // 获取客户端提交的数据 或者Enumeration<String> parameterNames =
    // request.getParameterNames();
    String name = request.getParameter("name");
    System.out.println("name:" + name);
    
    // 获取所有的数据,一个Key可以对应多个数据
    Map<String, String[]> map = request.getParameterMap();
    Set<String> keySet = map.keySet();
    Iterator<String> iterator = keySet.iterator();
    while (iterator.hasNext()) {
        String key = iterator.next();
        String[] value = map.get(key);
        System.out.println("key:" + key + ",value:" + Arrays.deepToString(value));
    }
    
    name:wangjing
    key:name,value:[wangjing, hage]

    3. 读取中文数据

    Myeclipse get读取的中文不存在中文乱码问题,应该是使用的tomcat-8.5版本比较高:

    如果存在,get方式获取数据存在两种解决方法

    1. 代码转码

    String username = request.getParameter("username");
    // 常用的解码形式:get请求过来的数据,在url地址栏经过编码了,所以取到的数据是乱码,tomacat收到这批数据,getParameter,默认使用IOS-8859-1去解码
    username = new String(username.getBytes("ISO-8859", "UTF-8"))
    String password = request.getParameter("password");
    System.out.println("username:" + username + ",password:" + password);

    2. 在tomcat里面conf/server.xml加上URIEncoding="UTF-8"

    <connector connectionTimeout="2000" prot = "8082" protocol = "HTTP/1.1" redirectPort="8445" URIEncoding="UTF-8" />

    但是post请求会出现乱码问题,怎么解决呢

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");// 设置请求体里面的编码,这句话对于get没有作用,应为get数据在url上面
        String username = request.getParameter("username");
        // 本处不需要解码,应该是版本比较高tomcat-8.5
        // 常用的解码形式:username = new String(username.getBytes("ISO-8859", "UTF-8"))
        String password = request.getParameter("password");
        System.out.println("username:" + username + ",password:" + password);
    
        PrintWriter pw = response.getWriter();
        if("风影".equals(username) && "wang".equals(password)){
            Object obj = getServletContext().getAttribute("count");;
            int totalCount = 0;
            
            if(obj != null){
                totalCount = (int)obj;
            }
            getServletContext().setAttribute("count", totalCount + 1);
            System.out.println("登陆成功的次数:" + (totalCount + 1));
            // 用户名密码校验成功登陆  设置状态码,重新定位
            response.setStatus(302);
            // 定位跳转的位置是哪一个页面
            response.setHeader("Location", "success.html");
        }else{
            pw.write("login fail...");
        }
    }

     8. HttpServletResponse

    负责返回数据给客户端,输出数据到页面上

    // 以字符串方式写数据,文字信息
    // response.getWriter().write("hello response");
    // 以字节流的方式写数据,文字信息,文件信息
    response.getOutputStream().write("Hello Response".getBytes());

    响应的数据中有可能出现乱码package com.wang.servlet;import java.io.IOException;import java.nio.charset.Chars 

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class ResponseDemo1
     */
    @WebServlet("/ResponseDemo1")
    public class ResponseDemo1 extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1. 字符流输出
            // response.getWriter().write("hello response");
            // 2. 字节流输出
            // response.getOutputStream().write("Hello Response".getBytes());
            // 设置响应头
            // response.setHeader(name, value);
            // 设置状态码
            // response.setStatus("");
            // 
            // response.setContentType(type);
            
            // CharacterOutput(response);
            ByteOutput(response);
        }
    
        private void CharacterOutput(HttpServletResponse response) throws IOException {
            /*
             * 中文乱码问题
             */
            // 字符流方法
            // 1. 设置编码时使用utf-8编码
            response.setCharacterEncoding("UTF-8");
            // 2. 指定浏览器查看这份数据使用的码表
            response.setHeader("Content-Type", "text/html;charset=UTF-8");
            
            response.getWriter().write("我爱java");
        }
        
        private void ByteOutput(HttpServletResponse response) throws IOException {
            /*
             * 中文乱码问题
             */
            // 字节流方法// 1. 指定浏览器查看这份数据使用的码表,以后不管是字节流还是字符流,写如下一句即可
            response.setContentType("text/html;charset=UTF-8");

    // response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "text/html;charset=UTF-8"); 同上 // 2. 指定输出的中文使用的码表 response.getOutputStream().write("我爱java".getBytes()); // 默认是utf-8 // String csn = Charset.defaultCharset().name(); UTF-8 } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

     9. Tomcat下载资源

    1. 直接以超链接形式,不写任何代码,也可以下载文件

    <body>
        让tomcat的默认servlet提供下载功能<br />
        <a href = "download/aa.jpg">aa.jpg</a><br />
        <a href = "download/bb.txt">bb.jpg</a><br />
        <a href = "download/cc.rar">cc.jpg</a><br />
    </body>

    原因时tomcat里面有一个默认的servlet,DefaultServlet,这个DefaultServlet专门用于处理放在tomcat服务器上面的静态资源

    2. 采用自定义tomcat方式

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>index</title>
        </head>
        <body>
            让tomcat的默认servlet提供下载功能<br />
            <a href = "download/aa.jpg">aa.jpg</a><br />
            <a href = "download/bb.txt">bb.txt</a><br />
            <a href = "download/cc.rar">cc.rar</a><br />
            手动编码提供下载功能:<br>
            <a href = "DownloadServlet?filename=aa.jpg">aa.jpg</a><br />
            <a href = "DownloadServlet?filename=bb.txt">bb.txt</a><br />
            <a href = "DownloadServlet?filename=cc.rar">cc.rar</a><br />
        </body>
    </html>
    package com.wang.servlet;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    @WebServlet("/DownloadServlet")
    public class DownloadServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1. 获取下载文件的名字
            String fileName = request.getParameter("filename");
            // 2. 获取这个文件在tomcat里面的绝对路径地址
            String path = getServletContext().getRealPath("download/" + fileName);
            // 3. 设置浏览器收到这种资源,采用下载的方式打开
            response.setHeader("Content-Disposition", "attachment; filename ="+fileName);
            // 4. 转换成输入流
            InputStream is = new FileInputStream(path);
            OutputStream os = response.getOutputStream();
            // 5. 流转换
            int len = 0;
            byte[] buffer = new byte[1024];
            while((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
            os.close();
            is.close();
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }

     下载过程中出现的中文文件名乱码问题解决方案:

    package com.wang.servlet;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URLEncoder;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    @WebServlet("/DownloadServlet")
    public class DownloadServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1. 获取下载文件的名字
            String fileName = request.getParameter("filename");
            // 2. 获取这个文件在tomcat里面的绝对路径地址
            String path = getServletContext().getRealPath("download/" + fileName);
            /*
             * filename = new String(fileName.getBytes("ISO-8859-1"),"UTF-8");
             */
            // 3. 如果文件的名字带有中文,那么需要对这个文件进行编码处理,如果是IE,Chrome使用URLEncoding编码
            // 如果是Firefox,使用Base64编码
            String clientType = request.getHeader("User-Agent");
            if(clientType.contains("Firefox")){
                fileName = DownloadUtil.base64EncodeFileName(fileName);
            }else{
                fileName = URLEncoder.encode(fileName, "UTF-8");
            }
            // 4. 设置浏览器收到这种资源,采用下载的方式打开
            response.setHeader("Content-Disposition", "attachment; filename ="+fileName);
            // 5. 转换成输入流
            InputStream is = new FileInputStream(path);
            OutputStream os = response.getOutputStream();
            // 6. 流转换
            int len = 0;
            byte[] buffer = new byte[1024];
            while((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
            os.close();
            is.close();
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    
    package com.wang.servlet;
    
    import java.io.UnsupportedEncodingException;
    import sun.misc.BASE64Encoder;
    
    public class DownloadUtil {
        public static String base64EncodeFileName(String fileName) {
            BASE64Encoder base64Encoder = new BASE64Encoder();
            try {
                return "=?UTF-8?B?"
                        + new String(base64Encoder.encode(fileName
                                .getBytes("UTF-8"))) + "?=";
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }

     10. 请求转发和重定向

    重定向:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if("admin".equals(username) && "admin".equals(password)){
            /*response.setStatus(302);
            response.setHeader("Location", "success.html");*/
            // 上面时以前的写法,重定向写法:
            response.sendRedirect("servlet/success.html");
        }else{
            /*response.setStatus(302);
            response.setHeader("Location", "fail.html");*/
        }
    }

    请求转发

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if("admin".equals(username) && "admin".equals(password)){
            /*response.setStatus(302);
            response.setHeader("Location", "success.html");*/
            
            // 上面时以前的写法,重定向写法:
            //response.sendRedirect("servlet/success.html");
            
            // 请求转发的写法
            request.getRequestDispatcher("servlet/success.html").forward(request, response);
        }else{
            /*response.setStatus(302);
            response.setHeader("Location", "fail.html");*/
        }
    }

    请求转发和重定向的不同点:

    1. 重定向显示的是最后的那个资源的路径地址    http://localhost:8082/HelloServlet/servlet/success.html

    请求的次数至少有两次,服务器在第一次请求后,会返回302以及一个地址,浏览器会根据这个地址进行第二次访问

    可以跳转到任意的路径,不是自己的工程也可以

    效率稍微低一点,需要执行两次请求

    后续的请求,没法使用上一次request存储的数据,或者,没有办法使用上一次的request对象,因为这是两次不同的请求

    2. 请求转发显示的是请求servlet的地址   http://localhost:8082/HelloServlet/Login?username=admin&password=admin

    请求次数只有一次,因为服务器内部帮助客户端执行了后续的工作

    只能跳转自己项目的项目路径

    效率稍微高一点,执行一次请求

    可以使用上一次的request对象

     11. Cookie

    一份小数据,是服务器给客户端,并且存储在客户端上的小数据

    应用场景:自动登陆,浏览记录,购物车

    cookie出现的原因:

    http的请求是无状态的,客户端与服务器通讯时候是无状态的,客户端在第二次访问服务器时候,是根本不知道这个客户端是以前来访过的。为了更好的收集用户习惯,更好的用户体验和交互。

    cookie的简单使用

    1. 在响应的时候,添加cookie

    2. 客户端接收到信息的界面,响应头多了一个字段set-cookie

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("wangjing", "2015141452156");
        response.setContentType("text/html;charset=UTF-8");
        // 给响应添加一个cookie
        response.addCookie(cookie);
        response.getWriter().write("请求成功");
    }

     对于客户端的一个网址,访问一次后cookie便会记录下来

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("wangjing", "2015141452156");
        response.setContentType("text/html;charset=UTF-8");
        // 给响应添加一个cookie
    //        response.addCookie(cookie);
        response.getWriter().write("请求成功");
        // 获取客户端返回的cookie
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for(Cookie c : cookies){
                String cookieName = c.getName();
                String cookieValue = c.getValue();
                System.out.println("cookieName:" + cookieName + ",cookieValue:" + cookieValue);
            }
        }
    }

     常用的方法:

    案例1:显示最近一次访问的时间

    1. 判断账号是否正确,如果正确,则获取cookie,但是得到的cookie是一个数组,要从数组中找到我们想要的对象

    2. 如果找到的对象为空,表明第一次登陆,需要添加cookie

    3. 如果找到的对象不为空,表明不是第一次登陆,如果更新cookie

    package com.wang.cookie;
    
    import java.io.IOException;
    import java.util.Date;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/LoginServlet_cookie")
    public class LoginServlet_cookie extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            response.setContentType("text/html;charset=UTF-8");
            if("admin".equals(username) && "admin".equals(password)){
                Cookie[] cookies = request.getCookies();
                Cookie cookie = CookieUtil.findCookie(cookies, "last");
                if(cookie == null){
                    Cookie c = new Cookie("last", System.currentTimeMillis()+"");
                    c.setMaxAge(60*60*3);
                    response.addCookie(c);
                    response.getWriter().write("欢迎您" + username);
                }else{
                    long lastVisitTime = Long.parseLong(cookie.getValue());
                    response.getWriter().write("欢迎您" + username + ",上次来访时间:" + new Date(lastVisitTime));
                    cookie.setValue(System.currentTimeMillis() + "");
                    response.addCookie(cookie);
                }
            }else{
                response.getWriter().write("登陆失败");
            }
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    package com.wang.cookie;
    import javax.servlet.http.Cookie;
    
    public class CookieUtil {
        public static Cookie findCookie(Cookie[] cookies, String name){
            if(cookies != null){
                for(Cookie cookie :cookies){
                    if(name.equals(cookie.getName())){
                        return cookie;
                    }
                }
            }
            return null;
        }
    }

    案例2:显示商品的浏览记录

    jsp:java server pager 最终会翻译成一个类,就是一个servlet

    定义全局变量:<%! int a = 0; %>

    定义局部变量:<% int b = 99; %>

    在jsp页面上,显示a和b的值

    <% =a %>

    <% =b %>

    <%@ page language = "java" contentType = "text/html;charset=UTF-8" pageEncoding="UTF-8" %>
    <html>
    
        <head>
            <meta charset="utf-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>会员登录</title>
            <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
            <script src="js/jquery-1.11.3.min.js" type="text/javascript"></script>
            <script src="js/bootstrap.min.js" type="text/javascript"></script>
            <!-- 引入自定义css文件 style.css -->
            <link rel="stylesheet" href="css/style.css" type="text/css" />
    
            <style>
                body {
                    margin-top: 20px;
                    margin: 0 auto;
                    width: 100%;
                }
                .carousel-inner .item img {
                    width: 100%;
                    height: 300px;
                }
            </style>
        </head>
    
        <body>
            
                <!--
                    时间:2015-12-30
                    描述:菜单栏
                -->
                <div class="container-fluid">
                    <div class="col-md-4">
                        <img src="img/logo2.png" />
                    </div>
                    <div class="col-md-5">
                        <img src="img/header.png" />
                    </div>
                    <div class="col-md-3" style="padding-top:20px">
                        <ol class="list-inline">
                            <li><a href="login.htm">登录</a></li>
                            <li><a href="register.htm">注册</a></li>
                            <li><a href="cart.htm">购物车</a></li>
                        </ol>
                    </div>
                </div>
                <!--
                    时间:2015-12-30
                    描述:导航条
                -->
                <div class="container-fluid">
                    <nav class="navbar navbar-inverse">
                        <div class="container-fluid">
                            <!-- Brand and toggle get grouped for better mobile display -->
                            <div class="navbar-header">
                                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                                    <span class="sr-only">Toggle navigation</span>
                                    <span class="icon-bar"></span>
                                    <span class="icon-bar"></span>
                                    <span class="icon-bar"></span>
                                </button>
                                <a class="navbar-brand" href="#">首页</a>
                            </div>
    
                            <!-- Collect the nav links, forms, and other content for toggling -->
                            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                                <ul class="nav navbar-nav">
                                    <li class="active"><a href="#">手机数码<span class="sr-only">(current)</span></a></li>
                                    <li><a href="#">电脑办公</a></li>
                                    <li><a href="#">电脑办公</a></li>
                                    <li><a href="#">电脑办公</a></li>
                                </ul>
                                <form class="navbar-form navbar-right" role="search">
                                    <div class="form-group">
                                        <input type="text" class="form-control" placeholder="Search">
                                    </div>
                                    <button type="submit" class="btn btn-default">Submit</button>
                                </form>
    
                            </div>
                            <!-- /.navbar-collapse -->
                        </div>
                        <!-- /.container-fluid -->
                    </nav>
                </div>
    
    
            <div class="row" style="1210px;margin:0 auto;">
                <div class="col-md-12">
                    <ol class="breadcrumb">
                        <li><a href="#">首页</a></li>
                    </ol>
                </div>
    
                <div class="col-md-2">
                    <a href="ProductInfoServlet?id=1">
                        <img src="products/1/cs10001.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>冬瓜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
    
                <div class="col-md-2">
                    <a href="ProductInfoServlet?id=2">
                        <img src="products/1/cs10002.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>圆白菜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
    
                <div class="col-md-2">
                    <a href="ProductInfoServlet?id=3">
                        <img src="products/1/cs10003.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>甜玉米</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
    
                <div class="col-md-2">
                    <a href="ProductInfoServlet?id=4">
                        <img src="products/1/cs10004.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>胡萝卜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
                <div class="col-md-2">
                    <a href="ProductInfoServlet?id=5">
                        <img src="products/1/cs10005.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>芹菜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
                <div class="col-md-2">
                    <a href="ProductInfoServlet?id=6">
                        <img src="products/1/cs10006.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>韭菜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
    
                <div class="col-md-2">
                    <a href="product_info.htm">
                        <img src="products/1/cs10007.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>香菜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
                <div class="col-md-2">
                    <a href="product_info.htm">
                        <img src="products/1/cs10008.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>土豆</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
                <div class="col-md-2">
                    <a href="product_info.htm">
                        <img src="products/1/cs10007.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>香菜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
                <div class="col-md-2">
                    <a href="product_info.htm">
                        <img src="products/1/cs10008.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>土豆</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
                <div class="col-md-2">
                    <a href="product_info.htm">
                        <img src="products/1/cs10007.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>香菜</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
                <div class="col-md-2">
                    <a href="product_info.htm">
                        <img src="products/1/cs10008.jpg" width="170" height="170" style="display: inline-block;">
                    </a>
                    <p><a href="product_info.html" style='color:green'>土豆</a></p>
                    <p><font color="#FF0000">商城价:&yen;299.00</font></p>
                </div>
    
            </div>
    
            <!--分页 -->
            <div style="380px;margin:0 auto;margin-top:50px;">
                <ul class="pagination" style="text-align:center; margin-top:10px;">
                    <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
                    <li class="active"><a href="#">1</a></li>
                    <li><a href="#">2</a></li>
                    <li><a href="#">3</a></li>
                    <li><a href="#">4</a></li>
                    <li><a href="#">5</a></li>
                    <li><a href="#">6</a></li>
                    <li><a href="#">7</a></li>
                    <li><a href="#">8</a></li>
                    <li><a href="#">9</a></li>
                    <li>
                        <a href="#" aria-label="Next">
                            <span aria-hidden="true">&raquo;</span>
                        </a>
                    </li>
                </ul>
            </div>
            <!-- 分页结束=======================        -->
    
            <!--
                   商品浏览记录:
            -->
            <div style="1210px;margin:0 auto; padding: 0 9px;border: 1px solid #ddd;border-top: 2px solid #999;height: 246px;">
    
                <h4 style=" 50%;float: left;font: 14px/30px " 微软雅黑 ";">浏览记录</h4>
                <div style=" 50%;float: right;text-align: right;"><a href="">more</a></div>
                <div style="clear: both;"></div>
    
                <div style="overflow: hidden;">
    
                    <ul style="list-style: none;">
                        <%
                            Cookie[] cookies = request.getCookies();
                            Cookie cookie = com.itcast.servlet.CookieUtil.findCookie(cookies,"history");
                            if(cookie == null){
                        %>
                        <h2>您还没有任何的浏览记录</h2>
                        <%
                            }else{
                                String[] ids = cookie.getValue().split("#");
                                for(String id : ids){
                        %>
                                <li style=" 150px;height: 216;float: left;margin: 0 8px 0 0;padding: 0 18px 15px;text-align: center;"><img src="products/1/cs1000<%=id %>.jpg" width="130px" height="130px" /></li>
                        <%        
                                }
                            }
                         %>
                    </ul>
    
                </div>
                <h2><a href = "ClearHistory">清除浏览记录</a></h2>
            </div>
            <div style="margin-top:50px;">
                <img src="./image/footer.jpg" width="100%" height="78" alt="我们的优势" title="我们的优势" />
            </div>
    
            <div style="text-align: center;margin-top: 5px;">
                <ul class="list-inline">
                    <li><a>关于我们</a></li>
                    <li><a>联系我们</a></li>
                    <li><a>招贤纳士</a></li>
                    <li><a>法律声明</a></li>
                    <li><a>友情链接</a></li>
                    <li><a target="_blank">支付方式</a></li>
                    <li><a target="_blank">配送方式</a></li>
                    <li><a>服务声明</a></li>
                    <li><a>广告声明</a></li>
                </ul>
            </div>
            <div style="text-align: center;margin-top: 5px;margin-bottom:20px;">
                Copyright &copy; 2005-2016 传智商城 版权所有
            </div>
    
        </body>
    
    </html>
    View Code
    @WebServlet("/ProductInfoServlet")
    public class ProductInfoServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 获取到当前用户准备浏览的商品ID
            String id = request.getParameter("id");
            Cookie[] cookies = request.getCookies();
            Cookie cookie = CookieUtil.findCookie(cookies, "history");
            if (cookie == null) {
                Cookie c = new Cookie("history", id);
                // 设置有效期
                c.setMaxAge(60 * 60 * 24 * 7);
                // 设置访问这个工程的时候,才带cookie过来
                c.setPath("/Product_view");
                response.addCookie(c);
            } else {
                // 获取以前的cookie
                String ids = cookie.getValue();
                // 让现在浏览的商品和以前浏览的商品形成cookie新的值
                cookie.setValue(id + "#" + ids);
                // 需要重新设置有效期
                cookie.setMaxAge(60 * 60 * 24 * 7);
                // 设置访问这个工程的时候,才带cookie过来
                cookie.setPath("/Product_view");
                response.addCookie(cookie);
            }
            response.sendRedirect("product_info.htm");
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    }

    清除浏览记录:其实就是清除cookie,删除cookie没有什么delete方法,只有设置maxage=0

    @WebServlet("/ClearHistory")
    public class ClearHistory extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 清除cookie
            Cookie cookie = new Cookie("history", "");
            cookie.setMaxAge(0);    // 设置立即删除
            cookie.setPath("/Product_view");
            response.addCookie(cookie);
            response.sendRedirect("product_list.jsp");
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }

    cookie总结:

    1. 服务器给客户端发过来的一小份数据,并且存放在客户端上面

    2. 获取cookie,添加cookie

    request.getCookie();

    response.addCookie();

    3. Cookie分类

    会话cookie:默认情况下,关闭浏览器,cookie就会消失

    持久cookie:在一定的时间,都有效,并且保存在客户端上面

    cookie.setMasAge(100);

    4. cookie的安全问题:

    由于cookie保存在客户端上,会有安全隐患

    cookie的大小与客户端有限制,一个web工程限制20个,总共限制300个,为了解决这个问题,出现了session

    12 Session

    session是基于Cookie的一种会话机制,cookie是数据存放在客户端,session是数据存放在服务器端。

    session何时创建,何时销毁

    创建:如果在servlet里面调用了request.getSession();

    销毁:存放在服务器内存中的一份数据,可以持久化,关闭了浏览器,session也不会销毁

    session会话时间过期,默认时间为30分钟或者关闭服务器,session销毁

    // 得到会话的ID
    String id = session.getId();
    // 存值
    session.setAttribute("wang", "2015141452156");
    // 取值
    session.getAttribute("wang");
    // 移除值
    session.removeAttribute("wang");
    @WebServlet("/LoginSession")
    public class LoginSession extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=UTF-8");
            String id = request.getSession().getId();
            System.out.println("session id:" + id);
            response.getWriter().write("收到请求了");
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            doGet(request, response);
        }
    
    }

    案例:简单的购物车

    package com.itcast.session;
    
    import java.io.IOException;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class CarServlet
     */
    @WebServlet("/CarServlet")
    public class CarServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=UTF-8");
            // 1. 获取要添加到购物车的商品id
            System.out.println(request.getParameter("id"));
            int id = Integer.parseInt(request.getParameter("id"));
            System.out.println(id);
            String[] names = {"Iphone", "小米", "华为", "锤子", "洛基亚"};
            String name = names[id];
            // 2. 获取购物车存放东西的session    Map<String, Integer>
            Map<String, Integer> map = (Map<String, Integer>) request.getSession().getAttribute("cart");
            // session里面没有任何东西
            if(map == null){
                map = new LinkedHashMap<String, Integer>();
                request.getSession().setAttribute("cart", map);
            }
            // 3. 判断购物车中有没有这个商品
            if(map.containsKey(name)){
                map.put(name, map.get(name) + 1);
            }else{
                map.put(name, 1);
            }
            // 4. 输出界面,跳转
            response.getWriter().write("<a href = 'product_list.jsp'><h3>继续购物</h3></a>");
            response.getWriter().write("<a href = 'cart.jsp'><h3>去购物车结算</h3></a>");
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    package com.itcast.session;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * Servlet implementation class ClearCart
     */
    @WebServlet("/ClearCart")
    public class ClearCart extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            HttpSession session = request.getSession();
    //        session.invalidate();    // 使此会话无效,直接使里面存放的所有数据消失
            session.removeAttribute("cart");
            response.sendRedirect("cart.jsp");
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            doGet(request, response);
        }
    
    }
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'cart.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <!-- 展示购物车的商品 -->
        <h2>您的购物车商品如下</h2>
        <%
            Map<String, Integer> map = (Map<String, Integer>)session.getAttribute("cart");
            if(map != null){
                for(String key : map.keySet()){
                    int value = map.get(key);
        %>
            <h3>名称:<%=key %>, 数量:<%=value %></h3>
        <%
                }
            }
         %>
         <a href = "ClearCart"><h4>清空购物车</h4></a>
      </body>
    </html>
    View Code
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'product_list.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <a href = "CarServlet?id=0"><h3>Iphone</h3></a>
        <a href = "CarServlet?id=1"><h3>小米</h3></a>
        <a href = "CarServlet?id=2"><h3>华为</h3></a>
        <a href = "CarServlet?id=3"><h3>锤子</h3></a>
        <a href = "CarServlet?id=4"><h3>洛基亚</h3></a>
      </body>
    </html>
    View Code
  • 相关阅读:
    Spark&Hadoop:scala编写spark任务jar包,运行无法识别main函数,怎么办?
    Linux:krb5
    SqlServer数据库端口默认是1433吗?
    Linux下使用shell实现上传linux下某个目录下所有文件到ftp
    Spark+Hadoop+Hive集群上数据操作记录
    hadoop之 Hadoop2.2.0中HDFS的高可用性实现原理
    虚拟路由冗余协议VRRP
    hadoop 之Hadoop生态系统
    Oracle NoLogging Append 方式减少批量insert的redo_size
    Oracle常用的性能诊断语句
  • 原文地址:https://www.cnblogs.com/feng-ying/p/9804453.html
Copyright © 2011-2022 走看看