Servlet
编程需要使用到javax.servlet
和 javax.servlet.http
两个包下面的类和接口,在所有的类和接口中,javax.servlet.servlet
接口最为重要。所有的servlet
程序都必须实现该接口或者继承实现了该接口的类。
javax.servlet.ServletConfig;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;
javax.servlet.http.Cookie;
javax.servlet.ServletContext;
javax.servlet.GenericServlet;
以上是Servlet的主要类和接口
Servlet
运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。对这句话再做点解释,比如HttpServlet
类继承自Servlet类,可以利用继承HttpServlet
来实现Http请求,当不是Http请求的时候,也可以定义其他形式的Servlet。
servlet
部署到Tomcat
web容器中,浏览器发送一个Http请求(或者别的请求)后,web容器会自动分配这些请求到特定的servlet
类实例(若没有,通过反射由web容器进行创建一个)。servlet其实是一个java对象,它其中包含了一系列处理Http请求的方法。web容器内包含多个servlet
,访问哪一个由web容器中配置文件web.xml
来决定;
[图片上传中...(image.png-14d6ab-1510124505627-0)]
package javax.servlet;
import java.io.IOException;
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
1、浏览器发送出Http请求;
2、web容器解析请求,将其向下转型为HttpServlet
请求;
3、web容器建立对应的servlet
实例;
4、调用init()方法对servlet实例进行初始化(只执行一次);
5、调用service()方法,其包根据其请求类型调用doget()
,dopost()
方法(需要根据请求进行复写);
6、然后输出response
响应,通过容器发送;
7、服务器关闭或者web容器关闭,会调用dstory()方法;
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest)req;
response = (HttpServletResponse)res;
} catch (ClassCastException var6) {
throw new ServletException("non-HTTP request or response");
}
this.service(request, response);
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
...
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
...
//其实是做了一系列的比较,跳转至对象请求处理方法。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable{...
private transient ServletConfig config;
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
}
...}
读取配置,当浏览器输入"/index"后:
index 《----- 根据servlet name 第三步
test.index
《----- 查到test.index servlet类 第四步
index 《----- 得到servlet name 第二步
/index 《----- 遍历url 第一步
package test;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class index extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doget ...");
System.out.println(getServletConfig().getInitParameter("key"));
resp.getWriter().print("welcome ");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("dopost ....");
}
@Override
public void destroy() {
System.out.println("destory 。。。");
}
@Override
public void init() throws ServletException {
System.out.println("init start...");
}
}
----
init start...
doget ...
doget ...
结果:
[图片上传失败...(image-a08a62-1510124430937)]
当配置该servlet
:
web.xml中配置load-on-startup=1,代表容器启动时就会初始化该对象,而不是第一次请求时;
下面是load-on-startup=1的运行结果
init start...
[2017-11-08 11:32:37,825] Artifact untitled:war exploded: Artifact is deployed successfully
[2017-11-08 11:32:37,825] Artifact untitled:war exploded: Deploy took 446 milliseconds
doget ...
doget ...
而destory()方法是在服务器关闭或者重启的情况下,开始执行
十一月 08, 2017 11:37:28 上午 org.apache.catalina.core.StandardService stopInternal
信息: Stopping service Catalina
destory 。。。
下面看一下,servlet的几个重要对象:
1、javax.servlet.ServletConfig;
通过调用GenericServlet
中的getServletConfig()
得到
它为一个接口,包含四个方法:
import java.util.Enumeration;
public interface ServletConfig {
String getServletName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration getInitParameterNames();
}
1.1、getServletName():
我们修改doget方法和web.xml文件:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doget ...");
// System.out.println(getServletConfig().getInitParameter("key"));
System.out.println("servlet的名字为:"+getServletConfig().getServletName());
//获取servlet的名称,也就是我们在web.xml中配置的servlet-name
resp.getWriter().print("welcome ");
}
-----
index //getServletName()
test.index
//增加一项
key
hello world //getInitParameter("key")
1
//表示初始化在容器启动时,0代表为第一次请求时
-----
doget ...
servlet的名字为:index
doget ...
servlet的名字为:index
从上面结果可以看出,获取的是当前servlet
对象的名字;
1.2、getInitParameter(String var1)
其实可以从名字上看出,其得到的事初始化参数,下面进行验证:
在doget()方法中增加一项:
System.out.println("servlet的初始化参数为:"+getServletConfig().getInitParameter("key"));
-------
doget ...
servlet的初始化参数为:hello world
servlet的名字为:index
bingo~
1、3 getInitParameterNames()
返回的是一个枚举类型的参数名称集;
Enumeration params=getServletConfig().getInitParameterNames();
while (params.hasMoreElements()){
System.out.println(params.nextElement());
}
resp.getWriter().print("welcome ");
---
//增加一行参数:
...
name
mylife
...
----
doget ...
name
key
1、4 getServletContext()
得到ServletContext接口对象;不过一般不使用此方法,一般采用GenericServlet
的public ServletContext getServletContext()
方法,来获取servletContext
对象;
2、javax.servlet.ServletContext;
tomcat为每个web项目都创建一个ServletContext
实例,tomcat在启动时创建,服务器关闭时销毁,在一个web项目中共享数据,管理web项目资源,为整个web配置公共信息等,通俗点讲,就是一个web项目,就存在一个ServletContext实例,每个Servlet读可以访问到它。
为web.xml增加一项配置:
//相当于全局(整个web项目)变量,配置整个web项目的初始化参数
feat
plapla
提供下面方法,来获取它,使用方法与上面相同,不在重复:
String getInitParameter(String var1);
Enumeration getInitParameterNames();
它还有几个重要的方法,用于页面之间的传参:
setAttribute(String var1, Object var2);
//在web项目范围内存放内容,以便让在web项目中所有;
removeAttribute(String var1);
//通过指定名称获得内容
getAttribute(String name)
// 通过指定名称移除内容
看一个例子:
新建两个类,fuck 和 test
------
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("test.doget start...");
System.out.println(getServletContext().getAttribute("content"));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("fuck.doget start...");
System.out.println(getServletContext().getAttribute("content"));
}
//运行结果...
doget ...
test.init() start...
test.doget start...
helloworld
fuck.init() start...
fuck.doget start...
helloworld
用于回去资源路径的方法:
String getRealPath(String var1);
使用方法,也很简单:
System.out.println("该项目位于:"+getServletContext().getRealPath("/"));
----
doget ...
该项目位于:D:\IdeaProjects\study\out\artifacts\untitled_war_exploded\
3、javax.servlet.http.HttpServletRequest;
request信息:
Accept:image/webp,image/apng,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Cookie:BAIDUID=FFB31BBED298FFFA711C8E2FE416214E:FG=1; BIDUPSID=FFB31BBED298FFFA711C8E2FE416214E; PSTM=1499983389; __cfduid=d49ab908a5a4d3ca5789b9de975db3feb1505744478; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; PSINO=2; H_PS_PSSID=1448_22534_21097_17001_24880_20928
Host:sp0.baidu.com
Referer:https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=servletconfig&oq=servletconfig&rsv_pq=b995eb8400028783&rsv_t=6cc3Xb6Dn%2BSyOjvExboNaM4ieI%2FD5bm00jWcd9klEP2y2TWdMxUIVgfWOL0&rqlang=cn&rsv_enter=0
常用的方法:
HttpSession getSession();
Cookie[] getCookies();
//继承的方法
void setAttribute(String var1, Object var2); //页面之间进行传值
void removeAttribute(String var1);
Object getAttribute(String var1);
String getParameter(String var1); //获取参数
String[] getParameterValues(String var1);//用于同一参数名的所有参数值获取
String[] getParameterValues(String var1);
/*转发,表示浏览器中url不会改变,也就是浏览器不知道服务器做了什么,是服务器帮我们跳转页面并且在转发后的页面,能够继续使用原先的request,因为是原先的request,所以request域中的属性都可以继续获取到。作用域见 jsp;
*/
RequestDispatcher getRequestDispatcher(String var1);
//获取 servletContext对象
ServletContext getServletContext();
System.out.println("获取统一资源标记符"+req.getRequestURI());//获取统一资源标记符
System.out.println("获取统一资源定位符"+req.getRequestURL());//获取统一资源定位符
System.out.println("域名"+req.getServerName());
-----
doget ...
获取统一资源标记符/untitled/index
获取统一资源定位符http://localhost:8070/untitled/index
域名localhost
4、javax.servlet.http.HttpServletResponse;
第一部分:状态行,由HTTP协议版本号, 状态码(200), 状态消息(OK) 三部分组成。
第二部分:消息报头,用来说明客户端要使用的一些附加信息
第二行和第三行为消息报头,
Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8
第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文,服务器返回给客户端的文本信息。空行后面的html部分为响应正文。
响应状态码:
1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进行更进一步的操作
4xx:客户端错误--请求有语法错误或请求无法实现
5xx:服务器端错误--服务器未能实现合法的请求
主要方法为:
//重定向
void sendRedirect(String var1) throws IOException;
//手动重定向
void setStatus(int var1, String var2);
void setHeader(String var1, String var2);
response.setStatus(302); //状态码302就代表重定向
response.setHeader("location","url....");
/*
重定向没有任何局限,可以重定向web项目内的任何路径,也可以访问别的web项目中的路径,并且这里就用"/"区分开来,如果使用了"/"开头,就说明我要重新开始定位了,不访问刚才的web项目,自己写项目名,如果没有使用"/"开始,那么就知道是访问刚才那个web项目下的servlet,就可以省略项目名了。就是这样来区别。
*/
5、javax.servlet.http.HttpSession;
Session是服务器端技术,利用这个技术,服务器在运行时,为每一个用户创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
当用户打开浏览器,访问某个网站操作session时,服务器就会在服务器的内存为该浏览器分配一个session对象,该session对象被这个浏览器独占。
session可以作为一个容器,存储一些对象,他有默认的存在时间一般为30min。形象描述为:
,
它主要用于一下几个方面:
1、禁止访问某些界面(比如说未登陆时);
2、网上商城中的购物车
3、保存登录用户的信息
4、将某些数据放入到Session中,供同一用户的各个页面使用
它的主要方法有:
Object getAttribute(String var1);
Enumeration getAttributeNames();
/** @deprecated */
String[] getValueNames();
void setAttribute(String var1, Object var2); //在session中存储或更新元素
void removeAttribute(String var1); //删除某个存储对象
可以通过web.xml设置其存在时间:注意该时间为发呆时间,即从最后一次使用开始计时;
若将其存在时间设为-1,代表其永不过期,但是服务器重启后还是会失效;
60 //设置存在时间为60分钟
6、javax.servlet.http.Cookie;
cookie机制则是在客户端保持状态的方案,cookie又叫会话跟踪机制;
cookie:
1.cookie是在服务端创建的
2.cookie是保存在浏览器这端的
3.cookie的生命周期可以通过cookie.setMaxAge();如果不设置,关闭浏览器就destroy了
Cookie
的maxAge
决定着Cookie
的有效期,单位为秒(Second)。Cookie
中通过getMaxAge()
方法与setMaxAge(int maxAge)
方法来读写maxAge
属性。
如果maxAge
属性为正数,则表示该Cookie
会在maxAge
秒之后自动失效。浏览器会将maxAge
为正数的Cookie
持久化,即写到对应的Cookie
文件中。无论客户关闭了浏览器还是电脑,只要还在maxAge
秒之前,登录网站时该Cookie
仍然有效。下面代码中的Cookie
信息将永远有效。
Cookie cookie = new Cookie("username","helloweenvsfei"); // 新建Cookie
cookie.setMaxAge(Integer.MAX_VALUE); // 设置生命周期为MAX_VALUE
response.addCookie(cookie); // 输出到客户端
如果maxAge
为负数,则表示该Cookie
仅在本浏览器窗口以及本窗口打开的子窗口内有效,关闭窗口后该Cookie
即失效。maxAge
为负数的Cookie
,为临时性Cookie
,不会被持久化,不会被写到Cookie
文件中。Cookie
信息保存在浏览器内存中,因此关闭浏览器该Cookie
就消失了。Cookie
默认的maxAge
值为–1。
如果maxAge
为0,则表示删除该Cookie
。Cookie
机制没有提供删除Cookie
的方法,因此通过设置该Cookie
即时失效实现删除Cookie
的效果。失效的Cookie
会被浏览器从Cookie
文件或者内存中删除,