什么是Servlet
- Servlet是Javaweb的三大组件(sevlet,listner,filter)之一,它属于动态资源,Servlet的作用是处理请求,服务器会吧接收到的请求交给Servlet来处理,在Servlet中通常需要:
- 接受请求数据
- 处理请求
- 完成响应
- 例如;客户端发出登录,注册等请求,这些请求都有Servlet来完成处理,Servlet由我们来完成编写,Servlet必须实现java.servlet.Servlet接口
- 每个Servlet都是唯一的,他们的功能是不一样的,比如一个Servlet是用来注册的,另一个servlet是用来登录的
实现Servlet接口的三种方式
- 实现java.servlet.Servlet接口(请查看Java ee 文档)
- 这个接口中一共有5个方法,其中声明周期方法有3个
- 声明周期的方法是服务器自动调用的
- destroy()servlet 销毁之前之前执行一次,不是这个方法销毁servlet
- init()servlet 创建之后,执行初始化方法
- service()服务器每次接收到一次请求,执行一次这个方法,每次处理请求都是使用的这个方法
- 剩下的两个方法
- getServletConfig()后去 servlet配置信息
- getServletInfo()获取servlet 的信息,一般没有什么用
- 特性:
- 一个类只有一个对象,服务器自动获取,但是可能存在多个Servlet类
- 线程不安全,效率高
- 解决线程不安全的三个解决方法:
- 不要定义成员变量,定义局部变量
- 创建无状态的成员
- 无状态类,也就是说类内部,没有对内部成员变量和外部变量的操作。简单来讲就是一个类中,的方法都不会操作内部和外部变量。
- 创建有状态的成员但是 只是可读的:比如定义一个属性,只有get方法,不给set方法,这样多个线程只能读取不能设置,实现了多线程的安全
- 这个接口中一共有5个方法,其中声明周期方法有3个
- 继承java.servlet.GenericServlet类
- 这个类是Servlet接口的实现抽象类,我们可以通过继承这个类来编写自己的类
- 继承java.servlet.http.HttpServlet类
- 这个类也是Servlet接口的一个实现类,用来面上http协议的
- Httpservlet原理
- 通常我们会使用继承HttpServlet来使用
如何访问 servlet
- 由于浏览器访问都是通过路径访问的
- 给servlet 指定一个个sevlet 路径,让servlet 和这个路径绑定在一起
- 浏览器通过路径访问servlet
- 访问过程分析
给Servlet配置Servlet路径
- 这个操作需要在WEB-INF下的web.xml中给Servet配置路径
格式:
<servlet> <servlet-name>xxx</servlet-name> <servlet-class>com.td.Text</servlet-class> </servlet> <servlet-mapping> <servlet-name>xxx</servlet-name> <!-- 两个servlet-name 必须名字是一样的 --> <servlet-pattern></servlet-pattern> <!--servlet-pattern这里必须是/开头 --> </servlet-mapping>
ServletConfig 接口介绍
- ServletConfig实例和servlet配置文件对应,一个ServletConfig 对应一个Servlet 实例
- 常用的方法
- getServletName()获取servlet的 名字,也就是获取web.xml中servlet配置配置的servlet-name的值
- getServletContext() 获取Servlet上下文
- getInitParameterNames()获取所有初始化参数的名字
- getInitParameter(String name) 获取指定的参数的名字
定义初始化参数
- 通过WEB-INF中的web.xml配置文件,定义初始化参数
- 位置 servlet标签内
- 可以定义多个
格式
<servlet> <init-param> <param-name>参数名</param-name> <param-value>参数值</param-value> </init-param> </servlet>
- 图解:
- 代码:
GenericServlet 自定义实现
自定义实现GenericServle类,
- 定义一个类,实现Servlet接口
- 封装一个ServletConfig对象,为当前类的 属性config
- 通过这个类的属性config实现,ServletConfig中的4个方法
代码如下:
package com.td; import java.io.IOException; import java.util.Enumeration; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public abstract class MyServlet implements Servlet { // 模拟GenericServlet类的方法,这个类的方法就是Servelet接口的方法加上,Servletconfig接口的四个方法,还有三个自带的方法没有重写。 private ServletConfig config = null; @Override // 当服务器关闭时,执行这个方法 public void destroy() { // TODO Auto-generated method stub } @Override public ServletConfig getServletConfig() { // TODO Auto-generated method stub return this.config; } @Override public String getServletInfo() { // TODO Auto-generated method stub return "getServletInfo() 执行了"; } @Override // 打开服务器,接受第一个请求的时候,执行这个方法。 public void init(ServletConfig config) throws ServletException { this.config = config; System.out.println("init()"); init(); } //自己定义了一个init方法,这样就可以,不用覆盖带有参数的init方法,并且能让功能进行扩展 public void init(){ } @Override // 服务器每次接收到一个请求,就执行一次这个方法 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub } // 一下是我 使用包装的属性,把ServletConfig中的方法进行封装到了自己定义的类中 public String getInitParameter(String name){ return this.config.getInitParameter(name); } public Enumeration<String> getInitParameterNames(){ return this.config.getInitParameterNames(); } public ServletContext getServletContext(){ return this.config.getServletContext(); } public String getServletName(){ return this.config.getServletName(); } // 自己实现了GenericServlet中的service方法 public abstract void service(ServletRequest req,ServletRequest res); }
HTTPServlet
- extends GenericServlet 继承GenericServlet
- 如果一个类继承了HTTPServlet那么,会调用service(ServletRequest,ServletResponse) 方法,这个方法调用service(HTTPServletRequest,HTTPServletResponse)方法,这个方式根据访问的方式,调用get 或者 put方法
- HTTPServlet中的访问 方式的方法,都是超出异常的。如果不重写,那么 就会报错405
- 所以我们需要重写访问方式的方法,如果没有重写,那么报错405
Servlet细节补充
- 线程安全问题
- 一个类只能有一个对象,这个对象是服务器自动获取的,多条线程访问会造成线程不安全的问题,但是也有解决方法
- 不要定义成员变量,定义局部变量
- 创建无状态的成员
- 创建有状态的成员但是 只是可读的:比如定义一个属性,只有get方法,不给set方法,这样多个线程只能读取不能设置,实现了多线程的安全
- 一个类只能有一个对象,这个对象是服务器自动获取的,多条线程访问会造成线程不安全的问题,但是也有解决方法
可以设置为服务器 启动就执行init方法
- 正常情况是,服务器启动后,接收到第一条请求,执行init方法
- 但是可以通过设置配置文件,让服务器启动就执行init方法
- 位置:web.xml 下的写在这里
格式:
<load-on-startup>这里填写非负数的整数</load-on-startup>
- 数字越小,先执行
-
- 用来指定Servlet的访问路径,必须是/开头,可以设置多个
- 也就是说一个Servlet可以有多个访问路径
- 可以使用通配符*号,但是不建议使用
- /servlet/*匹配前缀
- *.do匹配后缀
- /*匹配所有
- 不允许星号出现在URL中间
- 一个URL只能出现一个通配符*
web.xml文件的继承
- 每个Javaweb项目都有一个web.xml
- 所有的web.xml都是一个公共的父文件,每个项目都在使用这个配置文件,他在Tomcat–>conf–>web.xml
- 详解web.xml文件
- 当访问你的资源不存在的时候,它来处理
- 当请求jsp动态资源的时候,通过org.apache.jasper.servlet.JspServlet将动态资源转换成静态资源,响应给了客户端
- session 的过期时间
mime类型
欢迎页面设置
当请求jsp页面的时候,会根据jsp的url-pattern找到JspServlet,这个JspServlet将请求的jsp变成Java文件,在编译成class文件,创建对象,执行service方法
Servlet 和反射
- 服务器通过读取Java web项目中的web.xml 文件,
- 解析到Servlet的类名
- 通过反射获取Servlet实例(必须有空参数的 构造函数)
- 调用内部的方法
- ==以上操作都是由服务器来完成的==
ServletContext
- 概述:
- 一个项目只能有一个ServletContext对象,所以一般给这个对象命名application
- 可以在多个Servlet对象获取这个ServletContext对象,使用它可以在多个Servlet之间传输数据
- ==这个对象在服务器启动时就创建,服务器关闭时关闭==
- 获取ServletContext实例
- Servlet中的init方法传入的参数,是一个ServletConfig对象,调用这个对象的getServletConfig方法获取
- ServletConfig的方法getServletConfig 方法获取
- GenericServlet的getServletContext方法获取
- HttpServlet中的getServletContext方法获取
- HttpSession中的getServletContext方法获取
- ServletContextEvent中的getServletContext方法获取
- ServletContext常用的方法
- getServeltContextPath()这个方法会获取项目的路径,是个相对路径,经常用它来获取项目路径,然后进行资源路径的拼接,
域对象
- 域对象:就是在多个Servlet中传递数据的,
- 域对象必须有存储数据和获取数据的功能
Javaweb四大域对象
- ServletContext
- PageContext
- ServletRequest
- HttpSession
域对象内部都有个map用来存储数据,常用的方法
- setAttribute(java.lang.String name, java.lang.Object object)用来存储一个数据
- getAttribute(java.lang.String name) 获取值
- removeAttribute(java.lang.String name) 删除一个数据
- java.util.Enumeration
获取类(classes文件夹)路径下的资源
- 类路径资源对于javaweb项目而言,就是/WEB-INF/classes和WEB-INF/lib/每个jar包
==因为classes文件夹在WEB-INF内,这个文件夹是不能访问的,我们需要使用反射来获取内部的资源==
classLoader方式读取资源,相对的是服务器地址–>webapps–>Java web项目在下 WEB-INF –> classes文件夹
- 在Java web项目下的src目录下写的文件会被发送到classes文件夹下面
- 实例:
- class 方式读取资源
- 如果输入 的资源不带斜杠,相对的是资源所在目录
- 如果输入的资源带斜杠,那么相对的是classes文件夹
- 实例: