Java开发网站的核心servlet

得意时要看淡,失意时要看开。不论得意失意,切莫大意;不论成功失败,切莫止步。志得意满时,需要的是淡然,给自己留一条退路;失意落魄时,需要的是泰然,给自己觅一条出路Java开发网站的核心servlet,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

xi## web服务与web浏览器
1、Web服务器用于存储网站的所有信息和数据;而Web浏览器是用来访问和定位这些信息和数据。

2、Web浏览器发送HTTP请求,获取HTTP响应,并显示Web文档,而Web服务器获取HTTP请求,生成响应,并接受客户端数据。

3、Web浏览器用于通过网络与Web服务器链接。

4、Web服务器的主要组件是服务器核心,服务器核心64位二进制文件,应用程序,管理命令行界面等;而Web浏览器的组件是用户界面,UI后端,布局和渲染引擎,以及网络和数据持久性零件。

web服务器只起存储功能,web浏览器获取文档并展示,通过http协议通信。

静态网页与动态网页
如浏览器存储的静态网页,那么用户只能获取特定的一些网页,都是静态填充好的。如果存储的是动态网页,动态网页是需要汇编语言解析的。页面会动态的发生变化,就是服务器对用户行为做出相应的反应。汇编语言的运行需要相应的运行时环境如java的jre,而且数据也是汇编语言从数据库中获取的。

总结来说,web服务器就是搭载汇编语言运行时环境的,具有存储功能的,能提供http服务的软件。

web容器

处理动态网页的汇编语言有多种如java,python,js等,如果服务器存储多种不同的动态网页,就需要不同的运行时环境,所以就要有不同的线程来处理不同的内容。这就是web容器,不同容器中处理不同的动态网页。web容器并不直接对接http服务,而是web服务器解析后将文档共享给web容器,web容器随数据生成动态网页后将文档返回给web服务器,再由起封装http协议。而servlet就是java处理动态网页的容器
在这里插入图片描述

servlet简介

servlet就是一个web容器,其主要功能就是解析动态网页。同时Servlet 也是运行在带有支持 Java Servlet 规范的解释器的 web 服务器上的 Java 类。(也就是说,编写一个servlet类,存储在web服务器中,那么它就成为服务器处理java web的web容器)再这个类中解析动态网页。其通过 javax.servlet 包创建。servlet运行在服务器端,需要服务器软件。创建一个web容器就是创建一个servlet类,然后编写处理动态网页的代码。

访问一个动态网页的过程,实际上是将对应的 Servlet 类加载、实例化的过程。

servlet生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 通过调用 init () 方法进行初始化。

init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。
Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,也可以指定 Servlet 在服务器第一次启动时被加载。当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

  • Servlet 调用 service() 方法来处理客户端的请求并返回数据。

Servlet 容器调用 service() 方法来处理的请求,并把格式化的响应返回。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),调用 doGet、doPost、doPut,doDelete 等方法。

  • Servlet 通过调用 destroy() 方法终止,servelt不要响应,动态页面无法访问。

Servlet 容器关闭、重启或移除 Servlet 实例时,容器就会调用 destory() 方法,释放该实例使用的资源,例如:关闭数据库连接,关闭文件的输入流和输出流等。

  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

servlet实现类

Servlet 规范的最顶级是一javax.servlet.Servlet 的接口,所有的 Servlet 类都要直接或者间接地实现该接口。Servlet 接口 又内置了两个接口的实现类(抽象类),分别为 GenericServlet 和 HttpServlet。

  • 如果直接实现 javax.servlet包下的Servlet 接口,就要重写其全部方法。
//导入javax.servlet包下的Servlet接口
import javax.setvlet.Servlet
public class MyMervlet implements Servlet{
	  //Servlet 实例被创建后,调用 init() 方法进行初始化,该方法只能被调用一次
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    }
    //每次请求,都会调用一次 service() 方法
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //设置字符集
        servletResponse.setContentType("text/html;charset=UTF-8");
        //使用PrintWriter.write()方法写入文档,由web服务器封装http包响应浏览器
        PrintWriter writer = servletResponse.getWriter();
        writer.write("Hello Servlet");
        writer.close();
		//浏览器接收http包后解析,导出文档,当作html运行,Hello Servlet就打印了
    }
    //Servelet 被销毁时调用
    @Override
    public void destroy() {
    }
     //返回 ServletConfig 对象,该对象包含了 Servlet 的初始化参数
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    //返回关于 Servlet 的信息,例如作者、版本、版权等
    @Override
    public String getServletInfo() {
        return null;
    }
}
  • 继承 GenericServlet 抽象类创建 Servlet,只重写service方法
