Servlet——独立于平台和协议的服务器端的Java技术(下)

Servlet

在这里插入图片描述

学习目标

在这里插入图片描述

Cookie对象

Cookie是浏览器提供的一种技术,通过服务器的程序能将一些只须保存在客户端,或者在客户端进行处理的数据,放在本地的计算机上,不需要通过网络传输,因而提高网页处理的效率,并且能够减少服务器的负载,但是由于 Cookie 是服务器端保存在客户端的信息, 所以其安全性也是很差的,如常见的记住密码就是通过Cookie实现的

有一个专门操作Cookie的类 javax.servlet.http.Cookie

Cookie 的格式:键值对用“=”连接,多个键值对间通过“;”隔开

1 Cookie的创建和发送

创建Cookie对象

new Cookie("key","value")

发送Cookie对象

response.addCookie(Cookie对象);

例:

// 创建Cookie对象 
Cookie cookie = new Cookie("uname","zhangsan"); 
// 发送Cookie对象 
response.addCookie(cookie);

进入浏览器后按F12可查看

2 Cookie的获取

在服务器端只提供了一个 getCookies()的方法用来获取客户端回传的所有 cookie 组成的一个数组,如果需要获取单个 cookie 则需要通过遍历

getName()获取 Cookie 的名称

getValue()获取 Cookie 的值

// 获取Cookie数组
Cookie[] cookies = request.getCookies();
// 判断数组是否为空
if (cookies != null && cookies.length > 0) {
    // 遍历Cookie数组
    for (Cookie cookie : cookies){
        //获取 Cookie 的名称
        System.out.println(cookie.getName());
        //获取 Cookie 的值
        System.out.println(cookie.getValue());
    }
}

3 Cookei设置到期时间

到期时间用来指定该 cookie 何时失效,默认为当前浏览器关闭即失效

以手动设定 cookie 的有效时间(通过到期时间计算),通过 **setMaxAge(int time);**方法设定 cookie 的最大有效时间,以秒为单位

到期时间的取值:

取值结果
负整数不存储该cookie
正整数储存该cookie的秒数
删除该cookie
// 创建Cookie对象
Cookie cookie = new Cookie("uname","zhangsan");
// 设置Cookie 3天后失效
cookie.setMaxAge(3 * 24 * 60 * 60);
// 发送Cookie对象
response.addCookie(cookie);

4 Cookie路径

cookie的路径指的是可以访问该cookie的顶层目录,该路径的子路径也可以访问该cookie

Cookie的setPath设置cookie的路径,这个路径直接决定服务器的请求是否会从浏览器中加载某些cookie

当访问的路径包含了cookie的路径时,则该请求将带上该cookie;

如果访问路径不包含cookie路径,则该请求不会携带该cookie

5 Cookie注意问题

1、Cookie只保存在当前浏览器中,不能跨浏览器

2、服务器端发送重复的Cookie那么会覆盖原有的Cookie

3、不同的浏览器储存的Cookie数量不同且有上限

4、Cookie存中文问题

Cookie 中是不能出现中文,如果有中文则通过 URLEncoder.encode()来进行编码,获取时通过 URLDecoder.decode()来进行解码

// 设置中文储存数据
String name = "姓名";
String value = "张三";

// 通过 URLEncoder.encode()来进行编码
name = URLEncoder.encode(name);
value = URLEncoder.encode(value);

// 创建Cookie对象
Cookie cookie = new Cookie(name,value);
// 发送Cookie对象
response.addCookie(cookie);

// 获取时通过 URLDecoder.decode()来进行解码
URLDecoder.decode(cookie.getName());
URLDecoder.decode(cookie.getValue());

HttpSession对象

HttpSession对象是 javax.servlet.http.HttpSession 的实例,该接口并不像 HttpServletRequest 或HttpServletResponse 还存在一个父接口,该接口只是一个纯粹的接口。这因为 session 本身就属于HTTP 协议的范畴

