Servlet
C/S--->Client/Server(客户机/服务器)
优点:
1)运行效率较高
2)交互性强适合局域网,
缺点:升级维护困难
B/S-->Browser/Server(浏览器/服务器)
优点:无需关心客户端,升级维护,只需操作服务器即可.比较方便.
缺点:
1)交互性是请求/响应式,需要通过网络进行交互,效率相对c/s架构的软件来说较低.
2)要开发交互性较强的界面比较困难.
CGI:最早开发b/s架构的一门技术
从CGI分出 1)微软的ASP--->ASP.NET
2)JAVA的Servlet--->jsp
开发技术:
静态网页技术:
HTML,JS,CSS
动态网页技术:(动态说的是数据动态)
CGI,ASP,ASP.net,servlet,php,jsp等
url:
http://192.168.1.250:8888/poll/login.jsp
协议://地址(ip-->域名):端口(如果是80,可以省略)/web应用名/资源名
web服务器: (微软的)IIS:
(apache的)tomcat(开源的):等..
servlet:
1)属于j2ee的其中一个技术,是一个规范
2)servlet是一个web组件(包含servlet类和他的描述信息) 组件如java bean 可复用的
3)servlet运行的时候就是一个java对象(创建.调用.管理由web服务器(web容器)完成).web容器是web服务器的线程tomcat的web容器是CATALINA
web容器调用servlet对象的方法
首先由web容器创建两个对象:
1.HttpServletRequest:
包含了客户端提交的所以信息,在servlet中 ,可以通过这个对象获得客户端传递过来的数据.
2.HttpServletResponse:
通过这个对象可以向客户端返回数据
public void service(ServletRequest req,ServletResponseres){
}
web应用的目录结构:
应用名:(web应用的根目录的名字)
WEB-INF(必须):浏览器不能直接访问
classes(存放.class文件)
lib(存放第三方的.jar文件)
web.xml(描述servlet,包括类名和访问标识)
html/first.html
js/my.js
css/my.css
jsp/first.jsp
META-INF
tomcat服务器的目录结构:
bin:存放一些可执行文件:比如startup.sh,shutdown.sh
common:存放tomcat服务器和所以web应用都可以使用的类和jar包
conf:存放tomcat服务器使用的一些配置文件.比如 service.xml中可改端口号
logs:存放tomcat服务器和web应用输出的日志信息的文件
server:存放一些只能由tomcat服务器使用的类和jar包,以及tomcat自带的web应用
shared:存放一些只能由web应用使用的类和jar包
temp:存放一些临时文件
*webapps:用来部署web应用
work:存放jsp文件被翻译和编译以后的.java和.class文件.
web工程(IDE):通过工程可创建web应用
web应用:(成品软件)
javax.servlet.Servlet(接口)
javax.servlet.GenericServlet(抽象类)
javax.servlet.http.HttpServlet(抽象类)(建议使用)
Service-->doGet/doPost(根据客户端请求方式调用,不是非要同时调用)
tomcat由于已经启动无法启动 用命令 ps -ef|grep tomcat 在kill -9进程号
form表单处理:
1.提供表单
a)提供一个html页面包含一个form表单
b)提供一个servlet返回一个form表单
form表单action属性指定的路径
a)相对路径
register
b)绝对路径
/servlet/form/register
2.中文乱码问题
a)get方式提交
解决办法,在服务器中设置客户端提交请求的URI的编码类型
在server.xml中 <Connector 加 URIEncoding="UTF-8"
b)post方式提交
在server中获得客户端提交的参数之前,调用req对象的setCharacterEncoding方法设定编码类型。
c)响应
在server中获得输出流之前,调用response对象的的setCharacterEncoding方法设定编码类型。
3.method="get"和method="post" (form表单的两种提交方式比较)
get请求:
a)直接在浏览器地址栏输入请求的URL发起的请求:
b)点击一个超连接发起的请求
c)提交一个form表单但form表单的method不指定或指定get的时候
特点:
提交的数据放在请求的头部,一般在查询数据的时候我们会选择get方法发起请求
post请求:
a)提交一个method属性指定为post的表单发起的请求.
特点:
提交的数据放在请求体部,在向客户端提交数据的时候我们会选择使用post方式发起请求.
4.request/response对象中的方法
request.getContextPath();返回web的应用的根路径
request.getMethod();返回请求方式,get或post
request.getParameterMap();获得客户端提交的所有参数,包括参数名字和值
request.getParameterNames();获得客户端参数名字
request.getQueryString();返回URI后面所跟着的参数 如果是post方式提交返回null
request.setCharacterEncoding("UTF-8");设定客户端提交的内容的编码类型
5.servlet的url-pattern的写法(补充)
a)以"/"开始,后面跟着具体的内容
b)前通配(*) :如 *.do,*.action
c)后通配 如: /form/*,/basic/*
Servlet的生命周期(四个阶段)
1)装载和实例化阶段
创建者:web容器
创建情况:
(1)第一次访问的时候创建
<load-on-startup>num</load-on-startup>(num默认为-1)
当num<0时,第一次访问时创建servlet实例
(2)web应用被安装的时候创建(启动服务器)
当num >=0时,servlet在web应用被安装的时候创建
创建顺序:
num=0,最晚被创建
num>0,值越小越早被创建
2)初始化阶段
调用者:web容器
public void init(ServletConfig config){}
在GenericServlet中已经对有参的init方法作了实现
public abstract class GenericServlet implement Servlet{
private ServletConfig config;
public void init(ServletConfig config){
this.config=config;
this.init();
}
public void init(){
}
}
3)服务阶段
调用者:web容器
public void service(ServletRequest req,ServletResponse res){
}
在HttpServlet中已经对service方法作了实现
public abstract class HttpServlet extends GenericServlet{
public void service(ServletRequest req,ServletResponse res){
HttpServletRequest hReq=(HttpServletRequest)req;
HttpServletResponse hRes=(HttpServletResponse)res;
service(hReq,hRes);
}
public void service(HttpServletRequest hReq, HttpServletResponsehRes){
String method=hReq.getMethod();
if(method.equals("GET")){
doGet(hReq,hRes);
}else if(method.equals("POST")){
doPost(hReq,hRes);
}
}
//被子类覆盖
public void doGet(HttpServletRequest request, HttpServletResponseresponse) {
}
//被子类覆盖
public void doPost(HttpServletRequest request, HttpServletResponseresponse){
}
}
4)销毁阶段
调用者:web容器
public void destory{
}
注:init(),service(),destroy()称为servlet对象的生命周期回掉方法.
web应用的逻辑分层:
model(模型):
javabean,ejb..
view(显示):
servlet,jsp等
control(控制):
servlet,jsp....
请求的转发:
1)服务器内部跳转
请求转发器:RequestDispather
创建:
1.调用request对象的方法
指定的转发路径可以相对也可以是绝对的
相对路径:根据当前servlet的路径和转发的路径进行计算
绝对路径:就是转发的servlet的url-pattern
2.调用servletContext对象的方法
指定的路径必须是绝对路径
forward:
在转发请求之前首先调用response对象的resetBuffer方法,清空缓存.
include(包含):
将请求转发到其他servlet之前不会清空缓存
2)服务器外部重定向
RedirectServlet
通过服务器外部重顶向进行请求的转发 里面的路径可以相对可以绝对
绝对路径写法: 应用根路径+servlet的url-pattern
例:response.sendRedirect(request.getContextPath()+"/resource/view");
相对路径写法:例:response.sendRedirect("view");
服务器内部跳转和服务器外部重定向的比较
1)服务器内部跳转所有的servlet共享同一个请求,而服务器外部重定向,每个Servlet接受的请求都不相同
2)服务器内部跳转是在服务器实现的,而服务器外部重定向是由浏览器实现的
3)服务器内部跳转是通过request对象来完成的,而服务器外部重定向是通过response对象来完成的.
作业:
1.findUser.html
2.FindUserServlet:
1.负责接收客户端查找用户的请求
2.调用UserMange的findUser(String name)
3.将找到的User对象交给ViewUserServlet显示
ViewUserServlet
1.首先判段有没有需要显示的user,如果没有 提示
2.如果有,则将用户的详细信息进行显示
3.在UserManager中提供查询用户的方法.
Contextctx=new InitialContext();
DataSourceds=(DataSource)ctx.lookup(jndiName);
通过jndi从目录服务器上查找DataSource对象
DataSource( 连接池);
06 02 2008 JNDI:java name directory interface
创建DataSource对象
1.通过new 的方式创建.
2.通过web服务器提供的配置的方式,来创建DataSource(这种方式创建的DataSource已经存放在目录服务器上).
1)将oracle的驱动包放入到tomcat的common/lib目录下
2)JNDI Name:jdbc/ds
数据库的URL Data SourceURL:jdbc:oracle:thin:@192.168.1.220:1521:briupdb
数据库驱动名:JDBC Driver Class:oracle.jdbc.driver.OracleDriver
数据库用户名:User Name:jd0804
数据库用户密码:Password:jd0804
最大活动的连接数:Max. Active Connections:
Max. IdleConnections:(当连接池没有连接的时候,再创建的连接数)
使用DataSource
1.如果是通过new的方式创建的DataSource,可以直接调用他的getConnection方法来获得连接
2.通过jndi访问目录服务器,查找DataSource,调用方法获得连接.
ch05状态持久。
为什么需要状态持久?
因为http协议是无状态的,客户端发起一个请求的时候,会跟服务器建立socket连接,一旦响应,就会关闭socket连接,所以为了让服务器端知道某个客户端的状态信息,我们需要将状态进行持久化
cookie
创建: name value
Cookiecookie = new Cookie("isLogin", "true");
cookie.setMaxAge(time);
response.addCookie(cookie);
当time<0,表示cookie保存在浏览器进程中,一旦浏览器进程结束,cookie就消失
当time=0,表示删除客户端同名的cookie
当time>0,表示cookie将在浏览器端保存起来,超过time后才会消失
获取:
Cookie[] cookies=request.getCookies();
session(结合cookie使用):创建和保存都在服务器端
由web服务器维护
HttpSession session = request.getSession();
或者
HttpSession session = request.getSession(boolean create);
当create==true时,这个方法的作用跟无参的getSession()方法作用一样
当create==false时,这个方法的作用是:根据客户端传递过来的session的id,寻找服务器端的session,如果找到返回,如果没有找到,返回null;
StringID=session.getId();
session.setAttribute("isLogin", true);
当对客户端作出响应的时候,会将session的ID包装成一个cookie对象(名字为JSESSIONID,值为session的id),返回给客户端
HttpSession消失的情况:
1)web应用停止
2)超时(上一次访问开始的时间到当前时间,如果这个时间超过了指定的超时时间,那么就认为是超时了)
可在web.xml中可配置session的超时时间:
3)调用session对象的invalidate方法
通过URL重写解决cookie禁用sesion不能访问的问题:
当客户端禁用cookie之后,无法通过cookie保存session的id我们可以通过URL重写来保存session的id
url;jsessionid=HJGKJWBDRUWRGW
String oldUrl = "sessionCheck";
String newUrl = response.encodeURL(oldUrl);//encodeUrl已不建议使用
三个范围(scope)
requestScope(ServletRequest):在多个servlet之间进行服务器内部跳转的时候,我们可以通过将数据放在request对象中进行数据的传递。
request.setAttribute(key,value);
Object value=request.getAttribute(key);
request.removeAttribute(key);
sessionScope(HttpSession):session中一般存放一些状态信息,或者在整个会话中经常要使用的数据(不建议存放过多数据(影响服务器效率))
session.setAttribute(key,value);
Object value=session.getAttribute(key);
session.removeAttribute(key);
applicationScope(ServletContext):ServletContext一般存放整个系统运行过程中,经常要使用的数据
ctx.setAttribute(key,value);
Object value=ctx.getAttribute(key);
ctx.removeAttribute(key);
过滤器:Filter
web应用的事件的处理机制
1.事件源
web容器
2.事件对象:由web容器创建
在web应用启动和停止的时候产生:ServletContextEvent 在javax.servlet 包中
会话开始和结束的时候产生:HttpSessionEvent 在javax.servlet.http 包中
请求开始和结束的时候:ServletRequestEvent
对application范围中的数据操作的时候产生:ServletContextAttributeEvent
对session范围内的数据进行操作的时候产生: HttpSessionBindingEvent
对requset范围中的数据操作进行操作的时候产生:ServletRequestAttributeEvent
3.监听器
处理ServletContextEvent事件对应ServletContextListener接口(执行时间:web应用启动和停止)
处理HttpSessionEvent事件 HttpSessionListener执行时间:session(会话)开始和结束
处理ServletRequestEvent 事件 ServletRequestListener 执行时间:请求的开始和结束
处理ServletContextAttributeEvent 事件ServletContextAttributeListener
执行时间:加入数据,删除数据,替换数据
HttpSessionBindingEvent HttpSessionAttributeListener执行时间:加入数据,删除数据,替换数据
ServletRequestAttributeEventServletRequestAttributeListener
执行时间:加入数据,删除数据,替换数据
注册监听器:在web.xml中描述就可以完成监听器的工作.
一、 过滤器 Filter
1. why Filter?
针对通用WEB服务、功能,透明的处理
2. 什么是Servlet Filter?
过滤是 Servlet 2.3 版才引入的新特性。过滤器可以认为是实现 Http请求、响应以及头信息等内容的传送的代码片断。
过滤器并不能创建响应,但它可以“过滤”传给 servlet 的请求,还可以“过滤”从 servlet发送到客户端的响应;
它不仅能处理静态内容,还可以处理动态内容。换而言之,filter 其实是一个“servlet chaining”(servlet链)。
一个 filter 包括:
1) 在 servlet 被调用之前截获;
2) 在 servlet 被调用之前检查 servlet request;
3) 根据需要修改 request 头和 request 数据;
4) 根据需要修改 response 头和 response 数据;
5) 在 servlet 被调用之后截获.
3.过滤器的生命周期
Filter 组件的生命周期与 Servlet 的类似。
过滤器有四个阶段(与servlet类似):
1) 实例化;
2) 初始化(调用init()方法);
3) 过滤(调用doFilter()方法);
4) 销毁(调用destroy()方法);
4.Filter编程
1)定义Filter(implements Filter)
2)配置Filter
配置对哪些资源进行过滤(url)
<filter>
<filter-name>Logger</filter-name>//过滤器名
<filter-class>com.LoggerFilter</filter-class>//具体过滤器类
<init-param> //初始化参数
<param-name>xsltfile</param-name>
<param-value>/xsl/stockquotes.xsl</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Logger</filter-name>
<url-pattern>/*</url-pattern>//将过滤器应用于Web应用中的每个Web资源;可以只指定某个资源
</filter-mapping>
5.FilterChain
1) chain是如何配置,顺序
当同一个应用中配置了多个 filter 时,其执行顺序是如何的呢?
答:按 web.xml中<filter-mapping>的顺序来执行的
2) chain.doFilter(req, resp)
调用下一个Filter,到最后一个Filter则正式调用 TargetServlet
3) 调用过程(类似于递归调用)
6.Filter的类型
Filter有4种类型,主要体现在<filter-mapping>中的<dispatcher>属性:
<dispatcher>REQUEST</dispatcher>默认,客户端的直接的请求,才触发该过滤器
<dispatcher>FORWARD</dispatcher>servlet 调用 rd.forward(req,resp)时触发
<dispatcher>INCLUDE</dispatcher>servlet 调用 rd.include(req,resp)时触发
<dispatcher>ERROR</dispatcher>发生错误,跳转到错误页面时触发
二、监听器Listener
Listener 是 Servlet 的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作。
如:监听在线的用户数量。当增加一个session时,就激发sessionCreated(HttpSessionEventse),给在线人数加1
1. 监听器的种类
一共分三大类型,有 8 种 listener:
a.监听 servlet context
1)生命周期事件
接口: javax.servlet.ServletContextListener
内容: servlet 上下文已经被创建,并且可以用来向其第一个请求提供服务,或者 servlet 上下文即将关闭
2)属性的改变
接口: javax.servlet.ServletContextAttributeListener
内容: 在 servlet 上下文中,增加、删除或者替换属性
b.监听 servlet session
1)生命周期事件
接口: javax.servlet.http.HttpSessionListener
内容: 对一个 HttpSession 对象进行创建、失效处理或者超时处理
2)属性改变
接口: javax.servlet.http.HttpSessionAttributeListener
内容: 在 servlet 会话中,增加、删除或者替换属性
3)会话迁移
接口: javax.servlet.http.HttpSessionActivationListener
内容: HttpSession 被激活或者钝化
4)对象绑定
接口: javax.servlet.http.HttpSessionBindingListener
内容: 对 HttpSession 中的对象进行绑定或者解除绑定
c.监听 servlet request
1)生命周期
接口: javax.servlet.ServletRequestListener
内容: 一个 servlet 请求开始由 web 组件处理
2)属性改变
接口: javax.servlet.ServletRequestAttributeListener
内容: 在 ServletRequest 中,增加、删除或者替换属性
Servlet环境配置
JAVA_HOME=/XXX/XXX/(JDK路径,bin的上一层目录)
CATALINA_HOME=/XXXX/XXX(tomcat的绝对路径 windows中X:/xxx/xxx)
Tomcat使用
在启动Tomcat时,是运行Tomcat的bin目录下的startup.sh(windows中使用startup.bat)
Linux中要显示后台的具体信息,则用catalina.sh run 代替startup.sh命令。
判断Tomcat是否启动成功,可以在浏览器的地址栏中使用 http://localhost:8080/或 http://127.0.0.1:8080/可以访问到tomcat的主页就表示启动成功。
要想停止tomcat服务器,可使用shutdown.sh(windows中使用shutdown.bat),如果直接关闭启动窗口,就会造成8080端口占用错误,这时可以再使用shutdown.sh关闭一下服务器。
Servlet开发步骤
编写servlet源代码,注意servlet的结构。
编译servlet,需要servlet-api.jar文件(位于$Tomcat/common/lib/目录下;加入classpath环境变量中)
部署servlet
编写配置文件web.xml:其中包括servlet burl与 servlet name的映射,
以及servlet name 与 servlet class name的映射。
构造web应用程序目录结构如下:
└─MyWebApp 应用程序名
└─WEB-INF
└─classes
└─lib
└─*.html/*.jsp
配置文件web.xml放在WEB-INF目录下
servlet类文件放在classes目录下
将整个应用程序目录拷贝到 $Tomcat/webapps/ 目录下
使用此结构的优点
一个Web容器中可以共存多个Web应用程序。
Web容器知道该到何处寻找装入Web应用程序所需的类。
web.xml文件的写法
<?xml version="1.0"encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsdversion="2.4">
<servlet>
<servlet-name>IpLogServlet</servlet-name>
<servlet-class>tarena.servlet.lc.IpLogServlet</servlet-class>
<init-param>
<param-name>filename</param-name>//getServletConfig().getInitParameter();
<param-value>c:/iplog.txt</param-value>
</init-param>
<load-on-startup>2</load-on-startup >//启动服务器时就创建该servlet实例,必须是正数,小的数先加载
</servlet>
<servlet-mapping>
<servlet-name>IpLogServlet</servlet-name>//要和servlet标签中的相同
<url-pattern>/lc/iplog</url-pattern>//指定servlet相对于应用目录的虚拟路径
</servlet-mapping>/xxx/xxx(绝对路径),xxx(相对路径)
</web-app>
绝对路径开头的“/”代表 http://localhost:8080/
测试应用
在tomcat服务器中,访问应用下的资源可以在端口号后加上web应用文件夹的名字,就可以看到资源
http://localhost:8080/应用文件夹名/url-pattern
静态页面只能放在web应用的文件夹下,不能够放在WEB-INF文件夹下,WEB-INF文件夹中的资源是受保护的,不能够通过网络访问到。
Servlet的调用过程
用户通过浏览器向web服务器发送请求
http://serverip:port/appname
服务器为用户定位资源
静态资源:/a.html /a/b.html (这里的路径是针对web应用文件夹目录)读文件并把内容发送到客户端。
动态资源:解析web.xml定位Servlet类的名字。
装载类(WEB-INF/classes | WEB-INF/lib/*.jar)
创建该对象的实例
Servletser=(Servlet)(Class.forName("servle的类名")).newInstance();
//我们写的Servlet一定要实现Servlet接口或者继承实现了Servlet接口的类
ser.service(request,response);
用Servlet处理表单数据
FORM元素的属性
action: 用来指定要处理FORM数据的Servlet的URL
method: 指定数据传送给HTTP服务器的方法
解析请求
getParameterNames:可以获得一个迭代器Enumeration,通过这个迭代器,来获得form表单中参数的名字。
getParameter: 返回表单中参数名(区分大小写)对应的值(没有这样的参数,返回null;没有任何值,返回空String);多参数同名时,只取一个。
getParametervalues:返回表单中参数名(区分大小写)对应的字符串数组(没有这样的参数,返回null;只有一个值,返回值为单一元素组);
get& post
在浏览器的地址栏操作按回车键,或者是热连接,都是get请求,form的method属性如果不指定,默认为get请求(传的数据不能太大,且表现为明文)。
get请求,会将参数显示在浏览器的地址栏上,其显示格式,在地址之后会以?开始,以'&'分隔参数,可以通过HttpServletRequest对象的getQueryString()方法来获得get请求的参数值。
post请求:ServletRequest对象的getInputStream()方法可以获得一个由Socket得来的输入流,可以使用这个流来实现文件的上传。getReader()方法可以直接获取post请求的参数。
Servlet的生命周期
创建Servlet对象,通过服务器反射机制创建Servlet实例,默认第一次请求时才会创建。
调用Servlet对象的init()方法,初始化Servlet的信息,init()方法只会在创建后被调用一次。
响应请求,调用service()或者是doGet(),doPost()方法来处理请求,这些方法是运行的在多线程状态下的。
在长时间没有被调用或者是服务器关闭时,会调用destroy()方法来销毁Servlet对象。
Servlet对客户端提供服务的时序图(插图见Servlet_Note.pdf,P16)
Servlet生命周期状态图(插图见Servlet_Note.pdf,P17)
init方法
当首次创建Servlet时就会调用init方法, 而不是每个用户请求都会调用该方法。
我们可以在init方法中完成类似于构造方法的初始化功能。
init方法一结束,servlet即可接受客户端请求;
init方法实例
覆盖init(ServletConfigconf)方法时,应该总是在首行调用super.init();或者直接覆盖init();
init方法接受ServletConfig作为参数, 用以下方法获得参数值:
getInitParameter: 返回指定参数名称对应的值,如果参数不存在,返回null;
getInitParameterNames: 返回所有初始化参数的名字 ;
service方法
每当服务器接收到对Servlet的请求时,服务器就会产生一个新线程, 并调用service。
service方法检查HTTP请求类型,并相应地调用doGet、doPost、doPut、doDelete。
被container调用去响应(ServletResponse)来自客户端的请求(ServletRequest);
Servlets的多线程安全
多线程占用资源少,处理速度快,提高了效率。
一些编码建议:
对变量和方法定义适当的访问方式, 例如单纯取值操作不会有多线程安全问题;
同步化所有访问重要数据的实例变量; 多线程下,如果操作的是一个变量,且兼有读写操作,
就要考虑加上同步,但同步不能乱加,否则会造成死锁问题。
并发需要注意的
并发的环境:资源处于一个并发的环境
共享资源:多个线程共享一个临界资源
全面同步:如有n个变量访问同一个资源,这n个变量都得同步。即多个锁一把钥匙,钥匙放在一个共享区域内
sychronized(this):粗粒度的锁。是将所有的路都加锁;
sychronized(object o1):细粒度的锁。只对对象中的变量加锁。效率较前面的高,但是较难控制。
读写需要互斥。
sychronized(this):this不能是基本数据类型,必须是Object.不锁对象的引用,而是对象的内存空间。
servlet中需要同步的:成员变量、文件、静态变量、数据库连接
destroy方法
服务器决定删除已经加载的Servlet实例之前将调用Servlet的destroy方法;
该方法允许Servlet:
关闭数据库连接;
中止后台线程;
将Cookie程序清单或访问计数写到磁盘以及执行其他类似的收尾工作。
在Servlet终止时处理Service线程
在destroy()方法中:如有服务(通过一个同步化的实例方法取得当前线程数大于0),则置关闭状态为false(通过一个同步化的实例方法实现)。然后循环等待服务线程数为0,则置关闭状态为true.
在Service()方法中:如见关闭状态为true,便不执行具体逻辑方法,直接退出。
HTTPservlet类的基本结构
继承HttpServlet
实现至少一个service方法,如:doGet(...)和doPost(...)
service方法有两个参数,HttpServletRequest 和HttpServletResponse:
HttpServletRequest代表经过容器加工的用户的请求
HttpServletResponse代表需要容器进一步加工的对用户的响应
我们写的servlet需要引入javax.servlet.* 和javax.servlet.http.*两个命名空间
servlet继承关系
servlet主要数据结构:
Servlet 接口:主要定义了servlet的生命周期方法
ServletConfig接口:为servlet提供了使用容器服务的若干重要对象和方法。
ServletContext接口:是Servlet的上下文对象,这个对象是在服务器启动时创建的,为servlet提供了使用容器服务的若干重要方法。
GenericServlet抽象类:为servlet提供了一般的实现(包括实现了servlet和ServletConfig两个接口),保存了容器通过init方法传递给servlet的一个ServletConfig类型的重要对象。
HttpServlet抽象类:为处理http请求的servlet提供了一般实现,主要是定义和实现了若干service方法。
继承关系:GenericServlet继承了Servlet和ServletConfig接口;HttpServlet继承了GenericServlet;
我们写的servlet继承了HttpServlet
Servlet访问DB(一个servlet完成整个功能)
获取client端信息 ---> entity -------v
调用相应的处理方法 ---> controller |
连接数据库 ---> util ------------v
操作信息数据 ---> biz -------> model
返回给client端相应的结果页面 ---> view
将一个servlet按功能细分
将一个完成所有功能的servlet分解成多个,
分别完成自己的功能,即形成了mvc。
MVC框架(组件的各司其职)
Model,模型层(封装数据),这一层一般是进行数据库访问,并且封装对象,这一层中也存放在访问数据库取出信息封装成对象的类,也就是实体类的信息,可以使用JDBC或者Hibernate实现这一层的功能。
Ctrl,控制层(改变数据,改变模型的状态),用来相应请求和调用写好的相应的访问数据库的方法,这一层是用来控制请求的响应的,现在我们是使用Servlet来实现这一层,不过一般是会用开源的MVC框架来实现这层,例如struts,或者是Spring的MVC框架。
View,表现层(显示数据和收集数据),收集数据的一般是form表单,不过要保证数据的正确性要是用JavaScript验证信息,以后我们会学到的JSP(javaserver page)就是用来表现、显示数据的。
Servlet之间的怎么互相调用在上述基础上需要解决servlet之间的调用:可以利用servletContext解决每一个servlet都可能和上下文交互,则每个servlet中都应该保存一个servletContext对象,去访问整个应用的上下文,步骤如下:
getServletContext()::application
application.getRequestDispatcher(“/res/students/list”)::dis
patcher dispatcher.forward(request,response)
每个JVM中的每一个应用程序里都存在一个上下文
servletContext在servletConfig的对象中;
ServletContext.getRequestDispatcher(Stringpath):返回一个RequestDispatcher
通过RequestDispatcher的forward()或include()方法传送请求。
如何在一个servlet中调用另外一个
servlet:
ServletContext类的getRequestDispatcher(Stringpath)方法获得一个RequestDispatcher对象,并且跳转到指定的Servlet,getRequestDispatcher(Stringpath)方法中的参数就是path,就是指定跳转的Servlet的url-pattern。
RequestDispatcher类的forward(ServletRequestrequest, ServletResponseresponse) 方法,可以把请求对象转发给其他的Servlet。
在多个servlet中传递信息:
HttpServletRequest对象中的方法
setAttribute(String name,Objecto),可以使用HttpServletRequest对象来携带信息,并且可以通过getAttribute(Stringname)方法来获得携带的信息,这两个方法类似于map中的存取方法,setAttribute方法给数据加上标识,getAttribute方法则是通过这个标识来获取数据,可以使用这一对方法的前提就是要保证是同一个请求对象(HttpServletRequest)
转发请求至新的资源
request dispatcher的二种传送请求方式
Forward: 将请求从一个servlet传到服务器上的其他资源
(servlet、JSP、HTML);
Include: 将静态或动态内容包含在当前servlet中;
获得request dispatcher的二种方式:
ServletRequest.getRequestDispatcher() // 相对路径
ServletContext.getRequestDispatcher() // 绝对路径
Response.sendRedirect(/servapp/state/login); //要写绝对路径,产生新的请求,
Forward(req,resp);//在当前路径基础上跳转
两个页面之间跳转的时侯如果需要数据传递,则只能用
forward();因为sendRedirect()会产生一个新的请求。
servlet中使用数据源访问数据库
在服务器中配置数据源(使用admin管理界面)
再servlet中使用JNDI语法获取数据源
Context context = new InitalContext();
DataSource ds =(DataSource)
context.lookup("java:comp/env/"+dsName);
Connection con = ds.getConnection();
新建一个配置文件myapp.xml(假设web应用程序名称为:myapp),将xml文件的头部和一对<Context>标签写入该文件,将server.xml中有关数据源配置的<Resource>标签内容拷贝到myapp.xml中的<context>标签之间。server.xml位于$tomcat/conf/文件夹下,myapp.xml放在$tomcat/conf/catalina/localhost/文件夹下。
数据源配置Server.xml
<Resource
name="jdbc/oracle" 配置JDNI的名字
type="javax.sql.DataSource" 绑定资源的类型
password=“openlab"
driverClassName="oracle.jdbc.driver.OracleDriver" 驱动名
maxIdle=“1”最大空闲连接数
maxWait="-1"等待时间,配置为-1就是无限等待,直到有空闲连接为止
username=“open123"
url="jdbc:oracle:thin:@192.168.0.39:1521:TARENADB"
maxActive="3" 最大活动连接数/>
会话管理
为什么要使用session?
一般来讲,从同一客户打开浏览器连接到服务再到客户关闭浏览器可称为一次会话(中间浏览器可以打开多个窗口)
通信协议分为有状态和无状态两种。Http协议是一种无状态协议。一个客户向服务器发出请求然后服务器返回响应,连接就被关闭了。在服务器端不保留连接的有关信息.因此当下一次连接建立时,服务器已没有以前连接的信息了,无法判断这一次连接和以前的连接是不是属于同一客户发出的。在实际应用中,客户进行一个事务性的操作可能需要对服务器进行好几次连接,这时维护前几次连接的状态就非常重要。
服务器必须能够区分不同的客户,而且还要有为每一个客户存储数据的方法。
session实现的三种方法
Cookie
URL Rewriting
隐藏表单域
使用java servlet API进行会话管理
(session)
java servlet API 主要提供了两个与会话相关
的类和接口:Cookie和HttpSession
Cookie
控制机制:
⊕Browser---------request----- Web server
⊕Web server---------request+info--------- Browser
⊕Browser---------request+info-------- Web server(客户端
带信息来再次访问其标志的资源)
详细解释
Cookie是一小块可以嵌入到Http请求和相应中的数据。
它在服务器端产生,并作为响应头域的一部分返回用户。浏览器收到包含Cookie的响应后,会把Cookie的内容用key-value对的形式写入到一个客户端专门存放Cookie的文本文件中(c:/documentsand setting/$user/Cookies)。浏览器会把Cookie及随后产生的请求发给相同的服务器,服务器可以再次读取Cookie中存放的数据。
Cookie可以进行有效期的设置,过期的Cookie不会发送给服务器。
Cookie的用法:
获取Cookies:Cookie[] all = request.getCookies();
获取Cookies名字:Cookie[i].getName();
获取Cookies的值:Cookie[i].getValue();
为Cookies设置新值:Cookie[i].setValue();
设置Cookie保存的最大期限:
Cookie[i].setMaxAge (int expiry);毫秒
以cookie实现的session的流程:
Browser访问 Web server---- Web server
分给用户一个jsessionId并返回给用户保存在本地,同时将jsessionId保存在session中--- 用户再次访问本Webserver时带着 jsessionId来访问------ Webserver根据用户传过来的jsessionId跟session中的jsessionId比较,如果有相同的,就将这个jsessionId对应的session返回给用户,这样用户可以看到上一次的访问信息。
HttpSession
javax.servlet.http.HttpSession接口封装了HTTP会话的细节,该会话与一段时间内特定的web客户对web服务器的多个请求相关。它由Servlet容器环境实现。对Servlet的开发者隐藏实现的细节。
在Servlet中进行会话管理时,首先要获得会话对象。HttpServletRequest.getSession()对象返回与请求相关的当前HttpSession对象,并且该对象不存在时就创建一个新的对象。
HttpServletRequest.getSession(true)具有相同的功能。如果参数是false,当不存在会话对象的时候就不创建新的,而是返回一个Null值。
容器做的事情
产生不重复的jsessionId;
将jsessionId和session对象映射成表;
将jsessionId返回给用户
(cookie/urlRewriting);
再次访问时,先在表中查jsessionId对应的session;
将查到的session对象的引用放入request给用户。
用户做的事情
request.getSession();
request.setAttribute();
request.getAttribute();
servlet的会话机制(servlet将
cookie/urlRewriting封装而成)
底层的cookie和url之间的过程被封装;
urlRewriting的细节被屏蔽,即jsessionId由容器生成,jsessionId列表由容器维护;
状态对象由容器维护;
容器提供了在状态对象中存取数据的方法;会话状态会被自动持久化。
URLRewriting
Cookies可以用来跟踪某一用户向站点发出的每一个请求,有人认为web站点管理员能都收集到用户所浏览网页的足够信息。这侵犯
了用户的个人隐私权,所以某些用户会关闭浏览器的Cookie功能。这样的话就要求程序员事先在实现Cookie的同时也实现重写URL,那当Cookie失效的时候重写URL就会替代Cookie发挥作用。
Servlet中的数据可见范围和生命周期:
一个应用只有一个上下文对象。
Filter
链式结构的问题.
f.doFilter(r,r)
过滤器是没有url的servlet
容器知道filter的转发顺序,通过配置文件
web.xml中的位置决定执行先后
所以filter就解放了.
2004-9-16星期四 晴 Servlet的基础概念
1. Servlet是什么? 答:
1) 模块化的程序,运行在服务器端,增强了请求/响应导向服务;
2) 应用示例: a. 访问远端对象; b. 跟踪大量信息; c. 多用户协作
2. HTTP和Servlets 答:
1) Servlet是HTTP协议中作为CGI的一个替代品;
2) HttpServlet类用于开发HTTP为基础的Servlet
3. HttpServlet 答:
1)继承抽象类javax.servlet.GenericServlet,实现接口java.io.Serializable;
2) 用以开发Http协议为基础的Servlet
4. 服务方法 答:
1)每当服务接收到对Servlet的请求时,服务器就会产生一个新线程,并调用Service。service方法检查HTTP请求类型(GET、POST、PUT、DELETE等),并相应地调用doGet、doPost、doPut、doDelete等。
2) doGet/doPost方法接收HttpServletRequest和HttpServletResponse对象。
3) 99%的时间里,只需注意GET和/或POST请求;
4) 没有任何doHead方法。
5. 返回响应 答:
1) PrintWriter out = response.getWriter // 用于返回文本数据给客户端
2) ServletOutputStream out = response.getOutputStream //用于返回二进制数据给客户端
6. 支持Servlet的Web服务器 答:
1) J2EE应用服务器包括:Web Container和EJB Container;
2) Web Container的ServletEngine提供对Servlet的运行支持;
2004-9-17星期五 晴 用Servlet处理表单数据
1. Form元素的属性 答:
1) ACTION: 用来指定要处理FORM数据的Servlet的URL,也可以指定FORM数据将要发送到的电子邮件;
2) METHOD: 指定数据传送给HTTP服务器的方法;
3) ENCTYPE: 指定数据在传输之前进行编码的方式,
例multipart/form-data 编码将每个字段作为MIME可兼容的文档的单独部分传输。
2. 解析请求 答:
1) 对于所有的请求:
a. getParameterNames: 以Enumeration形式获取表单中清单, 每一项都可以转换成String;
b. getParameter:返回表单中参数名(区分大小写)对应的值(没有这样的参数,返回null;没有任何值,返回空String);
c. getParameterValues:返回表单中参数名(区分大小写)对应的字符串数组(没有这样的参数,返回null;只有一个值,返回值为单一元素组);Servlet的生命周期
1. Servlet的生命周期 答:
1) 通过web Container装载(J2EE的组件都是被动地装载入Container)并实例化Servlet对象;
2) 调用init()方法(在整个生命周期中只被调用一次);
3) 调用service()方法(在整个生命周期中可被调用多次);
4) 调用destroy()方法(在整个生命周期中只被调用一次);
2. init方法 答:
1) 当首次创建Servlet时就会调用init方法, 而不是每个用户请求都会调用该方法。
2) 除非被destroy方法移除,否则不能被重载;
3) init方法一结束,servlet即可接受客户端请求;
3. init方法实例 答:
1) 在编写接受ServletConfig作为参数的init方法时,应该总是在首行调用super.init;
2) init方法接受ServletConfig作为参数, 用以下方法获得参数值:
a. getInitParameter: 返回指定参数名称对应的值,如果参数不存在,返回null;
b. getInitParameterNames:返回指定参数名称对应的值枚举,如果参数不存在,返回的空枚举;
2004-9-20星期一 阴
3. service方法 答:
1) 每当服务器接收到对Servlet的请求时,服务器就会产生一个新线程, 并调用service。
service方法检查HTTP请求类型,请相应地调用doGet、doPost、doPut、doDelete。
2) 被container调用去响应(ServletResponse)来自客户端的请求(ServletRequest);
4. Servlets的多线程安全 答:
1) 多线程占用资源少,处理速度快,提高了效率。
2) 一些编码建议:
a. 对变量和方法定义适当的访问方式, 例如单纯取值操作不会有多线程安全问题;
b. 同步化所有访问重要数据的实例变量;
c. 创建访问类变量的访问方法。
5. SingleThreadModel接口 答:
1) 如果希望禁止多线程访问,可以让Servlet使用SingleThreadModel接口:
public class YourServlet extends HttpServlet implementsSingleThreadModel{ ... }
2) 使用此接口,系统将保证不会存在多个请求线程同时访问Servlet的单个实例。
但是仍然需要同步对存储在Servlet外部的类变量或共享字段的访问。
3) 如Servlet频繁被访问,则Servlet访问的同步将严重影响性能(延时)。
6. destroy方法 答:
1) 服务器决定删除已经加载的Servlet实例之前将调用Servlet的destroy方法;
2) 该方法允许Servlet:
a. 关闭数据库连接;
b. 中止后台线程;
c. 将Cookie程序清单或访问计数写到磁盘以及执行其他类似的收尾工作。
7. 在Servlet终止时处理Service线程 答:
1) 在destroy()方法中:
如有服务(通过一个同步化的实例方法取得当前线程数大于0),则置关闭状态为true(通过一个同步化的实例方法实现)。
然后循环等待服务线程数为0.
2) 在Service()方法中:如见关闭状态为true,便不执行具体逻辑方法,直接退出。
2004-9-21星期二 晴 资源访问
1. 分布式JAVA技术 答:
1) JDBC; a. 实现了Data和Client的分开; b. 通过简单的配置可以适用不同种类的数据库。
2) RMI(RMI使用的协议为Internet Inter ORB Protocol);
3) CORBA(核心技术为ORB:相应的你的请求转为另一个物理地址另一个不同语言对象的请求。
纯Java的情况下根本不用CORBA);
2. 转发结果至可视页面 答:
1) 用JavaBean(用来装载一组值,遵从一定协议的class)封装结果;
2) 每个JVM中的每一个应用程序里都存在一个上下文;
3) servletContext在servletConfig的对象中;
4) ServletContext.getRequestDispatcher(Stringpath):返回一个RequestDispatcher
5) 通过RequestDispatcher的forward()或include()方法传送请求。
3. 转发请求至新的资源 答:
1) request dispatcher的二种传送请求方式
a. Forward: 将请求从一个servlet传到服务器上的其他资源(servlet、JSP、HTML);
b. Include: 包括静态或动态内容;
2) 获得request dispatcher的二种方式: a.ServletRequest.getRequestDispatcher() // 相对路径 b.ServletContext.getRequestDispatcher() // 绝对路径
3) 四种资源范围
a. javax.servlet.ServletContext: 整个应用程序范围内;
b. javax.servlet.http.HttpSession: 会话期间;
c. javax.servlet.ServletRequest: 一个请求期间;
d. javax.servlet.jsp.PageContext:一个JSP页面;
2004-9-22星期三 晴 Servlets中的持久状态
1. HTTP协议中无状态的优缺点:
优点:可以服务很多客户端;
缺点:不能在多个请求之间共享信息(通过Cookie和Session解决);
2. Cookies 答:
1)Cookies是Web服务器发送到浏览器的简短文本信息,以后在访问同一个Web站点或域时浏览器就会毫无更改地返回该文本信息。
2) 用户可以决定是否接受Cookie。
3) 一个Cookie由以下内容组成: a. 名称; b. 单个值; c. 一些操作属性:路径或所在域、有效期以及版本号。
4) 每个站点,浏览器通常只接受20条Cookie,总共接受300条,以及每条Cookie限制为4KB。
3. 设置Cookie 答:
1) 创建Cookie: Cookie c = new Cookie("CookieName","CookieValue");
2) 设置有效期: c.setMaxAge(int lifetime);黙认为负值,只作用于当前会话,不能存储在磁盘上;如为0值表示删除Cookie;有效值为秒为单位。
3) 在响应头中放置Cookie: response.addCookie(c);
4) 从客户端读取Cookie:
Cookie[] cookies = request.getCookies();
Cookie cookie;
for(int i=0; i" + cookie.getName() + "" + cookie.getValue());}
4. Sessions 答:
1) 一个客户端和一个服务器端一次连接信息的所有集合,通过brower发出,由服务器端的servlet调用;
2) 提供一种方式在多个页面请求间确认用户或者储存关于用户的信息;
3) 实现会话跟踪的三种方式:a. cookie; b. URL重写; c. 隐藏的表单段
5. 设置Sessions 答:
1) 创建Sessions: HttpSession session =request.getSession(true);
// true表示如不存在则创建一个新的session
2) 用指定名称将一个对象绑定到session: public void setAttribute(String name,Object value);
3) 删除与指定名称相关的所有值: public void removeAttribute(String name);
4) 返回会话中所有属性名 public Enumeration getAttributeNames();
Servlet基础
1.介绍Servlet的基本概念(***)
(Servlet、Servlet容器、Servletvs. CGI)——————图示
1)它是由 java 编写的、服务端的小程序。相对而言,Applet和javaScript是客户端小程序。
2)基于Http协议的,运行在web服务器内的。Servlet和CGI都是运行在Web服务器上,用来生成Web页面。
3)没有 main 方法。是接受来自网络的请求(form表单,以及其他的请求),并对不同请求作出不同的响应。
4)由容器管理和调用。这个web容器可以控制Servlet对象的生命周期,控制请求由Servlet对象处理。
5)Web 服务器的辅助应用,处理特定的用户请求,并返回响应。
web服务器,这里的服务器不是硬件概念,而是软件,常用的web服务器有 Tomcat,Jboss等
Tomcat是一个用java语言编写的web服务器,所以需要有相应的java运行环境,也就是JVM,还要配置tomcat的具体路径。
6)继承 java 的优点,与协议、平台无关
2.开发第一个Servlet应用(**)
Web应用的结构
开发一个Servlet应用的步骤
1)建立 Web 应用目录(注意细节:各目录的位置、名称与包含的内容)
2)编写 Java 代码,如:HelloWorld.java
把生成的.class 文件放置到 WebRoot/WEB-INF/classes 目录下
3)编写配置文件:web.xml
放置到 WebRoot/WEB-INF/ 目录下
4)把整个 web 应用放到 �talina_home%/webapps //放到 tomcat的 webapps目录下
3.分析Servlet应用(***)
1)Servlet的继承体系
javax.servlet.Servlet接口--> GenericServlet抽象类 --> HttpServlet--> 自定义类
所有的servlet都必须实现该接口处理各种协议(包括http) 专职处理http协议 也可继承GenericServlet
2)Servlet接口;GenericServlet抽象类;HttpServlet类
Servlet接口(位置:javax.servlet.Servlet)定义了特定的生命周期方法:
init(ServletConfig config)
service(HttpServletRequest request, HttpServletResponseresponse)
destroy()
GenericServlet implements Servlet
实现了 init(ServletConfig config)、destroy()等方法;并提供了 init()方法。
还实现了 ServletConfig 接口。由于这是抽象类,所以必须实现抽象方法:service()
HttpServlet extends GenericServlet (位置:javax.servlet.http.HttpServlet)
具有父类 GenericServlet 类似的方法和对象,是使用 Servlet编程常用的类
支持 HTTP 的 post 和 get 等方法。
3)容器如何找到指定的Servlet?(图示)
Servlet有 3 个"名字":url 名、 应用中的逻辑名、 实际的名字
配置文件 web.xml 都把这几个名字一一对应起来了
Servlet是受容器管理的
request对象、response对象都是容器根据客户端请求而产生的。
容器根据url请求,通过DD(web.xml)配置(url名,内部逻辑名,完全限定名)定位具体的servlet。
容器根据客户请求创建/分配一个线程,并调用servlet的service()方法,把request对象、respone对象作为参数传过去
service()方法会根据客户端请求的Http方法调用不同的HttpServlet的方法(doGet(),doPost(),...);
Servlet使用response对象把处理完的结果响应到客户端。
service()方法结束后,线程要么撤销,要么返回容器的线程池;request对象、response对象都被gc回收。
4.使用Servlet来发送用户输入的信息
1)开发用户登录的应用
2)如何使用Form表单来提交数据
<form action="login" method="POST"enctype="multipart/form-data">
(1)action: 表单提交给服务器的哪个资源处理
"login" 为在 web.xml 中配置的 url-pattern 或者是 jsp、html 文件等。
(2)Get vs. Post方法的比较(使用Http Monitor)
GET---->通过 URL 提交表单信息,由于受到 URL 长度的限制,只能传递大约1024(1K)字节。
通过 http monitor 工具截获请求信息(下面仅写出请求行,请求首部略):
GET/welcome/login.html?username=zhangsan&password=lisiHTTP/1.1
//GET是请求方式; /welcome/login.html是请求路径;?号后面是参数列表,以&分隔; 最后是协议版本
POST--->通过 Http Body 提交表单信息,传输的数据量大,可以达到 2M。
由请求行、请求首部、消息体 三部分组成。
参数放在消息体中,长度不再受限,更安全;而 GET 必须把参数放在请求行。
通过 http monitor 工具截获请求信息(大略):
POST /welcome/login.html HTTP/1.1 //请求行
Accept: ...
Accept-Language: zh-cn,en-us;q=0.5
.....
Host: 127.0.0.1
..... //从请求行以下到这行,都是请求首部
username=zhangsan&password=zhangsan//消息体(有效负载)
enctype: multipart/form-data:在form中设置此属性后,传输的就是二进制数据,常可用于上传文件
5.如何在服务器端获得表单提供的数据
1)HttpServletRequest 对象
由 Web Container 封装了用户的 Http 请求数据包而生成,可通过它获得所有跟用户请求数据报相关的信息。
getProtocol():String ——返回对应的协议 (如:HTTP/1.1)
getMethod():String ——返回 http 对应的方法 (Get|Post)
getRemoteHost():String ——返回远程主机名 (如:127.0.0.1)
getRemotePort():int ——返回远程端口号 (如:55013)
getHeader(String config):String——返回http对应的首部信息(参数如Accept-Language)
getParameter(String name):String ——返回指定参数(name)的值(value)(如:zhangsan)
getParameterValues(String name):String[] ——返回指定输入参数(名为name)的所有值(输入的参数列表)
getParameterNames():Enumeration ——返回请求对象中全部输入参数的名称
(如:java.util.Hashtable$Enumerator@1ff395a)
2)解决 Servlet的中文乱码问题
(1)响应输出静态页面时,处理中文信息乱码: response.setContentType("text/html;charset=utf-8");
(2)获取数据过程中,处理中文输入乱码(3 种方法):
方法一:设置字符编码来解决 post 方法提交表单中文乱码问题。
request.setCharacterEncoding("gbk");
response.setContentType("text/html;charset=utf-8");
必须在第一个 request.getParameter("name"); 之前执行上面的语句。
方法二:重新生成指定编码的字符串
String name = newString(request.getParamete("name").getBytes("iso-8859-1"));
方法三:修改服务器的编码设置——解决 get 方法提交表单中文乱码问题
例如:Tomcat,通过修改%TOMCAT%/conf/server.xml
加入 URIEncoding="utf-8"
(3)静态 html 页面的中文化问题
<head>
<meta http-equiv="content-type" content="text/html;charset=gbk">
</head>
6.请求路径
请求路径是把请求导向到一个 servlet来响应服务。它是由几个重要的部分来组成的。
通过 HttpRequest 对象,暴露了如下信息(对照应用的目录结构):
1)上下文路径(Context Path)
该路径的前缀是和 ServletContext 相关的。
如果 Context 就是 Web 服务器的 URL 命名空间的缺省的根上下文时,那么上下文路径将会是一个空的字符串。
如果上下文并不是服务器的命名空间的根,则上下文路径就以“/”开始,但不能以“/”结束。
2)Servlet路径(ServletPath)
该路径就是直接与激活该请求的相应映射,它也是以“/”开头。
但要注意的是,如果指定的请求是与“/*”模式相匹配,则此时 Servlet路径就是一个空字符串。
3)路径信息(PathInfo)
请求路径中除了上下文路径和 Servlet路径以外的部分。
当没有额外的路径时路径信息就是空的(null),或者它会以“/”开始的字符串。
在 HttpServletRequest 接口中定义如下的方法来访问请求路径的相应信息:
getContextPath();
getServletPath();
getPathInfo();
值得注意的是,请求 URI 和路径的各部分之间的 URL 编码的不同之外,下面的等式恒成立:
requestURI = contextPath + servletPath +pathInfo
getServletConfig()
在servlet初始化时,容器传递进来一个ServletConfig对象并保存在servlet实例中,该对象允许访问两项内容:初始化参数和ServletContext对象,前者通常由容器在文件中指定,允许在运行时向sevrlet传递有关调度信息,比如说getServletConfig().getInitParameter("debug")后者为servlet提供有关容器的信息。此方法可以让servlet在任何时候获得该对象及配置信息。
getServletContext()
一个servlet可以使用getServletContext()方法得到web应用的servletContext
即而使用getServletContext的一些方法来获得一些值
比如说getServletContext().getRealPath("/")来获得系统绝对路径
getServletContext().getResource("WEB-INF/config.xml")来获得xml文件的内容
ServletContext
ServletContext接口表示一个web应用的上下文。可以想象成一个web一个能用的共享数据区域,该区域保存整个web共享数据。
当一个web应用启动的时候,就会创建该ServletContext接口的实现类。我们可以在根据需求,读写ServletContext这个web共享区的数据,那么如何获得ServletContext这个实例呢?下面提供了两种方法
publicServletConfig getServletConfig() {
publicServletConfig getServletConfig() {
returnconfig;
}
publicServletContext getServletContext() {
returngetServletConfig().getServletContext();
}
response.setCharacterEncoding
resp.setContentType("text/html;utf-8");写这句,有时候不起作用。
resp.setCharacterEncoding("UTF-8");写这句才管用。
查了一下:对于发送数据,服务器按照response.setCharacterEncoding—contentType—pageEncoding的优先顺序,对要发送的数据进行编码javax.servlet.ServletContext接口
一个servlet上下文是servlet引擎提供用来服务于Web应用的接口。Servlet上下文具有名字(它属于Web应用的名字)唯一映射到文件系统的一个目录。
一个servlet可以通过ServletConfig对象的getServletContext()方法得到servlet上下文的引用,如果servlet直接或间接调用子类GenericServlet,则可以使用getServletContext()方法。
Web应用中servlet可以使用servlet上下文得到:
1.在调用期间保存和检索属性的功能,并与其他servlet共享这些属性。
2.读取Web应用中文件内容和其他静态资源的功能。
3.互相发送请求的方式。
4.记录错误和信息化消息的功能。
ServletContext接口中的方法
Object getAttribute(String name)返回servlet上下文中具有指定名字的对象,或使用已指定名捆绑一个对象。从Web应用的标准观点看,这样的对象是全局对象,因为它们可以被同一servlet在另一时刻访问。或上下文中任意其他servlet访问。
void setAttribute(String name,Object obj)设置servlet上下文中具有指定名字的对象。
Enumeration getAttributeNames() 返回保存在servlet上下文中所有属性名字的枚举。
ServletContext getContext(String uripath)返回映射到另一URL的servlet上下文。在同一服务器中URL必须是以“/”开头的绝对路径。
String getInitParameter(String name)返回指定上下文范围的初始化参数值。此方法与ServletConfig方法名称不一样,后者只应用于已编码的指定servlet。此方法应用于上下文中所有的参数。
Enumeration getInitParameterNames()返回(可能为空)指定上下文范围的初始化参数值名字的枚举值。
int getMajorVersion() 返回此上下文中支持servlet API级别的最大和最小版本号。
int getMinorVersion()
String getMimeType(String fileName)返回指定文件名的MIME类型。典型情况是基于文件扩展名,而不是文件本身的内容(它可以不必存在)。如果MIME类型未知,可以返回null。
RequestDispatcher getNameDispatcher(String name)返回具有指定名字或路径的servlet或JSP的RequestDispatcher。如果不能创建RequestDispatch,返回null。如果指定路径,必须心“/”开头,并且是相对于servlet上下文的顶部。
RequestDispatcher getNameDispatcher(String path)
String getRealPath(String path)给定一个URI,返回文件系统中URI对应的绝对路径。如果不能进行映射,返回null。
URL getResource(String path)返回相对于servlet上下文或读取URL的输入流的指定绝对路径相对应的URL,如果资源不存在则返回null。
InputStream getResourceAsStream(String path)
String getServerInfo() 返顺servlet引擎的名称和版本号。
void log(String message)
void log(String message,Throwable t)将一个消息写入servlet注册,如果给出Throwable参数,则包含栈轨迹。
void removeAttribute(String name)从servlet上下文中删除指定属性。getServletContext()和getServletConfig()的意思
getServletConfig()在servlet初始化时,容器传递进来一个ServletConfig对象并保存在servlet实例中,该对象允许访问两项内容:初始化参数和ServletContext对象,前者通常由容器在文件中指定,允许在运行时向sevrlet传递有关调度信息,比如说getServletConfig().getInitParameter("debug")后者为servlet提供有关容器的信息。
getServletContext()和getServletConfig()的意思
getServletContext()和getServletConfig()的意思2007-07-0911:10.getServletContext()一个servlet可以使用getServletContext()方法得到web应用的servletContext即而使用getServletContext的一些方法来获得一些值比如说getServletContext().getRealPath("/")来获得系统绝对路径getServletContext().getResource("WEB-INF/config.xml")来获得xml文件的内容。
Servlet的Web应用---三种方法获取表单的各种属性(源码)
一、最通俗的方法:request.getParameter("name属性")
源码:
public voiddoPost(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML4.01 Transitional//EN/">");
out.println("<HTML>");
out.println("<HEAD><TITLE>AServlet</TITLE></HEAD>");
out.println(" <BODY>");
request.setCharacterEncoding("utf-8");
out.println("姓名:"+filterHtml(request.getParameter("name"))+"<br>");
out.println("Email:"+filterHtml(request.getParameter("email"))+"<br>");
out.println("年龄:"+request.getParameter("age")+"<br>");
out.println("编程时间:"+request.getParameter("codetime")+"<br>");
out.println("操作系统:");
String os[]=request.getParameterValues("os");
out.println("<ul>");
for(int i=0;i<os.length;i++){
out.println("<li>"+os[i]+"</li>");
}
out.println("</ul><br>");
out.println("编程语言:");
String language[]=request.getParameterValues("language");
out.println("<ul>");
for(int i=0;i<language.length;i++){
out.println("<li>"+language[i]+"</li>");
}
out.println("</ul><br>");
out.println("建议:"+filterHtml(request.getParameter("comment"))+"<br>");
out.println("</BODY>");
out.println("</HTML>");
out.flush();
out.close();
}此法缺点:需要知道表单的name属性。以下两种不需要知道,就可以。
二、Enumeration e =request.getParameterNames()方法:
public voiddoPost(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
request.setCharacterEncoding("utf-8");out.println("<html>");
out.println("<head><title>displaysurveyinfomation</title></head>");
out.println("<body>");
out.println("<h2>用户输入信息:</h2>");StringparameterName = null;
Enumeration e = request.getParameterNames();
while (e.hasMoreElements()) {
parameterName = (String) e.nextElement();
out.println("参数名称:" + parameterName +"<BR>");
printValues(out, request.getParameterValues(parameterName));
}
out.flush();
out.close();
}public voidprintValues(PrintWriter out, String[] values) {
out.println("<ul>");
for (int i = 0; i < values.length; i++) {
out.println("<li>" + values[i] +"</li>");
}
out.println("</ul>");
}
}三、数组方法:
public voiddoPost(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
request.setCharacterEncoding("utf-8");out.println("<html>");
out.println("<head><title>displaysurveyinfomation</title></head>");
out.println("<body>");
out.println("<h2>用户输入信息:</h2>");StringparameterName = null;
Map map = request.getParameterMap();
Set set=map.keySet();
Iterator it=set.iterator();
while (it.hasNext()) {
parameterName = (String) it.next();
out.println("参数名称:" + parameterName +"<BR>");
printValues(out, request.getParameterValues(parameterName));
}
out.flush();
out.close();
}public voidprintValues(PrintWriter out, String[] values) {
out.println("<ul>");
for (int i = 0; i < values.length; i++) {
out.println("<li>" + values[i] +"</li>");
}
out.println("</ul>");
}
}JavaServlet与Web容器之间的关系
Java是一种动态加载和运行的语言。也就是说当应用程序持有一个类的地址(CLASSPATH)和名称(包名和类名)的情况下,可以在程序运行期间任何时候加载这个类,并创建和使用该类的对象。Servlet就是基于这个机制与Web容器融合在一起的。目前已知的所有支持JavaServlet的Web容器都是采用Java开发的。当Web容器接收到来自客户端的请求信息之后,会根据URL中的Web元件地址信息到Servlet队列中查找对应的Servlet对象,如果找到则直接使用,如果没有找到则加载对应的类,并创建对象。也就是说,Servlet对象是在第一次被使用的时候才创建的,并且一旦创建就会被反复使用,不再创建新的对象。所有创建出的Servlet对象会在Web服务器停止运行的时候统一进行垃圾回收。
为了解决客户端请求地址与JavaServlet之间对应关系问题,Web容器需要一个用来描述这种对应关系的文件,一般是web.xml文件。如果一个Web应用程序中存在很多个Servlet,那么web.xml会变得非常庞大。在Servlet3.0规范推出之后,允许在Servlet代码中使用声明式语法来代替web.xml中的描述信息,这才让web.xml瘦身下来。
web.xml中的listener、 filter、servlet 加载顺序及其详解
一、
1、启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点。
2、紧急着,容创建一个ServletContext(servlet上下文),这个 web项目的所有部分都将共享这个上下文。
3、容器将<context-param>转换为键值对,并交给servletContext。
4、容器创建<listener>中的类实例,创建监听器。
二、
load- on-startup元素在web应用启动的时候指定了servlet被加载的顺序,它的值必须是一个整数。如果它的值是一个负整数或是这个元素不存在,那么容器会在该servlet被调用的时候,加载这个servlet。如果值是正整数或零,容器在配置的时候就加载并初始化这个servlet,容器必须保证值小的先被加载。如果值相等,容器可以自动选择先加载谁。
在servlet的配置当中,<load-on-startup>5</load-on-startup>的含义是:
标记容器是否在启动的时候就加载这个servlet。
当 值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才 加载。
正数的值越小,启动该servlet的优先级越高。
三、
首 先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关。即不会因为 filter 写在 listener的前面而会先加 载 filter。最终得出的结论是:listener -> filter-> servlet
同时还存 在着这样一种配置节:context-param,它用于向 ServletContext提供键值对,即应用程序上下文信息。我们 的 listener, filter 等在初始化时会用到这些上下文中的信息,那么context-param 配置节是不是应该写 在 listener 配置节前呢?实际上 context-param配置节可写在任意位置,因此真正的加载顺序为:context- param -> listener-> filter -> servlet
对于某类配置节而言, 与它们出现的顺序是有关的。以 filter 为例,web.xml 中当然可以定义多个 filter,与filter 相关的一个配置节 是 filter-mapping,这里一定要注意,对于拥有相同 filter-name 的filter 和 filter-mapping 配置 节而言,filter-mapping 必须出现在 filter之后,否则当解析到 filter-mapping 时,它所对应的 filter- name 还未定义。web 容器启动时初始化每个filter 时,是按照 filter 配置节出现的顺序来初始化的,当请求资源匹配多 个 filter-mapping时,filter 拦截资源是按照 filter-mapping 配置节出现的顺序来依次调 用 doFilter()方法的。
servlet 同 filter 类似 ,此处不再赘述。
由 此,可以看出,web.xml 的加载顺序是:context- param -> listener-> filter -> servlet,而同个类型之间的实际程序调用的时候的顺序是根据 对应的 mapping的顺序进行调用的。如何选择一款高性能的Servlet容器
本文为“秋日阳光”原创,转载请注明来源,谢谢!
http://hi.baidu.com/colorsight/blog/item/f0ce3816c5dfe10c4a90a7fa.html
做java开发这么久,一直都用tomcat来开发调试,没有关注过部署,也不大了解其他的servlet容器。做企业应用,一般不会有很大并发的情形,所以,只要是是稳定的容器,都可以,性能不用管太多。公司里一般选择jboss,因为它是免费的。
现在要做一个类似网站的项目,需要面对千万的用户,很高的并发,这时需要考虑容器的性能、稳定性。这是就要考虑使用什么样的servlet容器,我确定了3个标准:首先,服务器平台定为linux,要在linux上有较好的表现;其次,网络模块一定要使用epoll,而且要对epoll比较理解,使用的比较灵活,再好的东西用错了也没用;再次,容器本身要有较好的性能,能兼容最好能兼容jee6。
首先拿tomcat开刀,配置成nio模式,在我的开发机器上,用http_load做200个并发的压力测试。10秒以后,就开始connecttimeout了,我用jstack打印tomcat的堆栈,查看对selector的使用方式。这里的selector是EpollSelector,但是tomcat只使用了一个,在高并发的情况下,竞争还是比较大的,所以,个人认为tomcat的Acceptor的这种结构,从根基上注定了它不能承担高并发下的压力。pass!
而后,我用同样的方法测试了glassfish,它大概使用了5个selector,在同样的并发压力下,表现得非常稳定。单单从这点上来说,glassfish做的还是很出色的。
下一步想测试一下jboss,开源、免费的就这么几个了,我估计不会好到哪去,不过,还是用事实说话,测完再说。
容器本身的性能,不太容易测,所以,就只注重Acceptor,这要这个东西写得好就行,就像大楼一样,根基牢靠。
其实做个容器挺不容易的,一般都还要带一个Acceptor,写Acceptor需要对相应系统上的网络编程api比较熟悉,熟悉它的原理,知道普通用法。如果悟性较高,能创出高明的用法,那就是优秀的人才。其实,这样的人实在不多,举个例子吧,这么多开源的servlet容器,网络性能很好的能有多少呢,很明显,网络性能很好的这些项目,都是对linux网络编程或者ace编程比较熟悉的高手来开发的网络模块,如果对这些东西不熟悉,不可能写出很好的网络程序。当然啦,出门就能踩上牛粪的人除外。Servlet与Servlet容器
1.2Servlet与Servlet容器
JavaServlet(Java服务器小程序)是一个基于Java技术的Web组件,运行在服务器端,由Servlet容器所管理,用于生成动态的内容。Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类。Servlet被编译为平台独立的字节码,可以被动态地加载到支持Java技术的Web服务器中运行。目前Servlet规范最新的版本是2.5。
在上文中,出现了一个概念“Servlet容器”。那么什么是Servlet容器呢?Servlet容器有时候也叫做Servlet引擎,是Web服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务,解码基于MIME的请求,格式化基于MIME的响应。Servlet不能独立运行,它必须被部署到Servlet容器中,由容器来实例化和调用Servlet的方法,Servlet容器在Servlet的生命周期内包容和管理Servlet。
在JSP技术推出后,管理和运行Servlet/JSP的容器也称为Web容器。在本文中,Servlet容器、JSP容器,以及Web容器是同义的。
用户通过单击某个链接或者直接在浏览器的地址栏中输入URL来访问Servlet,Web服务器接收到该请求后,并不是将请求直接交给Servlet,而是交给Servlet容器。Servlet容器实例化Servlet,调用Servlet的一个特定方法对请求进行处理,并产生一个响应。这个响应由Servlet容器返回给Web服务器,Web服务器包装这个响应,以HTTP响应的形式发送给Web浏览器。整个过程如图1-3所示。
图1-3 用户访问Servlet
与CGI程序相比,Servlet具有以下优点:Servlet是单实例多线程的运行方式,每个请求在一个独立的线程中运行,而提供服务的Servlet实例只有一个。
Servlet具有可升级性,能响应更多的请求,因为Servlet容器使用一个线程而不是操作系统进程,而线程仅占用有限的系统资源。
Servlet使用标准的API,被更多的Web服务器所支持。
Servlet使用Java语言编写,因此拥有Java程序语言的所有优点,包括容易开发和平台独立性。
Servlet可以访问Java平台丰富的类库,使得各种应用的开发更为容易。
Servlet容器给Servlet提供额外的功能,如错误处理和安全。