import javax.setvlet.Servlet.GenericServlet 
//其他的方法官方已经编写,如果不满足需要也可以重写
public class ServletDemo extends GenericServlet {

    @Override
    public void service(ServletRequest arg0, ServletResponse arg1)
            throws ServletException, IOException {
        ......

    }
}

GenericServlet实现类除了继承Servlet的方法外还实现了新的方法:
在这里插入图片描述

  • javax.servlet.http.HttpServlet 抽象类,继承了GenericServlet抽象类,它只需要重写service中针对http服务的那部分。在GenericServlet抽象类需要在service方法中写判断逻辑是get还是post等方法,然后再去写对应的处理逻辑,但是在.HttpServlet 抽象类,不需要在写判断逻辑,继承的service方法中已经写好了判断的逻辑而且调用了对应的处理逻辑的方法,(方法写在serice外部,在serice中调用)这些方法是抽象方法没有方法体,只需要在器继承类中重写的处理逻辑就可以了。如下图
    在这里插入图片描述
    Servlet、GenericServlet和HttpServlet之间的关系感谢作者的图@Lin_Dong_Tian
    在继承类的对应的请求方法内部写处理逻辑就可以了。实例开发中请求的方法一般都是get或post,其他比较少用
public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	//设置处理请求的编码格式
    	request.setCharacterEncoding("utf-8");
        //设置响应文档的编码格式
        response.setContentType("text/html;charset=UTF-8");
        //IO输出流输出处理后的文档
        PrintWriter writer = resp.getWriter();
        writer.write("Hello World");
        writer.close();
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //一次请求不管请求方法是什么,处理逻辑都是相同的
        doGet(request, response);
    }
}

构建工程化项目结构

在编写servlet容器时,IDE中肯定不会只放servlet,如果需要访问数据路,还需要orm模型,需要jdbc的的开发工具包,配置servlet的路径的配置文件web.xml,java源码等,那么这些都该放在什么地方呢?那个目录下呢?这就需要构建工程化的项目了,对应的文件放在对应的目录才不会出错。

  • 在eclispe中:
    在这里插入图片描述
    选择 Dynomic web project动态网页项目
    在这里插入图片描述
    点击Target runtime行末的New Runtime,选择Apache下的相应的Tomcat服务器版本,创建的目录如下:
    在这里插入图片描述
    src中存放java源码,WEB-INF存放编译后的.class文件,lib存放需要的jar工具包(后俩不需要管),主要把要用的包导入到lib下就可以了。build时写完后打包存放的目录。src的mvc架构需要自己建。当然也可以学maven,直接建maven project更方便。

在package中新建可以直接建servlet,运行时需要配置Tomcat
在这里插入图片描述
点击add,查找下载的路径到如下的目录即可
在这里插入图片描述

package controller;

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;

@WebServlet("/Servlet_01")
public class Servlet_01 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public Servlet_01() {
        super();
        // TODO Auto-generated constructor stub
    }


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().write("Hello World");
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

//继承httpservlet之前有一个注解@WebServlet(“/Servlet_01”)这是对servlet的路径配置。
在这里插入图片描述

也可以建web.xml配置。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0" metadata-complete="true">
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>controller.Servlet_01</servlet-class>
    </servlet>
   <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/controller</url-pattern>
    </servlet-mapping>
</web-app>

运行成功:
在这里插入图片描述
web.xml 中各元素含义及用法如下:

<web-app>: 根元素。
<servlet> :用于注册 Servlet,即给 Servlet 起一个独一无二的名字。
<servlet> 包含两个主要的子元素 <servlet-name><servlet-class>,分别用于指定 Servlet 的名称和 Servlet 的完整限定名(包名+类名)。
<servlet-mapping> :用于定义 Servlet 与 URL 之间的映射。
<servlet-mapping> 包含两个子元素 <servlet-name><url-pattern>,分别用于指定 Servlet 的名称和虚拟路径。

