ServletContext,Cookie,HttpSession的使用

ServletContext对象

ServletContext对象官方也称servlet上下文。服务器会为每一个Web应用创建一个ServletContext对象,这个对象全局唯一,而且Web应用中所有的Servlet都共享这个对象。

ServletContext对象的作用

相对路径转绝对路径

servletContext.getRealPath("Path");

该方法可以将一个相对路径转成绝对路径,在文件的上传和下载时需要用到该方法作为路径的转换。

示例:

java 复制代码
package com.test;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //使用ServletContext对象将相对路径转成绝对路径
        String path="image\\girl.jpg";
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        String realPath=servletContext.getRealPath(path);
        System.out.println(realPath);
        //  先上传文件
        File file = new File(realPath);
        //实现文件的下载
        resp.addHeader("Content-Disposition","attachment;filename="+new String(file.getName().getBytes("gbk"),"ISO-8859-1"));
        //思路是:先以windows系统的GBK编码将字符串转成字节,再以浏览器的ISO-8859-1编码将字节转成字符
        try(InputStream is = new FileInputStream(file);
            OutputStream os = resp.getOutputStream();){
            //创建缓冲数组
            byte[] buffer = new byte[1024];
            int temp;
            while ((temp=is.read(buffer))!=-1){
                os.write(buffer,0,temp);
            }
            os.flush();
        }
    }
}
获取容器的基本附加信息

ServletContext简用sc表示

sc.getServerInfo();返回Servlet容器的名称和版本号

sc.getMajorVersion();返回Servlet容器所支持Servlet的主版本号

sc.getMinorVersion();返回Servlet容器所支持的Servlet的副版本号

web.xml配置

java 复制代码
    <servlet>
        <servlet-name>baseInfo</servlet-name>
        <servlet-class>com.test.GetBaseInfoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>baseInfo</servlet-name>
        <url-pattern>/baseInfo.do</url-pattern>
    </servlet-mapping>

代码:

java 复制代码
        //设置响应编码
        resp.setContentType("text/plain;charset=utf-8");
        //获取ServletContext对象
        ServletContext sc = this.getServletContext();
        //回Servlet容器的名称和版本号
        String serverInfo = sc.getServerInfo();
        //返回Servlet容器所支持Servlet的主版本号
        int majorVersion = sc.getMajorVersion();
        //返回Servlet容器所支持的Servlet的副版本号
        int minorVersion = sc.getMinorVersion();
        try(PrintWriter pw = resp.getWriter();){
            pw.println("servlet容器:"+serverInfo);//servlet容器:Apache Tomcat/9.0.80
            pw.println("支持的Servlet版本:"+majorVersion+"."+minorVersion);//支持的Servlet版本:4.0
            pw.flush();
        }
获取web.xml文件中的信息
XML 复制代码
   <context-param>
        <param-name>name</param-name>
        <param-value>张三</param-value>
    </context-param>
    <context-param>
        <param-name>age</param-name>
        <param-value>20</param-value>
    </context-param>

param-name:相当于key,param-value:相当于value

sc.getInitParameter("key");

读取web.xml文件标签中的配置信息

sc.getInitParameterNames();

读取web.xml文件中所有的param-name标签中的值

代码示例:

java 复制代码
        //设置响应编码格式
        resp.setContentType("text/plain;charset=utf-8");
        //获取ServletContext对象
        ServletContext sc = this.getServletContext();
        //
        Enumeration<String> initParameterNames = sc.getInitParameterNames();
        try(PrintWriter pw =resp.getWriter()){
            while (initParameterNames.hasMoreElements()){
                String key = initParameterNames.nextElement();
                String value = sc.getInitParameter(key);
                pw.println("key = "+key+",value : "+value);
            }
            pw.flush();
        }
全局容器

即将数据放到全局容器后不同的servlet都可以进行访问获取。

sc.setAttribute("key","ObjectValue");向全局容器添加数据

sc.getAttribute("key");从全局容器获取数据

sc.removeAttribute("key");从全局容器移除数据

代码示例:

java 复制代码
@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置响应编码格式
        resp.setContentType("text/plain;charset=utf-8");
        //获取ServletContext对象
        ServletContext sc = this.getServletContext();
        String username = (String) sc.getAttribute("username");
        String password = (String)sc.getAttribute("password");
        try(PrintWriter pw =resp.getWriter()){
            pw.println("username:"+username);
            pw.println("password:"+password);
            pw.flush();
        }
    }

    @Override
    public void init() throws ServletException {
        //全局信息一般是在容器初始化的时候添加的
        ServletContext sc= this.getServletContext();
        sc.setAttribute("username","root");
        sc.setAttribute("password","123456");
    }

ServletContext生命周期

当容器启动时就会创建ServletContext对象,并一直缓存该对象,直到容器关闭后该对象生命周期才结束。

ServletContext的生命周期很长,使用全局容器时不建议存放业务数据。

ServletConfig对象

ServletConfig对象对应web.xml文件中的节点,当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封装到一个ServletConfig对象中,我们可以通过这个对象获取节点中的配置信息,只能获取当前Servlet中的配置信息

