请求转发

定义

指服务器收到请求之后,从一个资源跳转到另一个资源的的操作。

这是一种在服务器内部的资源跳转方式.(换言之,请求转发是不能跳到服务器之外的资源)

语法格式

requset.getRequestDispatcher(url);

特点

  1. 浏览器地址栏路径不发生变化
  2. 请求转发只是一次请求一次响应
  3. 他们可以共享Request域中的数据
  4. 请求转发只能转发到当前服务器内部的资源
  5. 可以转发到WEB-INF目录下

图示:

重定向session消失 重定向session丢失_重定向session消失

请求转发就好比,我们去办理业务,我们带材料(数据)去窗口1(Servlet1),窗口1(Servlet1)拿到我们的材料后,开始办理,但是发现材料缺少,因此窗口1(Servlet1)把材料交给窗口2(Servlet2),当窗口2(Servlet2)把缺少的材料补全后,直接把我们的业务给直接办理好,并给我们一个最后的结果。

请求域(request域)

  • 在两个servlet请求转发时,会存在A类的数据需要传递给B类这样的需求
  • 此时就需要使用请求对象的请求域(resquest)功能
  • request.setAttribute(String key, Object value),这样就可以将数据存储在请求对象
  • 再另外一个servlet中使用请求对象取出值request.getAttribute("key"),要保持两个servlet中的键一致。

案例

index.jsp

<!doctype html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style type="text/css">
        table{
            text-align: center;
            border-collapse: collapse;
        }
    </style>
</head>
<body>
<div>
    <form action="Servlet1" method="post">
        <table border="1px" style="text-align: center;">
            <tr>
                <td>用户名:</td>
                <td>
                    <input type="text" name="username" placeholder="用户名">
                </td>
            </tr>
            <tr>
                <td>密码:</td>
                <td>
                    <input type="password" name="password" placeholder="密码">
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <input type="submit" value="登录">
                    <input type="reset">
                </td>
            </tr>
        </table>
    </form>
</div>
</body>
</html>

Servlet1类:

package com.lyc.lesson.servlet;

import com.lyc.lesson.utils.DBUtil;

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 java.io.IOException;
import java.sql.*;

@WebServlet("/Servlet1")
public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        
        //将页面获取的数据存入request域中
       	req.setAttribute("username", username);
        
        //请求转发的路径参数必须加斜杠('/')
        //getRequestDispatcher(url);url可以是:servlet(必须是该类的映射路径,不是类名),html或jsp
        req.getRequestDispatcher("/login/Servlet2").forward(req,resp);
        
}

Servlet2类

package com.lyc.lesson.servlet;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/login/Servlet2")
public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        //获取request域中的数据
        Object username = req.getAttribute("username");

        PrintWriter out = resp.getWriter();
        out.println("欢迎您:"+username);
    }
}

注意:

在请求转发中,getRequestDispatcher(url); url可以是:servlet(必须是该类的映射路径,不是类名),html或jsp

重定向

定义

重定向,指的是Web服务器接收到客户端的请求后,可能由于某些条件限制,不能访问当前请求URL所指向的Web资源,而是指定了一个新的资源路径,让客户端重新发送请求。重定向也可以使用Servlet直接的跳转,以及跳转页面.

语法格式

response.sendRedirect("路径");

特点

  1. 浏览器地址栏会发生变化
  2. 重定向是两次请求、两次转发
  3. 不能共享Request域中的数据
  4. 不能访问WEB-INF下的资源
  5. 可以访问工程外的资源

图示:

重定向session消失 重定向session丢失_服务器_02

重定向就好比,我们还是去办理业务,我们带着材料去窗口1(servlet1),窗口1(servlet)开始办理业务发现我们缺少东西,因此把材料给我们,并告诉我们去窗口(servlet2),能继续办理,因此我们带着材料,来到窗口2(servlet2)并把材料交给他,窗口2(servlet2)接收到材料开始办理业务,成功完成业务后,把结果返回给我们。

案例:

Servlet1:

package com.lyc.lesson.servlet;

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 java.io.IOException;

@WebServlet("/Servlet1")
public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //请求重定向的路径参数,不能加斜杠('/')
        //如果加了斜杠,项目名会丢失
        resp.sendRedirect("Servlet2");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

Servlet2:

package com.lyc.lesson.servlet;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/Servlet2")
public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.write("请求重定向");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
    }
}

关于请求转发和重定向的路径问题

  • 请求转发是服务器行为,服务器根路径是项目名,
    所以发请求,从/开始,不会丢失项目名
  • 重定向是浏览器行为,浏览器根路径是端口
    所以发请求,从/开始,就会丢项目名

解决丢项目名的方法:

// req.getContextPath(); // 获得项目名 
resp.sendRedirect(req.getContextPath()+"/redirect2"); // 拼接项目名

这样即使在重定向内路径也可以加/。

Cookie和Session

什么是cookie以及cookie的作用

cookie是浏览器支持的一种本地存储机制。一般由服务端设置生成,在响应请求时被自动存储在浏览器中