load-on-startup 是 web.xml 中的一个节点,是 servlet 元素的子元素,用来标记 Servlet 容器启动时是否初始化当前 Servlet,以及当前 Servlet 的初始化顺序。

  • 在idea中:
    idea和eclipse原理都一样,都是那几个目录,自行参考把,也可以看之前的文章iead创建web工程化项目

处理请求逻辑的对象 HttpServletRequest

http携带的参数被处理后封装在 HttpServletRequest对象中,对该对象解析可以获取客户端信息以及请求的相关信息。
HTTP 请求消息分为请求行、请求消息头和请求消息体三部分,所以 HttpServletRequest 接口中定义了获取请求行、请求头和请求消息体的相关方法。

  • 获取请求行信息
    HTTP 请求的请求行中包含请求方法、请求资源名、请求路径等信息,HttpServletRequest 接口定义了一系列获取请求行信息的方法,如下表。
    用于获取参数的方法:
    在这里插入图片描述
  • 获取请求行GET方法的数据
    在这里插入图片描述

😒
😮
😒
😐

  1. a标签的超链接发送get请求,参数直接传递给url,再由浏览器封装http协议。
  2. form表单发送get请求,再由浏览器封装http协议。
  3. 调用Javascript的xmlhttprequest对象发送get请求。

get请求只能发送application/x- www-form-urlencoded格式的数据,像form表单和a标签都是这种类型。该类型的请求内容提供了request.getParameter()方法来获取请求参数值。

  • 获取请求头信息
    当浏览器发送请求时,需要通过请求头向服务器传递一些附加信息,例如客户端可以接收的数据类型、压缩方式、语言等。HttpServletRequest 接口定义了一系列用于获取 HTTP 请求头字段的方法。

在这里插入图片描述

  • 获取请求体信息获取POST请求数据
    请求体主要是封装请求携带的数据的,请求体的数据一般没有大小限制(请求行有限制)。而且不想get有数据类型的限制,post方法可以发送多种数据类型的数据,也更安全。请求体的内容发送到服务器后会直接通过IO输入流写入缓冲区。HttpServletRequest 接口定义了一系列用于获取 HTTP 请求体内容的方法。
返回值类型 方法声明 描述
BufferedReader getReader() 该方法用于获取写入请求体写入缓冲区中的字符流数据
InputStream getInputStream() 该方法用于获取请求体传递的字节流数据
  • 设置请求信息
方法声明 描述
setCharacterEncoding() 该方法用于设置解析请求数据的编码格式

处理响应逻辑的对象HttpServletResponse

Servlet 容器会针对每次请求创建一个 response 对象,并把它作为参数传递给 Servlet 的 service 方法。Servlet 处理请求后,会将响应信息封装到 response 对象中,并由容器解析后返回给客户端。

  • 设置响应行的方法
    在这里插入图片描述
  • 设置响应头的方法
    在这里插入图片描述
  • 设置响应体的方法
    响应体就是响应数据存储的地方。用Io输出流将其存储在文件中,将文件的内容发送给封装在http协议中发送给前端。
返回类型 方法声明 描述
OutputStream getOutputStream() 该方法用于创建文件并存储二进制数据
PrintWriter getWriter() 该方法用于创建文件并存储字符数据
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;

@WebServlet("/Servlet_01")
public class Servlet_01 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public Servlet_01() {
        super();
        // TODO Auto-generated constructor stub
    }


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("utf-8");
		PrintWriter out=response.getWriter();
		out.write("Hello World");
		
	}	
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

servlet转发与重定向

请求转发就是将该页面的请求和响应对象转发到其他servlet中,实现共用一次http请求。如果需要添加其他数据servlet也提供了域对象用于存储额外数据。

方法声明 描述
getRequestDispatcher().forward(req,res) 该方法将域对象转发到其它servlet中,参数是路径
setAttribute() 该方法用于将请求信息存储到请求域中,其功能是实现servlet之间的通信(servlet之间传递数据)
getAttribute() 该方法用于获取存储在请求域的数据
removeAttribute() 该方法用于删除域对象的数据
getAttributeNames() 该方法用于返回 request 对象中的所有属性名的枚举集合
request.getRequestDispatcher("/servlet_01").forward(req,res);

