JavaWeb基础

1.web开发项目结构

src------java代码核心的配置文件(例如spring配置文件等) servlet
web----静态资源或者jsp
html/js/css/img等静态资源外部都可以直接访问
web-inf-外界无法访问
web.xml—servlet相关配置

2.servlet

  • 定义:servlet是基于java技术的web组件,由容器管理并产生动态的内容。servlet与客户端通过servlet容器实现请求/相应模型进行交互。(springmvc底层就是基于servlet)

2.1servlet环境搭建

  1. 在项目中创建libs目录存放第三方依赖包
  2. 导入servlet-api.jar到libs目录中(在tomcat安装的目录lib目录中)
  3. 创建servlet包专门存放servlet
  4. 创建Servlet子类实现Servlet接口
  5. 在Servlet子类加上@WebServlet("path")注解定义URL访问路径
  6. 重写Servlet类中的service,在service中编写动态资源
    在这里插入图片描述
package com.zhxd.test;
/*
 * author zhxd
 * ClassName indexServlet
 */

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;

//利用注解定义客户端访问路径
@WebServlet("/zhxd")
public class indexServlet implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /*
    * tomcat 启动完成
    * 127.0.0.1:8080/项目名称/zhxd 执行service
    * 通过service方法获取ServletRequest ServletResponse对象
    * */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("zhxd???");
        //通过servletRequest对象获取客户端传递给服务器的参数
        String username = servletRequest.getParameter("username");
        //设置响应的格式和字符集
        servletResponse.setContentType("text/html;charset=gbk");
        //获取响应客户端的流传输管道
        PrintWriter writer = servletResponse.getWriter();
        if(username.equals("zhxd")) {
            writer.println("登录成功");
        }else {
            writer.println("登录失败");
        }
        writer.close();
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

2.2servlet执行流程

  • servlet由tomcatweb服务器创建,service也是由tomcatweb服务器调用
  • 创建一个Servlet子类必须实现servlet接口重写service方法
  • tomcat服务器执行servlet中的service方法是因为创建的Servlet实现了httpservlet接口,实现了service方法
    在这里插入图片描述

2.3servlet生命周期(重点)

  1. 创建servlet实例被服务器(tomcat)加载servlet —无参构造方法
  • servlet创建的模式有两种:第一,第一次访问servlet才会创建servlet对象;第二,提前创建好servlet对象。
  • 单例模式:servlet对象创建好之后,在jvm内存中只会存一份
  • @WebServlet(urlPatterns="path",loadOnstartup=1)
    urlPattern:访问的url
    loadOnStartup:当值为负数的时候:第一次访问的创建Servlet对象;当值为0和正数时:服务器启动就会创建Servlet对象,数字越小优先级越高,zhxd01Servlet loadOnstartup = 1,zhxd02Servlet loadOnstartup=2,底层会根据loadOnstartup的值排序,越小越优先加载
  • 共享同一个Servlet对象,存在线程安全问题
    在这里插入图片描述
  1. init()初始化方法
  • 当servlet类被创建时,执行init方法,该方法只执行一次,可以在该方法中写一些初始化的代码
  1. service(),执行每次请求
  • 每次客户端发送请求到服务器都会执行service方法,每次请求都执行一次
  1. destroy():销毁
  • 当tomcat容器停止的时候卸载servlet
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.4Servlet其他方法

  • getServletConfig():该方法返回调用init()方法时传递给Servlet对象的ServletConfig对象,ServletConfig对象包含Servlet的初始化参数
  • getServletInfo():返回一个字符串,返回的是一个纯文本字符串,而不是任何类型的标记

getServletConfig的用法:

  1. @WebServlet()注解中定义初始化参数,例:@WebServlet(urlPattern="/zhxd",initParams={@WebInitParam(name="",value="")})
  2. 定义成员属性ServletConfig servletConfig
  3. 在生命周期init(ServletConfig servletConfig)中给servletConfig赋值,this.servletConfig = servletConfig;
  4. 重写getServletConfig()方法

例:

package com.zhxd.test;
/*
 * author zhxd
 * ClassName indexServlet
 */

import javax.servlet.*;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;

//在@WebServlet注解中的initParams定义初始参数
@WebServlet(urlPatterns = "/zhxd", loadOnStartup = -1, initParams = {
        @WebInitParam(name = "param1", value = "teacher"),
        @WebInitParam(name = "param2", value = "student")
})
public class indexServlet implements Servlet {
    //定义私有的servletConfig
    private ServletConfig servletConfig;