session 无论客户端还是服务器端都可以感知到,若重新打开一个新的浏览器,则无法取得之前设置的 session,因为每一个 session 只保存在当前的浏览器当中,并在相关的页面取得

Session 的作用就是为了标识一次会话,或者说确认一个用户,并且在一次会话期间共享数据

通过**request.getSessions()方法来获取当前会话的session对象**

// 如果session对象存在,则获取;如果session对象不存在,则创建 
HttpSession session = request.getSession();

1 标识符 JSESSIONID

Session 既然是为了标识一次会话,那么此次会话就应该有一个唯一的标志,这个标志就是sessionId

每当一次请求到达服务器,如果开启了会话(访问了 session),服务器第一步会查看是否从客户端回传一个名为 JSESSIONID 的 cookie,

如果没有则认为这是一次新的会话,会创建 一个新的 session 对象,并用唯一的 sessionId 为此次会话做一个标志。
如果有 JESSIONID 这个cookie回传,服务器则会根据 JSESSIONID 这个值去查看是否含有id为JSESSION值的session 对象,
如果没有则认为是一个新的会话,重新创建一个新的 session 对象,并标志此次会话;
如果找到了相应的 session 对象,则认为是之前标志过的一次会话,返回该 session 对象,数据达到共享

这里提到一个叫做 JSESSIONID 的 cookie,这是一个比较特殊的 cookie

当用户请求服务器时,如果访问了 session,则服务器会创建一个名为 JSESSIONID,值为获取到的 session的 sessionId 的 cookie 对象,并添加到 response 对象中,响应给客户端,有效时间为关闭浏览器

所以 Session 的底层依赖 Cookie 来实现

2 session域对象

Session表示一次会话,在一次会话中数据是共享的,此时session作为域对象存在

通过 setAttribute(name,value) 方法向域对象中添加数据

通过 getAttribute(name) 方法从域对象获取数据

通过 removeeAttribute(name) 方法从域对象中移除数据

// 获取session对象 
HttpSession session = request.getSession();

// 设置session域对象
session.setAttribute("uname","admin");

// 获取指定名称的session域对象
String uname = (String) request.getAttribute("uname");

// 移除指定名称的session域对象
session.removeAttribute("uname");

数据存储在 session 域对象中,当 session 对象不存在了,或者是两个不同的 session 对象时,数据就不能共享了

3 session对象的销毁

1 默认时间到期

当客户端第一次请求 servlet 并且操作 session 时,session 对象生成,Tomcat 中 session 默认的存活时间为 30min,即你不操作界面的时间,一旦有操作,session 会重新计时

可以在 Tomcat 中的 conf 目录下的 web.xml 文件中进行修改默认到期时间

<!-- session 默认的最大不活动时间。单位:分钟。 --> 
<session-config>
    <session-timeout>30</session-timeout> 
</session-config>
2 自己设定到期时间

通过 session.setMaxInactiveInterval(int) 来设定 session 的最大不活动时间,单位为秒

//获取session对象
HttpSession session = requestgetSession();

//设置session的最大不活动时间
session.setMaxInactiveInterval(30);	//30秒

通过 getMaxInactiveInterval() 方法来查看当前 Session 对象的最大不活动时间

//获取session的最大不活动时间
int time = session.getMaxInactiveInterval();
3 立刻失效

以通过 session.invalidate() 方法让 session 立刻失效

//销毁session对象
session.invalidate();

ServletContext对象

每一个 web 应用都有且仅有一个ServletContext 对象,又称 Application 对象

在 WEB 容器启动的时候,会为每一个 WEB 应用程序创建一个对应的 ServletContext 对象

作用:

1、作为域对象用来共享数据

2、保存了当前应用程序相关信息

1 常用方法

获取 ServletContext 对象(四种方式)

1、通过 request 对象获取

ServletContext servletContext = request.getServletContext();