响应重定向就是跳转到其他网页,重定向请求数据就都丢失了。

方法声明 描述
sendRedirect() 该方法用于让浏览器访问新的 URL
response.sendRedirect("www.baidu.com");

Session与Cookie

  • 会话技术

从打开浏览器访问某个网站,到关闭浏览器的过程,称为一次会话。会话技术是指在会话中,帮助记录用户状态和数据的技术。

常用的会话技术分为两种:

  1. Cookie :客户端会话技术
  2. Session :服务端会话技术

Cookie

Cookie分为两种:

  1. 会话级别 Cookie(默认):Cookie 保存到浏览器的内存中,浏览器关闭则 Cookie 失效。
  2. 持久的 Cookie:Cookie 以文本文件的形式保存到硬盘上。

会话级别的Cookie用于服务器识别不同的浏览器,持久Cookie用于保存用户状态或用户数据。例如当你关闭浏览器后,便于服务器断开连接session销毁了,但再打开发现仍然处于登录状态,这就是持久的cookie的将用户信息存储在cookie中,发送到服务器直接用cookie中的信息登录,然后返回登录状态。

  • servlet提供Cookie的API用于操作cookie
Cookie cookie = new Cookie("key","value");

javax.servlet.http 包中定义了一个 Cookie 类,利用它的带参构造方法,可以创建 Cookie 对象。第一会话是没有发送cookie的,因为cookie再服务器生成,并响应增加到http响应头中。
在这里插入图片描述

javax.servlet.http.Cookie 类中提供了一系列获取或者设置 Cookie 的方法:
在这里插入图片描述

Session

Session 是服务器端会话技术。当浏览器访问 Web 服务器的资源时,服务器可以为每个用户浏览器创建一个 Session 对象,每个浏览器独占一个 Session 对象。

session与cookie是相辅相成的,浏览器第一次访问服务器会自动生成session,返回个浏览器作为浏览器的cookie,之后再带cookie发送浏览器就能识别是哪个了。

session只有会话级别,存储再服务器端的内存中,随服务器的关闭而销毁,当也可以编程式销毁。

  • servlet提供Session API用于操作session
HttpSession session=request.getSession();

session中存储的都key-value的类型。
在这里插入图片描述

+URL 重写维持服务器端会话
如果cookie被禁用的话,浏览器无法接收cookie对象,可以通过url重写来维持会话状态。在每个 URL 末尾追加一些额外的数据来标识 session 会话,服务器会把该 session 会话标识符与已存储的有关 session 会话的数据相关联。例如,http://w3cschool.cn/file.htm;sessionid=12345,session 会话标识符被附加为 sessionid=12345,标识符可被 Web 服务器访问以识别客户端。

URL 重写是一种更好的维持 session 会话的方式,它在浏览器不支持 cookie 时能够很好地工作

servlet处理文件上传

<input type="file" accept=".doc,.docx,.pdf,.txt,.htm,.html" />

当type类型为file时,浏览器会调用系统的文件资源管理器,打开文件夹选择文件然后上传资源。
一般上传的资源有: 文件,文件夹,图片,视频等 对于文件,图片,视频必须先解析为二进制流,再传递,然后再合成。例如图片也可以在上传时解析为base64的字符串传递,文件也可以。Apache提供了专业的工具来完成这一过程。FileUpload工具,有了这个神奇的工具,我们只需要选择要上传的文件,交由工具处理,然后在web容器(Servlet)按照官方提供的方法获取它并存储到指定位置就可以了,两款强有力的工具包。commons-fileupload-1.4-bin.zipcommons-io-2.11.0-bin.zip

对于文件夹的话就需要先压缩了了,将压缩包传给服务器。

文件上传的流程:

  1. 前端接口
<form action="/ServletDemo/FileUpload" method="post" enctype="multipart/form-data">
	<input type="file" name="file" size="50" />
	<br />
	<input type="submit" value="上传文件" />
</form>
//action是要提交的地址用同一个ide开发就是相对路径,分离就是绝对路径
//方法必须是post文件一般很大,只能由post
//enctype必须是multipart/form-data,它不对字符进行编码,用于发送二进制的文件。
//application/x-www-form-urlencoded只用于发送key-value的字符类型数据。
//text/plain用于发送纯文本内容。