    public indexServlet() {
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //在初始化给servletConfig赋值
        this.servletConfig = servletConfig;
    }

    //重写getServletConfig
    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //通过ServletConfig对象.getInitParameter获取初始化参数
        String param1 = getServletConfig().getInitParameter("param1");
        String param2 = getServletConfig().getInitParameter("param2");

        servletResponse.setContentType("text/html;charset=gbk");
        PrintWriter writer = servletResponse.getWriter();
        writer.println("param1:" + param1);
        writer.println("param2:" + param2);
        writer.close();
    }

    @Override
    public String getServletInfo() {
        return "I'm ServletInfo";
    }

    @Override
    public void destroy() {

    }
}

2.5HttpServlet

HttpServlet模板设计模式:
在这里插入图片描述
HttpServlet对的servlet接口包装,提供get/post/put/head等方法
httpServletDemo.java

package com.zhxd.test;
/*
 * author zhxd
 * ClassName httpServletDemo
 */

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("/zhxd01")
public class httpServletDemo extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println("Http的post请求");
        writer.close();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println("Http的get请求");
        writer.close();
    }
}

html/userinfo.html(post请求)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>userinfo</title>
</head>
<body>
    <form action="http://127.0.0.1:8080/zhxd01" method="post">
        <label for="">姓名:</label><input type="text" name="username" value=""/><br>
        <label for="">年龄:</label><input type="number" name="age" value=""/><br>
        <input type="submit" name="submit" value="提交" />
    </form>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

2.6request与response对象

  • request:获取客户端发送给服务端的数据
  • response:返回数据给客户端
  • http协议基于请求(request)响应(response)模型

2.6.1request对象

  1. 获取请求方式:String getMethod()
  2. 获取项目访问路径:String getContextPath()
    在这里插入图片描述
  3. 获取URL统一资源定位符:StringBuffer getRequestURL()
  4. 获取URI统一资源标识:String getRequestURI()
  5. 获取get请求的参数:String getQueryString()
  6. 根据请求头名称获取值:String getHeader(String name)
  7. 获取当前上下文(获取tomcat配置的项目路径):String contextPath()
  8. 通过流读取来获取Post参数:
  • ServletInputStream getInputStream()
  • BufferReader getReader()
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        通过流获取Post参数
        BufferedReader reader = req.getReader();
        String str = reader.readLine();
        System.out.println(str);
        reader.close();
    }
  1. request通用获取请求参数
  • Request对象里面封装好了一个Map集合,Map集合里面放的是所有的参数
  • 返回Map集合,Map<String,String[]> getParameterMap()
  • 根据键名获取值:String[] getParameterValues(String name)
  • 根据键名获取值:String getParameter(String name)
package com.zhxd.test;
/*
 * author zhxd
 * ClassName httpServletTest
 */

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.util.Map;

@WebServlet("/zhxd02")
public class httpServletTest 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 {
        //请求URL:http://127.0.0.1:8080/zhxd02?name=zhxd&&name=zxd
        //获取到参数的Map集合
        Map<String, String[]> map = req.getParameterMap();
        //遍历map集合
        for (String key : map.keySet()) {
            System.out.print(key + ":");
            String[] values = map.get(key);
            for (String value : values) {
                System.out.print(value+" "); // name:zhxd zxd
            }
            System.out.println();
        }

        //根据 键名 获取值
        String value = req.getParameter("name");
        System.out.println(value);//zhxd

        String[] values = req.getParameterValues("name");
        for (String v : values) {
            System.out.println(v);
            /*
            * zhxd
            * zxd
            * */
        }
    }
}

2.6.2response对象

  • 客户端在发出每个请求的时候都会创建一个response对象,并作为参数传入Servlet.service()中,用于对客户端的请求进行响应
  1. 设置服务端的编码:response.setCharacterEncoding("gbk")
  2. 设置响应头:response.setHeader("Content-type", "text/html;gbk")
  3. 同时设置客户端和服务端(调用setCharacterEncoding()方法):response.setContentType("text/html;charset=gbk")
  • 相应格式由三部分组成:响应行、响应头、响应体
  1. 向客户端响应正文(响应体),可以使用response响应流:
  • response.getWriter()/response.getOutputStream():如果响应的是字符,就用writer,如果响应的是字节,比如下载的时候,则用outputstream
  1. 设置错误的响应码:response.setError(404, "未找到请求的资源")
  2. 设置正确的响应码:response.setStatus(200)