XML 复制代码
    <servlet>
        <servlet-name>servletConfig</servlet-name>
        <servlet-class>com.test.GetServletConfig</servlet-class>
        <init-param>
            <param-name>username</param-name>
            <param-value>张三</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123456</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletConfig</servlet-name>
        <url-pattern>/servletConfig.do</url-pattern>
    </servlet-mapping>

init-param标签只能在servlet标签里,多个name-value是这样并列的。

代码:

java 复制代码
       //设置响应编码
        resp.setContentType("text/plain;charset=utf-8");
        ServletConfig servletConfig = this.getServletConfig();
        Enumeration<String> names = servletConfig.getInitParameterNames();
        try(PrintWriter pw = resp.getWriter()){
            while (names.hasMoreElements()){
                String name=names.nextElement();
                String value=servletConfig.getInitParameter(name);
                pw.println("name = "+name+",value = "+value);
            }
            pw.flush();
        }

Cookie对象

Cookie对象和HttpSession对象的作用都是维护客户端浏览器与服务段的会话状态的对象。

Cookie是通过客户端浏览器实现会话的维持,支持跨二级域名

HttpSession是通过服务端来实现会话状态的维持

特点

  • 使用字符串存储数据
  • 使用key与value结果存储数据
  • 单个Cookie存储数据大小限制在4097个字节
  • Cookie存储的数据不支持中文,Servlet4.0支持
  • Cookie是与域名绑定所以不支持跨一级域名访问
  • Cookie对象是保存在客户端浏览器或系统磁盘中的
  • Cookie分为持久化Cookie和状态Cookie
  • 浏览器在保存同一域名所返回的Cookie数量是有限的,不同浏览器所支持的数量不同,chrome浏览器为50个。
  • 浏览器每次请求时都会把当前访问的域名相关的Cookies在请求中提交到服务端。

Cookie对象的创建

cookie默认会随浏览器的关闭而销毁

java 复制代码
//创建Cookie
Cookie cookie = new Cookie("key","value");
//添加Cookie
resp.addCookie(cookie);

代码示例

java 复制代码
        //创建Cookie
        Cookie cookie = new Cookie("word","helloWorld");
        //将cookie对象写回给客户端浏览器
        resp.addCookie(cookie);
        resp.setContentType("text/plain;charset=utf-8");
        try(PrintWriter pw = resp.getWriter()){
            pw.println("name:"+cookie.getName());
            pw.println("value:"+cookie.getValue());
            pw.println("Cookie创建好了");
            pw.flush();
        }

获取Cookie中的数据

浏览器每次请求时都会把与当前域名相关的Cookie在请求中提交到服务端,通过HttpServletResponse对象获取Cookie,返回Cookie数组

java 复制代码
Cookie[] cookies = request.getCookies()

代码示例:

java 复制代码
       resp.setContentType("text/plain;charset=utf-8");
        //获取Cookie
        Cookie[] cookies = req.getCookies();

        try(PrintWriter pw = resp.getWriter()) {
            for (int i = 0; i < cookies.length; i++) {
                String name = cookies[i].getName();
                String value = cookies[i].getValue();
                pw.println("name:"+name);
                pw.println("value:"+value);
            }
            pw.flush();
        }
解决Cookie不支持中文问题

在Servlet4.0版本后的Cookie中name不能使用中文,但是value可以使用中文。

如果存储的数据里面含有中文,代码会直接出现异常,我们可以对含有中文的数据进行重新编码来解决该问题。

ULREncoder.encode("content","code");

将内容按照指定的编码方式做URL编码处理。

URLDecoder.decode("content","code")

将内容按照执行的编码做URL解码处理

代码示例:

java 复制代码
//创建Cookie
        Cookie cookie = new Cookie(URLEncoder.encode("姓名","utf-8"), URLEncoder.encode("张三","utf-8"));
        //设置cookie有效时间
        cookie.setMaxAge(60);

解码:

java 复制代码
//进行解码处理
                pw.println("name:"+ URLDecoder.decode(name,"utf-8"));
                pw.println("value:"+URLDecoder.decode(value,"utf-8"));

编码和解码的编码格式必须是一样的。

状态Cookie和持久化Cookie

状态cookie:Cookie对象仅仅会被缓存在浏览器所在的内存中,当浏览器关闭后Cookie对象也就会被销毁。

持久化Cookie:浏览器对Cookie做持久化处理,基于文件形式保存Cookie在系统的执行目录中。

当Cookie创建后默认是状态Cookie,可以使用cookie.setMaxAge();方法设置失效时间,单位为秒

一旦设置了失效时间,该Cookie就变成了持久化Cookie.浏览器就会将该Cookie持久化到磁盘里,当失效时间到达后删除。

注意:Cookie对于存储内容是基于明文方式存储的,安全性低,不要存放敏感数据,

在servlet4.0虽然支持中文,建议对Cookie中存放的数据做编码处理,可提高安全性。

HttpSession对象