2 . 引入工具包
在这里插入图片描述
在这里插入图片描述
引入到WEN-IN的lib目录下,没有就新建。
在这里插入图片描述
右键点击Build Path
在这里插入图片描述
在Referrenced Libraries中出现同样的jar包后即可了,目的是配置路径需要调用的时候知道工具包在哪。
在这里插入图片描述

  1. 根据根据工具包提供的类获取并解析上传的文件。

FileUpload 对象
在 HTML 文档中<input type="file">标签每出现一次,一个 FileUpload 对象就会被创建。

该元素包含一个文本输入字段,用来输入文件名,还有一个按钮,用来打开文件选择对话框以便图形化选择文件。

该元素的 value 属性保存了用户指定的文件的名称,但是当包含一个 fileupload 元素的表单被提交的时候,浏览器会向服务器发送选中的文件的内容而不仅仅是发送文件名。可以通过遍历表单的 elements[] 数组,或者通过使用 document.getElementById()来访问 FileUpload 对象。

Apache提供的两个工具包就是来解析发送的文件的。工具包提供了:
顶级类
org.apache.commons.fileupload类来处理HTML文件上传的组件。
子类及接口
org.apache.commons.fileupload.disk接口的基于磁盘的实现。
org.apache.commons.fileupload.servletFileUpload在servlet中使用的实现
还有另一个包的io流处理工具
org.apache.commons.io.*

//引入工具包,确保classpth中有响应的环境
import org.apache.commons.fileupload.disk.*;
import org.apache.commons.fileupload.servlet.*;
import org.apache.commons.io.*;

//servlet处理文件
public class UploadServlet extends HttpServlet {
	
	//文件上传只能用post方法
	 public void doPost(HttpServletRequest request, 
               HttpServletResponse response)
              throws ServletException, java.io.IOException {
		//调用工具包的servlet的实现类ServletFileUpload,用于获取前端的FileUpload对象
		//isMultipartContent()用于判断是否为文件上传
		 private boolean isFileUpload=ServletFileUpload.isMultipartContent(request);
		//true···false 的判断逻辑就不写了,只写上传的主体
		
		//fileUpload的最终实现类,获取的文件以这个类接收并处理处理
		 DiskFileItemFactory factory = new DiskFileItemFactory();
		//上面接收的文件需要io流输出但前提是先配置好其基本信息
		
		/*默认输出流在内存中接收,如果文件过大损耗服务器资源,
		setSizeThreshold()设置写入内存的阈值,大于会创建临时文件写入磁盘
		()中是字节   100*1024=100 kb
		1 B=8bit (1 字节= 8 比特)
		*/
		//返回用于临时存储大于配置大小阈值的文件的目录。
		factory.setSizeThreshold(100*1024);  
		
		//设置临时文件
		factory.setRepository(new File("c:\\Tomcat\\webapps\\data"));
		
		//文件对象及配置信息返回到servlet,由其处理
		/*
		上面对文件的处理只是工具包在完成,需要上传到服务器就要用servlet接口的ServletFileUpload的实现来处理
		*/
		 ServletFileUpload upload = new ServletFileUpload(factory);

		//允许文件上传的最大值
		upload.setSizeMax( 1024*1024 );
		
		//ServletFileUpload实现类的parseRequest(request)用于处理 multipart/form-data 类型的表单数据流,返回类型为List
		// 解析请求,获取文件项
      	List fileItems = upload.parseRequest(request);

		/*经过上面的解析以及获取到了文件的字节流数据并用List存储起来,
		那么那些是文件的信息那些是内容呢?还需要对List解析提出文件信息和文件内容
		*/
		/*
		<input type="file">提交的是一个fileUpload类型,和工具包fileupload下的FileItem是同一数据类型,接收的文件或表单项。该类中提供了许多方法来获取表单项或数据。
		*/
		//Iterator循环List提出文件内容的字节流写入文件
		Iterator i = fileItems.iterator();
		while ( i.hasNext () ) {
			//将元素强转FileItem类调用isFormField ()判断是否为表单项
         	FileItem fi = (FileItem)i.next();
         	if ( !fi.isFormField () ){
	            // 获取后缀名
	            String fieldName = fi.getFieldName();  //
	            //获取文件名
	            String fileName = fi.getName();
	            //回由浏览器传递的内容类型,如果未定义则为空。
	            String contentType = fi.getContentType();
	            //提供关于是否将从内存读取文件内容的提示。
	            boolean isInMemory = fi.isInMemory();
	            //获取文件大小
	            long sizeInBytes = fi.getSize();
          //根据获取的参数创建文件写入内容
          	//判断结尾
            if( fileName.lastIndexOf("\\") >= 0 ){
				//创建文件对象
               file = new File( filePath + 
               fileName.substring( fileName.lastIndexOf("\\"))) ;
            }else{
               file = new File( filePath + 
               fileName.substring(fileName.lastIndexOf("\\")+1)) ;
            }
            //FileItem的write方法将内容写入磁盘,这里判断是内容后才写入的磁盘
            fi.write( file ) ;
            //打印成功
            out.println("Upload Successfull: " + fileName + "<br>");
         }
      }
	}