2、通过 session 对象获取

ServletContext servletContext = request.getSession().getServletContext();

3、通过 ServletConfig() 方法来获取

ServletContext servletContext = getServletConfig.getServletContext();

4、直接通过ServletContext 获取

ServletContext ServletContext = getServletContext();

获取项目存放的真实路径

String realPath = request.getServletContext().getRealPath("/");

获取当前服务器的版本信息

String serverInfo = request.getServletContext().getServerInfo();

2 ServletContext 域对象

通过向 ServletContext 中存取数据,可以使得整个应用程序共享某些数据。

当然不建议存放过多数据,因为 ServletContext 中的数据一旦存储进去没有手动移除将会一直保存

1、设置域对象

servletContext.setAttribute("name","zhangsan");

2、获取域对象

String name = (String) servletContext.getAttribute("name");

3、移除域对象

servletContext.removeAttribute("name");

3 生命周期

创建:服务器启动的时候,服务器为每个WEB应用创建一个属于该web项目的对象ServletContext类

销毁服务器关闭或者项目从服务器中移除的时候

有效:在整个服务器上被保留

文件上传和下载

使用 servlet 可以实现文件的上传和下载

文件上传

文件上传涉及到前台页面的编写后台服务器端代码的编写前台发送文件,后台接收并保存文件,这才是一个完整的文件上传

1 前台页面

页面里需要存在表单

表单的请求方式必须为post ----> method="post"

表单的类型必须为文件上传表单 ----> enctype="multipart/form-data"

<form action="upload" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="uname">
    文件:<input type="file" name="myFile">
    <input type="submit" value="提交">
</form>
2 后台实现

使用注解 @MultipartConfig 将一个 Servlet 标识为支持文件上传

Servlet 将 multipart/form-data 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作

package com.xxxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;

@WebServlet("/upload")
@MultipartConfig    //表单上传文件必须添加的注解@MultipartConfig
public class UploadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求的编码格式 
        request.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");
        //获取表单用户名的值
        String name = req.getParameter("name");
        //获取表单中文件的name值
        Part part = req.getPart("myFile");
        //获取上传的文件名
        String fileName = part.getSubmittedFileName();
        //根据ServletContext获取文件的路径
        String filePath = req.getServletContext().getContextPath();
        //将路径上传到指定位置
        part.write(filePath+fileName);
    }
}

文件下载

将服务器上的资源下载(拷贝)到本地

有两种方式:

1、通过超链接本身的特性:download

2、通过代码下载

1 超连接下载

默认下载

<!-- 当超链接遇到浏览器不识别的资源时,会自动下载,如压缩包 --> 
<a href="test.zip">超链接下载</a>

指定 download 下载

<!-- 当超链接遇到浏览器识别的资源时,默认不会下载。通过download属性可进行下载 --> 
<a href="test.txt" download>超链接下载</a>

注意:

download 属性可以不写任何信息,会自动使用默认文件名

如果设置了download属性的值,则使用设置的值做为文件名

当用户打开浏览器点击链接的时候就会直接下载文件

2 后台实现下载

前台页面设置下载路径

<a href="download?filename=test.txt">下载文件</a>

后台代码实现

package com.xxxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取文件路径
        String filePath = req.getServletContext().getContextPath();
        //获取文件名
        String fileName = req.getParameter("name");
        //通过路径和文件名获得对象
        File file = new File(filePath+fileName);
        //判断文件是否存在且不为文件夹,是则读写文件内容,否则不读取数据
        if(file.exists() || file.isFile()){
            //设置响应类型
            resp.setContentType("application/x-msdownload");
            //设置响应头信息
            resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            //输入流
            InputStream is = new FileInputStream(file);
            //输出流
            ServletOutputStream os = resp.getOutputStream();
            //定义数组
            byte[] b = new byte[1024];
            int len = -1;
            //循环读取数据
            while((len = is.read(b)) != -1){
                os.write(b,0,len);
            }
            //释放资源
            os.flush();
            os.close();
            is.close();
        }else{
            System.out.println("文件下载失败!!!请重试");
        }
    }
}