cookie是为了辨别用户身份的。我们知道HTTP本身是无状态的协议,服务端不会记得是谁向它发来的请求。但在某些情况下我们需要记住用户在未登录的状态下浏览了什么,比如淘宝。这时候就需要借助我们的Cookie了。 客户端请求服务器后,如果服务器需要记录用户状态,服务器会在响应信息中包含一个Set-Cookie的响应头,客户端会根据这个响应头存储Cookie信息。再次请求服务器时,客户端会在请求信息中包含一个Cookie请求头,而服务器会根据这个请求头进行用户身份、状态等较验。

创建cookie、响应到浏览器

package com.lyc.lesson.servlet;

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;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;

@WebServlet("/CookieServlet")
public class CookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建cookie对象
        Cookie cookie = new Cookie(key,value);
		
        //通过响应将cookie对象添加到浏览器
        resp.addCookie(cookie);
        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

获取cookie的值

package com.lyc.lesson.servlet;

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;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;

@WebServlet("/CookieServlet")
public class CookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建cookie对象,解决中文乱码问题
        Cookie cookie = new Cookie("username","admin");
       
        //通过响应将cookie对象添加到浏览器
        resp.addCookie(cookie);

        //通过请求获得站点上的所有cookie对象
        Cookie[] cookies = req.getCookies();
        //遍历所有cookie对象,得到数据
       for (int i = 0; cookies != null && i < cookies.length; i++) {
    Cookie ck = cookies[i];
    String name = ck.getName( );
    String value = ck.getValue( );
    System.out.println(name+"="+value );
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

删除cookie

cookie是没有删除方法的,只能靠最大生命(setMaxAge)值来确定cookie的存活时间。cookie默认的生命周期是会话结束时(浏览器关闭),就销毁。同时也可以设置cookie的生命周期。

setMaxAge(int expiry);
  • 大于0,存在指定的
  • 等于0,直接删除
  • 小于0,一般是-1 ,保存至浏览器关闭
// 创建cookie
        Cookie cookie = new Cookie("username","admin");

        // 创建的cookie,默认存储到浏览器关闭.
        // 可以设置时间,单位是秒!!
        // cookie.setMaxAge(30);
        // cookie.setMaxAge(0); // 直接删除该cookie
        cookie.setMaxAge(-1); // 保存至浏览器关闭

cookie的中文乱码问题

cookie的中文乱码指的是,cookie中的键如果取中文就会乱码。

解决中文乱码的方法:先将中文编码,在解码

package com.lyc.lesson.servlet;

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;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;

@WebServlet("/CookieServlet")
public class CookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建cookie对象,解决中文乱码问题
        //编码:URLEncoder.encode
        Cookie cookie = new Cookie(
                URLEncoder.encode("姓名", "utf-8"),
                URLEncoder.encode("张三", "utf-8"));
        cookie.setMaxAge(60);

        //通过响应将cookie对象添加到浏览器
        resp.addCookie(cookie);

        //通过请求获得站点上的所有cookie对象
        Cookie[] cookies = req.getCookies();
        //遍历所有cookie对象,得到数据
        for (Cookie cookie1 : cookies) {
            String name = cookie1.getName();
            String value = cookie1.getValue();
		//解码:URLDecoder.decode
          System.out.println(URLDecoder.decode(name, "utf-8")+"="+ URLDecoder.decode(value, "utf-8"));
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

什么是Session

  1. session就一个接口( Httpsession ) 。
  2. Session就是会话。它是用来维护一个客户端和服务器之间关联的一种技术
  3. 每个客户端都有自己的一个session会话。
  4. Session会话中,我们经常用来保存用户登录之后的信息。

创建session

request.getSession();

第一次调用是:创建 Session 会话,之后调用都是:获取前面创建好的 Session 会话对象。

存数据

登录页面

<!doctype html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style type="text/css">
        table{
            text-align: center;
            border-collapse: collapse;
        }
    </style>
</head>
<body>
<div>
    <form action="SessionServlet" method="post">
        <table border="1px" style="text-align: center;">
            <tr>
                <td>用户名:</td>
                <td>
                    <input type="text" name="username" placeholder="用户名">
                </td>
            </tr>
            <tr>
                <td>密码:</td>
                <td>
                    <input type="password" name="password" placeholder="密码">
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <input type="submit" value="登录">
                    <input type="reset">
                </td>
            </tr>
        </table>
    </form>
</div>
</body>
</html>

SessionServlet:

package com.lyc.lesson.servlet;

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;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/SessionServlet")
public class SessionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
		//获取前端页面传来的数据
        String username = req.getParameter("username");
		//创建session对象
        HttpSession session = req.getSession();
        //将数据存入session域中
        session.setAttribute("username", username);
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

获取session[重点]

对于session来讲,只要会话不结束,无论是请求转发还是重定向都可以获取session域中的数据。

删除session

public void setMaxInactiveInterval(int interval)

设置 Session 的超时时间(以秒为单位),超过指定的时长,Session 就会被销毁。 值为正数的时候,设定 Session 的超时时长负数表示永不超时(极少使用)

//获取 Session 的超时时间 
public int getMaxInactiveInterval()
//让当前 Session 会话马上超时无效。
public void invalidate()

Session和Cookie的联系和区别

区别:

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上。
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能, 考虑到减轻服务器性能方面,应当使用COOKIE。
  4. 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

联系:

重定向session消失 重定向session丢失_servlet_03