特点:

保存在服务端,使用key与value结构存储数据,key是字符串类型,value是Object类型

存储数据大小没有限制

HttpSession对象的创建

通过request.getSession()方法创建

客户端浏览器在请求服务端资源时,

如果请求中没有jsessionid,getSession()方法将会为这个客户端浏览器创建一个新的HttpSession对象,并为这个HttpSession对象生成jsessionid,在响应中通过状态Cookie写回给客户端浏览器,

如果在请求中包含了jsessionid,getSession()方法则是根据这个ID返回与这个客户端浏览器对应的HttpSession对象。

getSession()方法重载方法getSession(true|false);

当参数为true时与getSession()方法相同,

当参数为false时则只去根据jsessionid查找是否有与这个客户端浏览器对应的HttpSession对象,如果有则返回,如果没有则不会创建新的HttpSession对象。

HttpSession对象常用方法

|---------------------------|-----------------------------------|
| 方法 | 描述 |
| setAttribute("key",value) | 将数据存储到HttpSession对象中 |
| getAttribute("key") | 根据key获取HttpSession中的数据,返回Object |
| getAttributeNames() | 获取HttpSession中所有的key,返回枚举类型 |
| removeAttribute("key") | 根据key删除HttpSession中的数据 |
| getId() | 获取当前HttpSession的SessuonID,返回字符串类型 |

通过HttpSession对象存数据

java 复制代码
        resp.setContentType("text/plain;charset=utf-8");
        //创建HttpSession对象
        HttpSession session = req.getSession();
        //添加数据
        session.setAttribute("name","jack");
        session.setAttribute("age",30);
        String sessionId = session.getId();
        System.out.println(sessionId);
        try(PrintWriter pw = resp.getWriter()){
            pw.println(sessionId);
            pw.println("存好数据了");
            pw.flush();
        }

通过HttpSession取数据

java 复制代码
        resp.setContentType("text/plain;charset=utf-8");
        //创建HttpSession对象
        HttpSession session = req.getSession();
        //获取所有的name
//        Enumeration<String> attributeNames = session.getAttributeNames();
        try(PrintWriter pw = resp.getWriter()) {
//            while (attributeNames.hasMoreElements()) {
//                String name = attributeNames.nextElement();
//            }
            //通过key获取数据
            pw.println(session.getAttribute("name"));
            pw.println(session.getAttribute("age"));
            pw.flush();
        }

HttpSession对象的销毁方式

  • 通过web.xml文件指定销毁时间
  • 通过HttpSession对象中的invalidate()方法销毁当前HttpSession对象

web.xml文件指定超时时间,当达到超时时间后容器就会销毁该HttpSession对象,单位为分钟

XML 复制代码
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>

时间计算是根据最后一次访问请求时间作为起始时间的,只要用户继续访问,服务器就会更新HttpSession对象的最后访问时间。

如果是在Tomcat的web.xml配置了超时时间,相当于配置了全局的HttpSession超时时间,如果同时也在web项目中配置了超时时间,则会以web项目中的超时时间为准。

invalidate()是HttpSession对象中提供的用于销毁当前HttpSession的方法。

HttpSession对象的生命周期

HttpSession对象生命周期中没有个固定的创建时间和摧毁时间。什么时候创建取决于什么时候调

用getSession(),HttpSession对象的销毁时间取决于超时时间以及调用invalidate();

如果没有超过超时时间或者通过invalidate()摧毁,则会一直存在。

默认超时时间为30分钟。

HttpSession与Cookie的区别

  • cookie数据存在浏览器或者系统的文件里,HttpSession中的数据存放在服务器中
  • cookie是不安全的,而HttpSession是安全的
  • 单个cookie存储数据不能超过4k,很多浏览器都限制一个域名保存cookie的数量,HttpSession没有容量以及数量的限制

使用建议:

HttpSession中的数据存放在服务端的,安全性比较高。我们可以在HttpSession对象中存储数据,但是由于它的生命周期不固定,不建议存放业务数据,一般用来存放用户登录信息。

相关推荐
SomeB1oody4 分钟前
【Rust自学】5.1. 定义并实例化struct
开发语言·后端·rust
Q_192849990613 分钟前
基于Spring Boot的建材租赁系统
java·spring boot·后端
鲨鱼辣椒不吃辣c15 分钟前
拦截器魔法:Spring MVC中的防重放守护者
java·spring·mvc
winks321 分钟前
Spring Task的使用
java·后端·spring
云空26 分钟前
《解锁 Python 数据挖掘的奥秘》
开发语言·python·数据挖掘
秋意钟32 分钟前
Spring新版本
java·后端·spring
椰椰椰耶34 分钟前
【文档搜索引擎】缓冲区优化和索引模块小结
java·spring·搜索引擎
mubeibeinv35 分钟前
项目搭建+图片(添加+图片)
java·服务器·前端
青莳吖36 分钟前
Java通过Map实现与SQL中的group by相同的逻辑
java·开发语言·sql
Buleall44 分钟前
期末考学C
java·开发语言