过滤器Filter

Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改

对于Web应用程序来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和服务器端之间的请求与响应信息,对其修改或过滤

过滤器原理
在这里插入图片描述

作用如下:

  1. 在客户访问后台资源之前拦截客户请求
  2. 在资源被送到客户端之前加以控制
  3. Servlet过滤器负责过滤的Web组件可以是Servlet、JSP或HTML文件

在一个Web应用程序中,可以部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链

过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到服务器端的Servlet

过滤器链原理
在这里插入图片描述

Filter接口

过滤器实现 javax.servlet.Filter 接口,注解为**@WebFilter**,必须按顺序执行并重写3个方法

1、init(FilterConfig filterConfig)

初始化配置参数

2、doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)

在客户端请求及服务器端回复时自动调用

ServletRequest和ServletResponse必须先转换成HttpServletRequest 和HttpServletResponse 才能使用

HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;

3、destroy()

销毁过滤器

Filter生命周期(饿汉单例) :

创建 初始化 服务 销毁

应用

  • 字符集处理
  • 用户访问权限判断
  • 积分下载资源
  • 水印处理
  • “和谐词语”修改替换
  • 缓存处理
  • 自动登录案例

字符集处理实例:

package com.xxxx.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*")
public class CharsetFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init......");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        //转型
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //设置编码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //放行
        filterChain.doFilter(req,resp);
    }

    @Override
    public void destroy() {
        System.out.println("destroy......");
    }
}

注意:

@WebFilter("/*") 表示为所有java类都可以进行过滤,

需要指定某些时可以直接加后缀,如@WebFilter(".do") @WebFilter(".action")

监听器Listener

监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行

监听原理

1、存在事件源

2、提供监听器

3、为事件源注册监听器

4、操作事件源,产生事件对象,将事件对象传递给监听器,并且执行监听器相应监听方法

JAVAweb 提供了八大监听器,给Web应用增加事件处理机制,以便更好地监视和控制Web应用的状态变化,从而在后台调用相应处理程序,其主要控制application session request对象的发生的特定事件

JAVAweb八大监听器

监听事件都要实现监听接口

监听对象实现监听接口监听事件
ServletRequestServletRequestListenerServletRequestEvent
ServletRequestAttributeListenerServletRequestAttributeEvent
HttpSessionHttpSessionListenerHttpSessionEvent
HttpSessionActivationListener
HttpSessionAttributeListenerHttpSessionBindingEvent
HttpSessionBindingListener
ServletContextServletContextListenerServletContextEvent
ServletContextAttributeListenerServletContextAttributeEvent

生命周期及作用

ServletRequest

创建:启动服务器时创建

销毁:关闭服务器或者从服务器移除项目

作用:利用ServletContextListener监听器在创建ServletContext域对象时完成一些想要初始化的工作或者执行自定义任务调度

HttpSession

创建:访问服务器任何资源都会发送请求(ServletRequest)出现,访问.html和.jsp和.servlet都会创建请求

销毁:服务器已经对该次请求做出了响应

作用:每一个会话只能访问当前会话作用域,在线多人登录

ServletContext

创建:只要调用了getSession()方法就会创建,一次会话只会创建一次

销毁:1.超时(默认为30分钟) 2.非正常关闭,销毁 3.正常关闭服务器(序列化)

作用:每位用户登录网站时都会创建一个HTTPSession对象,利用这个统计在线人数

简单实现监听 ServletContext

只要服务器开启就执行 contextInitialized() 方法

服务器销毁就执行 contextDestroyed() 方法

HttpSession和ServletContext同理

package com.xxxx.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ServletListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContextListener创建。。。");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContextListener销毁。。。");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值