	 //doGet方法直接返回错误
	 public void doGet(HttpServletRequest request, 
                       HttpServletResponse response)
        throws ServletException, java.io.IOException {
        
       response.getWriter().write("POST method required !");
   } 
}

成功再webapps下的data文件夹写入文件
在这里插入图片描述

过滤器 Servlet Filter

filter简介
过滤器能够对传给 Servlet 容器的Web 资源的 request 对象和 response 对象进行检查和修改。
主要有以下功能:

  • 在客户端的请求访问后端资源之前,拦截这些请求。
  • 在服务器的响应发送回客户端之前,处理这些响应。

其具体实现又有不同的类型:

  • 身份验证过滤器(Authentication Filters)。
  • 数据压缩过滤器(Data compression Filters)。
  • 加密过滤器(Encryption Filters)。
  • 触发资源访问事件过滤器。
  • 图像转换过滤器(Image Conversion Filters)。
  • 日志记录和审核过滤器(Logging and Auditing Filters)。
  • MIME-TYPE 链过滤器(MIME-TYPE Chain Filters)。
  • 标记化过滤器(Tokenizing Filters)。
  • XSL/T 过滤器(XSL/T Filters),转换 XML 内容。

过滤器被部署在部署描述符文件 web.xml 中,然后映射到您的应用程序的部署描述符中的 Servlet 名称或 URL 模式。当 Web 容器启动 Web 应用程序时,它会为您在部署描述符中声明的每一个过滤器创建一个实例。该过滤器执行的顺序是按它们在部署描述符中声明的顺序。

filter实现类及方法
过滤器要实现 javax.servlet.Filter 接口,并定义了 3 个方法,如下:

返回值类型 方法 描述
void init (FilterConfig filterConfig) 该方法用于初始化过滤器。
void doFilter(ServletRequest request,SeivletResponse response, FilterChain chain) 当客户端请求的 URL 与过滤器映射的 URL 匹配时,容器会先调用该方法对请求进行拦截。对参数 request 和 response 进行处理,参数 chain 代表当前 Filter 链对象,在该方法内部,调用 chain.doFilter() 方法,才能把请求交付给 Filter 链中的下一个 Filter 或者 Web 资源。
void destroy() 销毁 Filter 对象释放被占用的资源

filter执行流程
在这里插入图片描述
filter配置
基于xml:

//注册过滤器
<filter>
  <filter-name>MyFilter</filter-name>
  <filter-class>controller.MyFilter</filter-class>
  <init-param>
  	//初始化参数
    <param-name>prop</param-name>
    //参数值
    <param-value>Hello Filter</param-value>
  </init-param>
</filter>
//配置映射
<filter-mapping>
  <filter-name>MyFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
//Filter 的 init 方法中提供了一个 FilterConfig 对象,来获取初始化参数值。
public void  init(FilterConfig config) throws ServletException {
	// 获取初始化参数
	String prop = config.getInitParameter("prop"); 
	// 输出初始化参数
	System.out.println(prop); 
}

web.xml配置后就可以写处理逻辑了:

