servlet的介绍 & xml中配置 以及 & 三种实现方式(补充设置浏览器不缓存的方法)
开始时间:2018年10月13日20:53:30 | 2018年10月14日16:10:56
结束时间:2018年10月13日21:53:30 | 2018年10月14日17:02:23
累计时间:2小时
备注:几乎每一句话都很有收获,复习的时候务必要仔细一点
Servlet 简单介绍:
Servlet 服务器端的一个小程序: 运行在服务器上。 能够接收客户端请求,并且给客户端做出相应。
* 实现方式: 三种:
(1)实现Servlet 接口:
(2)继承GenericServlet:类。
(3)继承HttpServlet:
* Servlet 当中设定的方法:
初始化的方法; init();
接收客户端的请求,Service();
销毁Servlet: destroy();
* Servlet 的生命周期:
和Servlet 声明周期相关的方法:
init(ServletConfig config); Servlet创建之后,自动执行。
service(ServletRequest request, ServletResponse response); 当客户端浏览器发出请求的时候 service方法被调用。
destroy() 服务器关闭的时候,当前的应用称web服务器上卸载的时候。
生命周期---(面试问题)
诞生: 当客户端浏览器 第一次 访问该Servlet的时候,此时Servlet诞生。
第二次访问不创建,所以说servlet是单例
自动会调用init方法,执行一个初始化操作。
服务: 当客户端浏览器每次发出请求,service方法都会被执行。
销毁: 服务器关闭的时候,当前的应用称web服务器上卸载的时候。
* 访问方式
不能被浏览器直接访问, 需要在当前应用的核心配置当中 对 当前servlet进行配置
配置方法如下:
1 打开webinfo文件 下面的web.xml (是web应用的核心配置文件)
<!--注册Servlet: -->
<servlet>//需要有两个子标签 第一个放文件名 第二个放你的文件所在的全路径名
(如果是eclipse的话 可以快速copy全路径 如图 点击 copy qualified name即可)
<servlet-name>FirstServlet</servlet-name>
<servlet-class>web.servlet.FirstServlet</servlet-class>
</servlet>
<!-- 映射 -->(本质上是一个图结构)
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name> 和上面注册一样
<url-pattern>/xxx</url-pattern> /表示相对当前路径 映射上面那个class 自己命名的值会显示在URL栏
</servlet-mapping>
servlet访问原理
- url-pattern绑定 路径。访问的是xxx ,通过name 获得当前全路径名称
- 底层通过反射,创建了实例
补充一个Servlet 简单案例:
重点是浏览器设置不缓存
下面代码设置了浏览器不缓存,避免出现 修改服务器端给浏览器的响应 而浏览器显示不改变 的情况!
如果已经出现的话,清空浏览器缓存,或者重启。
package com.yidongxueyuan.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("yyy");
//设置浏览器不缓存:
// 同时出现,设置浏览器的不缓存:
response.setHeader("expires", "-1");
response.setHeader("Pragma", "no-cache");// http10.0
response.setHeader("Cache-Control", "no-cache");// http1.1
}
}
response.setHeader("expires", "-1"); 中的 第二个参数 不一定非得是-1,只要小于当前时间的毫秒值,即可。一般是-1或0
重点介绍三种实现方式
方式一: 实现步骤
(1) 创建一个类: 类实现implements Servlet
(2) 重写Servlet当中的方法:
(3) 访问》 通过浏览器访问:
下面程序中: servlet实例被创建的时候,自动执行init方法。
继承之后要重写的五个方法中,三个是servlet生命周期的方法
package com.yidongxueyuan.web.servlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class FirstServlet implements Servlet {
//第一步: 创建一个Servlet 实例:
public FirstServlet(){
System.out.println("servlet 被创建了");
}
//初始化方法: 对当前的Servlet 进行初始化操作:
@Override
public void init(ServletConfig paramServletConfig) throws ServletException {
System.out.println("init方法被执行了,完成了一个初始化操作。 ");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//service 方法: 对客户端的请求 进行相关的处理:
@Override
public void service(ServletRequest request,
ServletResponse paramServletResponse) throws ServletException,
IOException {
System.out.println("serice方法被执行了。。。。。。");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy方法被执行了。 此时Servlet被销毁。 ");
}
}
方式二:继承GenericServlet:类。
- servlet是单例的,如果定义全局变量 的话,当多线程并发访问时候,会出现数据 安全问题。(尽量不要使用单例)
第二种方式用了config对象作为全局变量,所以不太好。
关于这个类,手写如下:
package com.yidongxueyuan.web.servlet;
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;
/*
* 自定义的GenericServlet:
*/
public class MyGenericServlet implements Servlet {//Servlet 单例: 定义的全局变量 会引发数据安全问题。 尽量不要使用全局变量。
//提供一个了一个全局的config对象:
private ServletConfig config;
//不是一个生命周期方法:
public void init(){
}
//生命周期方法:
@Override
public void init(ServletConfig config) throws ServletException {
this.config=config;
init();
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public void service(ServletRequest paramServletRequest,
ServletResponse paramServletResponse) throws ServletException,
IOException {
}
@Override
public String getServletInfo() {
return "这是一个快乐的Servlet ";
}
@Override
public void destroy() {
}
//提供一个方法; 获得servlet 的名称:
public String getServletName(){
String servletName = config.getServletName();
return servletName;
}
//提供一个方法:获得初始化参数的值:
public String getInitParameter(String key){
String value = config.getInitParameter(key);
return value;
}
//获得初始化参数的名称;
public Enumeration getInitParamNames(){
return config.getInitParameterNames();
}
//获得上下文环境对象:
public ServletContext getServletContext(){
return config.getServletContext();
}
}
深入这个类的目的:是为了让别的类去继承,那么现在手写一个类去继承
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
public class BServlet extends MyGenericServlet {
//一堆: 实现Servlet的方式二:
//这是一个生命周期方法: 原因: 覆写了父类的生命周期方法; 那么父类的init方法单中所有的操作被覆盖了。 引发了其他的方法不能被使用。
/*@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("xxxx");
}*/
@Override
public void init() {
// .....
}
}
如果重写init方法的话:
这是一个生命周期方法: 原因-- 覆写了父类的声明周期方法; 那么父类的init方法单中所有的操作被覆盖了。 引发了其他的方法不能被使用。
那么该如何解决呢?
在被继承的父类Generic中写一个重载的方法
//不是一个生命周期方法:
public void init(){
}
//生命周期方法:
@Override
public void init(ServletConfig config) throws ServletException {
this.config=config;
init();
}
这样的话,子类再去继承的时候,重写无参的方法即可
方式三:继承HttpServlet:
重点!!!!!! 与第二种实现方式的关系如下:
API文档中提到:必须去复写其中一个方法
HttpServlet类:详解:
HttpServlet类提供的自定义的方法: 不是生命周期的方法:
service(HttpServletReuqest request, HttpServletResponse response); //提供的方法:
在该方法当中, 可以获得客户端的请求方式, 根据不同的请求方式,做了具体的派发。
例如: get请求 : 调用doGet方法:
post请求: doPost方法:
原有的生命周期的方法; service(ServletRequest req, ServletResponse res)
在生命周期方法当中, 将req 强制转换成了其子类对象, 调用了service方法(该类源码):
{
HttpServletRequest request;
HttpServletResponse response;
try
{
request = (HttpServletRequest)req;
response = (HttpServletResponse)res;
}
catch (ClassCastException e)
{
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
* 很多人在继承这个类之后重写方法的时候直接重写的是service方法,既可以处理post,又可以处理get,但是坏处在于:父类已经给你给你完成的 (针对不同请求分类的派发操作) 会被复写掉,不建议但是可以。
实现具体步骤如下:
(1)类 继承HttpServlet。
(2)重写doGet方法或者是doPost方法即可。
(3)配置: web.xml
补充 web.xml文件中配置<context-param>和<init-param>的区别
{
<context-param>和<init-param>都是上下文参数,但它们的范围和使用方式不同。
<context-param>是application范围内的初始化参数,用于向servlet-context提供键值对,即应用程序的上下文信息,listener、filter等初始化时会用到这些信息
<init-param>是servlet范围内的参数,只能在servlet类的init()方法中取得
来源:****
原文:https://blog.****.net/blacktal/article/details/72843737?utm_source=copy
}
1 注册 先写class里面的全路径名称 然后写上面的 name 理论上任意,但规范是类名
2 写下面的映射(以前写过)
(4)访问: \
代码如下:
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* 实现三:
1)类 继承HttpServlet。
(2)重写doGet方法或者是doPost方法即可。
(3)配置: web.xml
(4)访问: http://localhost:8080/javaEE-04/servlet/AServlet
*/
public class AServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("AServlet被创建了 并且完成了初始化");
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//获得一个参数的值:
String value= this.getServletConfig().getInitParameter("username");
System.out.println(value);
System.out.println("============");
//获得参数的名称:
Enumeration<String> enumeration = this.getServletConfig().getInitParameterNames();
while(enumeration.hasMoreElements()){
String nextElement = enumeration.nextElement();// 参数的名称:
String val = this.getServletConfig().getInitParameter(nextElement);
System.out.println(nextElement+" "+val);
}
System.out.println("============");
//获得servlet的名称:
String servletName = this.getServletConfig().getServletName();
System.out.println("servletName"+servletName);
//获得上下文对象:
ServletContext servletContext = getServletConfig().getServletContext();
System.out.println("servletContext"+servletContext);
System.out.println("doget方法被执行了");
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("dopost方法被执行了");
}
}
注:以后凡是说servlet的都是指第三种实现方式的servlet。
Servlet的补充:
1: web的三大组件:
Servlet: 动态资源(作用是处理请求)
Filter : 过滤器
Listener: 监听器
2:作用:
接收请求:
处理请求:
完成响应:
3: 初始化的方法,init service的方法, 参数都是来源于Tomcat服务器。
Tomcat服务器帮忙创建的。
4 :config 对象
config对象: 类型ServletConfig 接口
config 对象当中的方法:
java.lang.String getInitParameter(java.lang.String name)
Gets the value of the initialization parameter with the given name.
java.util.Enumeration<java.lang.String> getInitParameterNames()
Returns the names of the servlet's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the servlet has no initialization parameters.
ServletContext getServletContext()
Returns a reference to the ServletContext in which the caller is executing.
java.lang.String getServletName()
Returns the name of this servlet instance.
Servlet的配置信息都保存在当前的对象中 具体哪些信息如下:
ServletConfig 对象 : 对应Servlet的配置信息------------
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>com.yidongxueyuan.web.servlet.FirstServlet</servlet-class>
<!-- 给出一些配置的参数 ,给出的初始化参数只能在当前的Servlet当中有效: -->
<init-param>
<param-name>encoding</param-name>
<param-value>gbk</param-value>
</init-param>
<init-param>
<param-name>encoding1</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
<!-- 映射 -->
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/FirstServlet</url-pattern>
</servlet-mapping>
</web-app>