2.6.3request请求转发和response重定向

2.6.3.1request请求转发
  • 请求转发是在服务器内部资源跳转的一种方式,只能转发到服务器内部资源中。
  1. 获取转发器:request.getRequestDispatcher(String path)
  2. 使用RequestDispatcher进行请求转发:forward(ServletRequest servletRequest,ServletResponse servletResponse)
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/httpServlet02");
requestDispatcher.forward(request,response);
  1. 数据共享:request.setAttribute(String name,value)
    在这里插入图片描述
    httpServlet01.java
package com.zhxd.test;
/*
 * author zhxd
 * ClassName httpServlet01
 */

import javax.servlet.RequestDispatcher;
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("/httpServlet01")
public class httpServlet01 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 {
        //获取重请求对象
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/httpServlet02");
        //共享数据
        req.setAttribute("name","zhxd");
        //请求转发
        requestDispatcher.forward(req, resp);
    }
}

httpServlet02.java

package com.zhxd.test;
/*
 * author zhxd
 * ClassName httpServlet01
 */

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("/httpServlet02")
public class httpServlet02 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 {
        //获取共享数据
        String name = (String)req.getAttribute("name");
        System.out.println(name);
        resp.setContentType("text/html;charset=gbk");
        PrintWriter writer = resp.getWriter();
        writer.println("这是httpServlet02返回的数据");
        writer.close();
    }
}

在这里插入图片描述

2.6.3.2response重定向
  • 客户端往服务器发送一个请求,服务端返回http状态码是302,同时返回一个新的URL,客户端会按照新的URL重新去发送请求
  • 相关API
  1. 首先设置http状态码为302:response.setStatus(302)
  2. 设置响应头location的值:reponse.setHeader("Location","www.baidu.com")
  3. 合并上面两个API:response.sendRedirect(String location)
    在这里插入图片描述
package com.zhxd.test;
/*
 * author zhxd
 * ClassName httpServlet01
 */

import javax.servlet.RequestDispatcher;
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("/httpServlet01")
public class httpServlet01 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.setStatus(302);
        resp.setHeader("Location", "http://www.baidu.com");
        /*
        *resp.sendRedirect("http://www.baidu.com");
        */
    }
}

在这里插入图片描述
浏览器尚未跳转,按下F9,进入下一步,页面进入百度页面

  • 重转发与重定向的区别
  1. 转发只能把请求转发给同一个web应用的其他组件;重定向可以转发到任意的地址。
  2. 重转发访问结束后,浏览器的地址栏URL并不会发生变化,客户端只发送一次请求;重定向访问结束后,浏览器地址栏URL会发生变化,客户端会发送两次请求。
  3. 请求转发调用者和被调用者之间共享请求对象,属于同一个请求和响应过程;重定向则是不同的请求和响应过程

3.JSP

JSP是Java Server Page的缩写,是java服务端页面,底层是基于Servlet封装,最终JSP文件会编译为Servlet的java文件。由于Servlet做界面的时候极其不方便,所以产生了JSP技术,页面的书写和一般的html相似。

  • 在JSP中定义Java代码
  1. <%…%>:内容会放到_jspService()方法之中
  2. <%=…%>:内容会放在out.print(),作为out.print()的参数(responsse.getWriter())
  3. <%!..%>:内容会放在_jspService()方法之外,被类直接包含
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%
    System.out.println("%%是定义在_jspservice之中的...");
    int j = 20;
    test();
  %>
  <%="%=%这个也是定义在_jspservlet之中的,可以直接输出字符串给客户端" + j%>
  <%!
    void test() {
      System.out.println("%!%是定义在_jspservice之外的");
    }
  %>
  </body>
</html>

查看转换成Servlet对象之后的代码:CATALINA_BASE: C:\Users\zhxd.IntelliJIdea2017.3\system\tomcat\Unnamed_test\work
在这里插入图片描述
在这里插入图片描述

3.1JSP内置对象

  • JSP内置对象有九个,不需要用户(程序员)创建,在JSP页面中就可以直接使用的对象
对象名真实类型作用
pageContextPageContext当前页面共享数据,还可以获取其他八个内置对象
requestHttpServletRequest请求对象
responseHttpServletResponse响应对象
outJspWriter输出对象,数据输出到页面上
sessionHttpSession一次会话的多个请求间共享数据
applicationServletContext用户间共享数据
pageObject前页面(Servlet)的对象 this
configServletConfigServlet的配置对象
exceptionThrowable异常对象
  1. out对象
  • int getRemaining():获取剩余缓冲区大小
  • int getBufferSize():获取缓冲区大小
  • void isAutoFlush():自动刷新缓冲区
  1. page对象