// 实现 Filter 类
public class MyFilter implements Filter  {
static String username;
Static String password;
   public void  init(FilterConfig config) 
                         throws ServletException{
      // 获取初始化参数
      String prop = config.getInitParameter("prop"); 

      // 密码加上初始化参数值用于加密,存储数据库的话
      password=password+prop;
   }
   public void  doFilter(ServletRequest request, 
                 ServletResponse response,
                 FilterChain chain) 
                 throws java.io.IOException, ServletException {
		//传递加密后的密码
      request.setAttribute("username",username);
      request.setAttribute("password",password);

      // 把请求传回过滤链
      chain.doFilter(request,response);
   }
   public void destroy( ){
      /* 在 Filter 实例被 Web 容器从服务移除之前调用 */
   }
}

基于注解@WebFilter 注解进行配置
在这里插入图片描述

监听器 Servlet Listener

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

  • 监听对象
    Servlet 规范中定义了 8 个监听器接口,用于监听ServletContext、HttpSession 和 ServletRequest 对象的生命周期和属性变化事件
  • 监听器分类
    监听对象创建和销毁的监听器
    在这里插入图片描述

监听对象中属性变更的监听器
在这里插入图片描述

监听 HttpSession 中的对象状态改变的监听器
在这里插入图片描述

  • 监听器注册
    监听器的注册同样有两种方式,在 web.xml 中注册监听器;使用 @WebListener 注册监听器。

在 web.xml 中使用 标签配置监听器,Web 容器会自动把监听器注册到事件源中

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">
    <listener>
        <listener-class>controller.Servlet</listener-class>
    </listener>
</web-app>

@WebListener 注解,可以将该 Java 类注册为一个监听器

利用Servlet和Filter统计网站访问量

原理:对于网站的访问不仅仅限于登录,未登录的访问也要统计。进入一个网页首先肯定会跳转到首页,在首页之前写一个servlet,然后跳转到首页,在servlet的路径下创建一个txt文件为一个时间和同一时间下访问次数(2022-02-120),在servlet的doGet方法或doPost方法中获取通过IO读取文件把0解析出来,通过与当前时间判断,相同就加一,不同就把旧的值写入到数据库,把新时间写入并赋值为1,然后再写入文件。这样每发送一个处理一个请求就相当于访问了一次。数据库也记录了每日的访问量。

//处理逻辑
	Date time=new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String timeFormat = sdf.format(time);
    //System.out.println(timeFormat);


    String path=getServletConfig().getServletContext().getRealPath("/");
    File file=new File(path+"total.txt");
    BufferedReader reader= null;
    reader = new BufferedReader(new FileReader(file));
    int result=0;
    String shijian="";
    String params;
    while ((params=reader.readLine())!=null){
        result=result+Integer.parseInt(params.substring(10));
        shijian=shijian+params.substring(0,10);
    }
    //System.out.println(result);
    reader.close();

    result=result+1;
    //System.out.println(result);
    FileWriter writer=new FileWriter(path+"total.txt");
    if(shijian.equals(timeFormat)){
        writer.write(String.valueOf(timeFormat)+String.valueOf(result));
    }
    else {
        writer.write(String.valueOf(timeFormat)+"0");
    }

    writer.flush();
    writer.close();


    SqlSessionFactory sqlSessionFactory11=new SqlsessionFactory().SqlsessionFactory();
    SqlSession session11=sqlSessionFactory11.openSession();
    BrwoerMapper mapper11=session11.getMapper(BrwoerMapper.class);

    List<String> list11=mapper11.selectIf(timeFormat);
    if (list11.size()==0){
        //System.out.println("no...");
        mapper11.insertOne(result, timeFormat);

    }
    else {
        //System.out.println("yes...");
        mapper11.updateOne(result, timeFormat);

    }
    session11.commit();
    session11.close();

文件
在这里插入图片描述
在这里插入图片描述
这端字符按String存储再解析程int类型,时间xxxx-xx-xx的格式是固定的,确保其后面的都是次数。注意代码上是时间不同就会插入到数据库,再初始化,不同是累加,所以第二天才会把前一天的访问量插入到数据库中。
在这里插入图片描述

filter原理一样,就不需要新建一个servlet直接再doFilter方法中写处理逻辑。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/156318.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!