servlet
Servlet简介
Java Servlet是和平台无关的基于Java技术的Web组件,运行在服务器端,它由Servlet容器所管理,用于生成动态的内容。
Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类。
Servlet被编译为平台独立 的字节码,可以被动态地加载到支持Java技术的Web服务器中运行。
Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,Servlet和客户的通信采用“请求/响应”的模式。
Servlet的功能:
1:接收用户请求的HTTP协议,解析。
2:返回一个http的响应协议。让浏览器再去解析。
Servlet容器响应客户请求的过程
Servlet框架
配置Servlet
第一次访问请求:
第二次访问请求:
开发一个servlet,有三种方法
实现javax.servlet.Servlet接口
继承javax.servlet.GenericServlet
继承javax.servlet.http.HttpServlet(推荐)
一、servlet就是一个普通的类,创建一个servlet接口的实现类
1) public class HelloServlet implements Servlet{
2) 在web.xml中配置和映射servlet
<!-- 配置servlet和映射servlet --> <!-- 注册一个servlet --> <servlet> <!-- 注册名 --> <servlet-name>hello</servlet-name> <!-- servlet类的全类名 --> <servlet-class>com.java.servlet.HelloServlet </servlet-class> </servlet> <!-- 映射servlet --> <servlet-mapping> <!-- 必须和注册名一致 --> <servlet-name>hello</servlet-name> <!-- 浏览器访问路径 /代表当前web应用的根目录 --> <url-pattern>/hello</url-pattern> </servlet-mapping>
访问路径:http://localhost:8080/demo1/hello
二、servlet容器,运行servlet或者jsp等软件环境
1) 可以创建servlet,调用servlet生命周期方法
2) servlet的生命周期是由servlet容器负责管理的
构造器:只被调用一次,只有第一次请求servlet的时候,创建该servlet构造方法,单例
init方法:只被调用一次,在创建好实例以后,直接调用,用于获取或响应请求
service方法:被调用多次,在每一次请求的时候都调用service方法,用于获取或响应请求
destroy方法:只被调用一次,在当前web应用程序被卸载的时候被调用。用于释放资源
三、ServletRequest:获取请求
ServletResponse:响应
getWriter():返回printWrite对象,可以调用该对象的Write()方法吧内容输出到浏览器上
设置响应内容格式response.setContentType("text/html;charset=utf-8");
@Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub System.out.println("service方法执行了"); //获取请求信息,通过Url获取 String name=request.getParameter("name"); //设置响应内容 //1.设置响应内容格式 response.setContentType("text/html;charset=utf-8"); //输出到浏览器 //getWriter():返回printWrite对象,可以调用该对象的Write()方法吧内容输出到浏览器上 response.getWriter().write("今天天浩"+name); }
四、load-on-startup:
1).配置在
<servlet> <!-- 注册名 --> <servlet-name>hello</servlet-name> <!-- servlet类的全类名 --> <servlet-class>com.java.servlet.HelloServlet</servlet-class> <!-- 指定servlet被创建和初始化的时机 --> <load-on-startup>-1</load-on-startup> </servlet>
Servlet的加载
2)load-on-startup 元素标记容器是否应该在web应用程序启动的时候就加载这个servlet,(实例化并调用其init()方法)。
它的值必须是一个整数,表示servlet被加载的先后顺序。
如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
如果值为正整数或者0时,表示容器在应用启动时就加载并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
五、servlet-mapping
1).同一个servlet可以有多个servlet-mapping,
即多个<servlet-mapping>的子节点<servlet-name>的设置值可以是同一个servlet注册名
2).在servlet映射到的url中可以使用通配符*
但是只能有两种固定格式,一种是"*.扩展名",另一种是以"/"开头,以"/*"结尾,他俩不能混合使用,比如“/*.html”
六、ServletConfig接口:代表当前servlet,可以获取当前servlet的配置,还可以获取ServletContext对象
功能:用于读取web.xml中配置的serlvet的所有信息
Servlet容器将代表Servlet容器的对象(ServletContext)和Servlet的配置参数信息一并封装到一个称为ServletConfig的对象中,
并在初始化Servlet实例对象时调用init(ServletConfig config)方法将ServletConfig对象传递给Servlet。
1).配置初始化信息,配置放到<servlet>标签中
<!-- 初始化参数 --> <init-param> <param-name>username</param-name> <param-value>root</param-value> </init-param> <init-param> <param-name>pwd</param-name> <param-value>123456</param-value> </init-param>
2)获取初始化参数
getInitParameter(String):根据初始化参数名获取初始化值
getInitParameterNames() :获取所有初始化参数的名字
3)获取当前servlet的注册名(几乎不用)
getServletName():获取当前servlet注册名
4)获取当前代表web应用的ServletContext对象
getServletContext()获取代表当前web应用的ServletContext对象
七、实现servlet的第二种方式 继承GenericServle类
GenericServlet提供除了service()方法外所有接口中方法的缺省实现
GenericServlet的方法,只有service(req,res)是抽象方法,只需要实现这个方法就好
1).是一个servlet,是servlet接口和servletConfig接口的实现类,是一个抽象类,其中service方法是一个抽象方法
2).具体实现
(1)在GenericServle中声明了一个成员变量servletConfig,并且在init(ServletConfig config)里面对象这个变量完成了赋值
(2).利用servletConfig成员变量实现了ServletConfig接口里面的方法
(3).还定义了init()方法,如果子类需要在初始化的时候完成一些特定功能,可以重写init方法,并且在init(ServletConfig config)
里面调用了init方法,注意:重写的init的方法不是生命周期方法,init(ServletConfig config)才是生命周期方法
八、HttpServlet类是实现servlet最常用的一种方式
第一步:调用 MyServlet的service(ServletRequest, ServletResponse)方法,但是MyServlet没有重写这个方法,所以到MyServlet的父类去找
第二步:调用HttpServlet的service(ServletRequest, ServletResponse)方法,查看源码发现它调用了service(HttpServletRequest, HttpServletResponse)
第三步:查看HttpServlet的service(HttpServletRequest, HttpServletResponse)方法,发现它对请求方法进行了判断,如果是GET请求,则调用doGet()方法,如果是POST请求,则调用doPost()方法。
第四步:如果在MyServlet中重写了 doGet(),doPost()方法,则会调用MyServlet中的重写的响应的doGet(),doPost()方法。
1).继承GenericServle,他是针对http协议定制的
2).在service(ServletRequest req, ServletResponse res)中直接把ServletRequest和ServletResponse转成了
HttpServletRequest和HttpServletResponse,并且调用了重载的service(HttpServletRequest req, HttpServletResponse res)
方法,在重载service(HttpServletRequest req, HttpServletResponse res)中,获取了请求方式,并且根据请求方式去调用
doGet()或者doPost()方法
3).继承HttpServlet只需要重写doGet()和doPost()方法即可
九、Servlet的线程安全问题
public class ThreeServlet extends HttpServlet{ //声明一个成员变量 //String userName:不能这么定义,因为servlet是单例的,会出现线程安全问题 //因为servlet是单例的,多个用户同时访问的话,用的都是同一个对象,也是同一个属性,所以会出现线程安全问题 //解决办法:1,加同步代码块,但是这种效率太低了 2,定义成局部变量 private String name; @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); name = req.getParameter("name");//接收用户的参数 PrintWriter out = resp.getWriter(); try { Thread.sleep(5000);//为了突出并发问题,在这设置一个延时 } catch (InterruptedException e) { e.printStackTrace(); } out.println(this+",你的名字:"+name);//输出到页面 } }
十、ServletContext接口:当前web应用对象(在当前web应用下所有的地方都可以获取他,只有一个,相当于这个项目的全局变量)
ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器关闭才释放。
一个web项目,就存在一个ServletContext实例,每个Servlet都可以访问到它,用于共享数据。
1.获取ServletContext的两种方式
ServletConfig的getServletContext()方法
GenericServlet的getServletContext()方法
2.ServletContext常用方法:
getInitParameter(String):根据初始化参数名获取初始化值
getInitParameterNames() :获取所有初始化参数的名字
getRealPath():获取当前web项目的真实路径
getContextPath():获取当前web应用的根目录 重点
三大域对象
ServletContext、HttpSession、HttpServletRequest
功能
获取WEB应用程序的初始化参数、获取项目的真实的路径、作为域对象,保存多个客户共享的数据
Servlet3.0的注解
@WebServlet 用于将一个类声明为 Servlet
@WebInitParam该注解通常不单独使用,而是配合 @WebServlet 或者 @WebFilter 使用。它的作用是为 Servlet 或者过滤器指定初始化参数