page对象包含当前Servlet接口引用的变量,可以看做this关键字的别名

  • getClass():返回当前Object的类
  • hashCode():返回该Object的哈希代码
  • toString():把该Object类转换成字符串
  • equals(Object o()):比较该对象和指定对象是否相等
  1. pageContext对象

在JSP页面中,使用pageContext对象可以获取JSP的其他8个内置对象。它代表当前JSP页面的运行环境,并提供了一系列用于获取其他内置对象的方法。

  • JspWriter getOut():用于获取out内置对象
  • Object getPage():用于获取page内置对象
  • ServletRequest getRequest():用于获取request内置对象
  • ServleResponse getResponse():用于获取response内置对象
  • HttpSession getSession() :用于获取session内置对象
  • Exception getException() :用于获取exception内置对象
  • ServletConfig getServletConfig():用于获取appliction内置对象
  • setAttribute(String name,Object value, int scope):用于设置pageContext对象的属性

pageContext对象可以设置。scope参数:PageContext.PAGE_SCOPE(1),PageContext.REQUEST_SCOPE(2),PageContext.SESSION_SCOPE(3),PageContext.APPLICATION_SCOPE(4)

  • getAttribute(String name,Object value, int scope):用于获取pageContext对象的属性
  • removeAttribute(String name,int scope):删除指定范围内名称为name的属性
  • removeAttribute(String name):删除所有范围内名称为name的属性
  • findAttribute(String name):从4个域对象中查找名称为name的属性
  1. session对象

session中保存的数据是一次会话有效,保存用户状态,直到浏览器关闭为止(和服务器断开连接)。

  • session.setAttribute(String name, Object obj):将属性设置在session范围内
  • session.getAttribute(String name):从session对象中获取属性
  • session.removeAttribute(String name):从session对象中移除属性
  1. application对象

application对象用于保存所有应用程序中的公有数据。它在服务器启动时自动创建,在服务器停止时销毁。

  • getAttributeNames():获得所有application对象使用的属性名。
  • getAttribute(String name):从application对象中获取指定对象名。
  • setAttribute(String key, Object obj):使用指定名称和指定对象在application对象中进行关联。
  • removeAttribute(String name):从application对象中去掉指定名称的属性。

3.2el表达式

el(Expression Language)表达式语言,用于简化JSP页面内的代码,主要功能是获取数据。语法:${expression},会从page、request、session、application域中取值
在这里插入图片描述
httpServletTest.java

package com.zhxd.test;
/*
 * author zhxd
 * ClassName httpServletTest
 */

import javax.servlet.RequestDispatcher;
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("/httpServletTest")
public class httpServletTest 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 name = "张三";
        int age = 20;
        String gender = "male";
        //定义request域的数据
        req.setAttribute("name", name);
        req.setAttribute("age", age);
        req.setAttribute("gender", gender);
        //请求转发
        req.getRequestDispatcher("test.jsp").forward(req, resp);
    }
}

test.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>test</title>
</head>
<body>
    <%--使用el表达式--%>
    ${name} - ${age} -${gender}
</body>
</html>

3.3jstl标签

jstl是标签语言,是apache对el表达式的扩展,但是并非JSP内置的标签,需要自己导包并指定标签库。

  • 环境步骤
    • 导入jstl依赖包
    • 导入JSTL的core标签库<%@ taglib prefix=“c” uri=“http://java.sun.com/jstl/core_rt” %>
      • prefix=“c”:指定标签库的前缀,这个前缀可以随意给值,但是按照习惯标签前缀通常都是c
      • uri=“http://java.sun.com/jstl/core”:指定标签库的uri

下载地址:jstl依赖包
JSP学习会重点学到2个标签,<c:if>和<c:forEach>

3.3.1<c:if>条件判断

相当于java的if条件判断语句,它只有if语句,没有else语句
语法<c:if test=“条件”></c:if>

  • 条件:必须是一个布尔值,一般结合el表达式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
    <title>test</title>
</head>
<body>
    <%request.setAttribute("number", 4);%>
    <c:if test="${number % 2 == 0}">
        <h1>偶数</h1>
    </c:if>
    <c:if test="${number % 2 != 0}">
        <h1>奇数</h1>
    </c:if>
</body>
</html>

3.3.2<c:forEach>循环语句

相当于java的循环语句

  • forEach标签的属性
  1. 数值操作
    • begin:开始值
    • end:结束值
    • var:临时值
    • step:步长
    • varStatus:循环状态对象
      • index:容器中元素的索引,从0开始
      • count:循环次数,从1开始
        2.遍历容器
    • items:容器对象
    • var:容器单个元素的临时值
    • varStatus:循环状态对象
      • index:容器中元素的索引,从0开始
      • count:循环次数,从1开始
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
    <title>test</title>
</head>
<body>
    <%
        ArrayList<String> nameList = new ArrayList<String>();
        nameList.add("beijing");
        nameList.add("guangzhou");
        nameList.add("zhuhai");
        request.setAttribute("nameList", nameList);
    %>
    <%--遍历容器--%>
    <c:forEach items="${nameList}" var="name" varStatus="vs">
        第${vs.count}次循环<br />
        name${vs.index}:${name}<br />
        <hr />
    </c:forEach>
    <%--遍历数值--%>
    <c:forEach begin="0" end="10" step="2" var="i" varStatus="vs">
        第${vs.count}次循环,索引值为${vs.index},数值为${i}
        <hr />
    </c:forEach>
</body>
</html>

在这里插入图片描述

4.会话技术

http协议是无状态的,没有任何的记忆功能,每次服务器接收到的请求都是认为是新的请求。会话可以理解为一次通话,从开始直到挂断为一次会话,一次会话可以包含多次请求和响应。会话技术实现方式有:

  1. 客户端会话跟踪技术:Cookie
  2. 服务端会话跟踪技术:Session
  3. token/jwt

4.1Cookie

Cookie是客户端的会话技术,将数据保存在客户端中,之后每一次请求都携带Cookie数据进行访问,基本原理:Cookie实现是基于HTTP协议的,客户端通过发送请求到达服务端,服务器会创建cookie,通过执行Set-Cookie将数据返回给客户端,当时用同一个浏览器发送一个请求时,在请求头中设置cookie数据发送给服务端。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 创建Cookie对象:Cookie cookie = new Cookie(String key, String value)
  • 使用response响应Cookie给客户端:response.addCookie(Cookie cookie)
  • 获取客户端携带的所有Cookie:Cookie[] cookies = request.getCookies()
  • 获取Cookie对象的名字:String getName()
  • 获取Cookie对象的值:String getValue()
  • 设置Cookie的过期时间:cookie.setMaxAge(int seconds)
    • 正数:将Cookie写入浏览器所在的电脑硬盘中,持久化存储,到期自动删除
    • 负数:默认值,当浏览器关闭时,Cookie失效
    • 零:删除对应Cookie

setCookie

@WebServlet("/setCookie")
public class testServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie1 = new Cookie("name", "zhangsan");
        Cookie cookie2 = new Cookie("age", "18");
        //设置cookie
        resp.addCookie(cookie1);
        resp.addCookie(cookie2);
    }
}

getCookie

@WebServlet("/getCookie")
public class testServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取所有Cookie
        Cookie[] cookies = req.getCookies();
        for(Cookie cookie:cookies) {
            //获取cookie对象的名字和值
            System.out.println(cookie.getName());
            System.out.println(cookie.getValue());
        }
    }
}

4.2Session

session的底层是基于cookie封装的,数据保存在服务端。session实现的原理:

  1. 客户端发送请求达到服务器创建session,服务器会返回一个sessionid在响应头
  2. 客户端接收到sessionid之后保存在Cookie中
  3. 当同一个浏览器发送请求时会把sessionid通过Cookie形式发送给服务端,服务端接受到sessionid之后再根据id寻找对应的session
    在这里插入图片描述
  • 常用API:
  1. void setAttribute(k,v):设置session的键值对
  2. Object getAttribute(k):根据键获取值
  3. void removeAttribute(k):根据键删除session
  4. void invalidate:销毁session对象

getSessionA

@WebServlet("/getSessionA")
public class testServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();//获取session对象
        //设置session
        session.setAttribute("name", "zhangsan");
        session.setAttribute("age", 18);
    }
}

getSessionB

@WebServlet("/getSessionB")
public class testServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //获取session
        String name = (String)session.getAttribute("name");
        Integer age = (Integer) session.getAttribute("age");
        System.out.println("姓名为:"+ name + "  " + "年龄:" + age);
    }
}

