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
原文地址:https://www.cnblogs.com/feng-ying/p/9804453.html