在这里插入图片描述

  • Sesssion和Cookie的区别
    • session用于存储一次会话多次请求的数据,存在服务端端,Cookie存在客户端
    • session可以存储任意类型和大小的数据,Cookie存储的数据有大小限制
    • session数据较为安全用户不可见,cookie相对不安全

5.过滤器

过滤器是存在客户端与服务器之间的一道过滤网,在访问资源时,对请求进行修改判断,把不符合规则的请求拦截或者修改。应用场景:判断用户是否登录、过滤请求记录日志、身份校验,权限控制等。同时过滤器也可以减少代码冗余的问题。

5.1使用步骤

  1. 定义一个类实现Filter接口
  2. 重写doFilter()/init()/destory()方法
    • filterChain.doFilter(servletRequest, servletResponse):放行
  3. 配置拦截路径
package com.zhxd.filter;
/*
 * author zhxd
 * ClassName FilterTest01
 */

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;


@WebFilter("/*")
public class FilterTest01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器正在运行~");
        filterChain.doFilter(servletRequest, servletResponse);//放行请求
    }

    @Override
    public void destroy() {

    }
}

5.2过滤器的声明周期

  1. init():在服务器启动时创建Filter对象,然后调用init初始化方法,只执行一次。
  2. doFilter():在每次请求被拦截时会执行,会执行多次
  3. destory():在服务器关闭后,Filter对象被销毁,只执行一次

5.3配置过滤器的拦截

  • 拦截路径配置(四种):
  1. 具体资源路径配置:/index.jsp,只有访问index.jsp时,过滤器才会执行
  2. 拦截目录:/zhxd/*,访问zhxd目录下的所有资源,都会执行过滤器
  3. 后缀名拦截:*.jsp,访问jsp资源时,都会执行过滤器
  4. 拦截所有资源:/*,所有请求都会执行过滤器
  • 拦截方式配置:
  1. REQUEST:默认值,直接访问时拦截
  2. FORWARD:转发资源时拦截
  3. INCLUDE:包含资源访问时拦截
  4. ERROR:错误跳转资源时拦截
  5. ASYNC:异步访问资源时拦截
//直接访问时
@WebFilter(value = "/index.jsp", dispatcherTypes = DispatcherType.REQUEST)
//转发访问时
@WebFilter(value = "/index.jsp", dispatcherTypes = DispatcherType.FORWARD)

5.4过滤器链

执行完过滤器1,再执行过滤器2…形成了一个链式调用,优先级按照过滤器类名的自然排序
在这里插入图片描述

6.监听器

web监听器是Servlet中特殊的一种类,能帮助开发者监听web中的特定事件,比如ServletContext、HttpSession、ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控。
监听器有三类6种:

  1. 监听生命周期:
  • ServletRequestListener
  • HttpSessionListener
  • ServletContextListener
  1. 监听值的变化
  • ServletRequestAttributeListener
  • HttpSessionAttributeListener
  • ServletContextAttributeListener

案例:统计在线人数
onlineSessionListener.java

package com.zhxd.listener;
/*
 * author zhxd
 * ClassName SessionListenerTest
 */

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/*
* 监听的实现
* 1. 实现需要的接口
* 2. 加上监听类的注解
*
* 监听Session的声明周期
* 1. sessionCreated session对象创建
* 2. sessionDestoryed session对象销毁
* */
@WebListener
public class onlineSessionListener implements HttpSessionListener {
    //在线人数
    private Integer onlineNumber = 0;

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("执行Session监听器");
        onlineNumber++;
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        servletContext.setAttribute("onlineNumber", onlineNumber);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("销毁Session监听器");
        onlineNumber--;
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        servletContext.setAttribute("onlineNumber", onlineNumber);
    }
}

onlinServlet.java

package com.zhxd.servlet;
/*
 * author zhxd
 * ClassName onlineServlet
 */

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("/online")
public class onlineServlet 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");
        //从Application作用域中取出在线人数
        //输出
        PrintWriter writer = resp.getWriter();
        //已登录情况下
        String key = req.getParameter("key");
        if(key == null || !(key.equals("logout"))) {
            Integer onlineNumber =
                    //不能直接使用req.getServletContext(),要通过session去获取上下文(application作用域)
                    (Integer) req.getSession().getServletContext().getAttribute("onlineNumber");
            writer.write("<h1>在线人数:" + onlineNumber + "</h1><br />");
            writer.write("<a href='online?key=logout'>退出登录</a>");
            writer.close();
            return;
        }
        //退出
        req.getSession().invalidate();
        writer.write("<h1>您已退出,再见</h1>");
        writer.close();
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值