设为首页 收藏本站
查看: 1106|回复: 0

[经验分享] JAVA 由浅及深之 Servlet

[复制链接]

尚未签到

发表于 2017-2-19 11:28:06 | 显示全部楼层 |阅读模式
  原文出处:
  http://hxraid.iteye.com/blog/463701
  http://www.cnblogs.com/200911/archive/2012/05/02/2479880.html(cookie , session)
  http://www.cnblogs.com/cuiliang/archive/2011/10/21/2220671.html
  http://blog.csdn.net/muyihuakai/article/details/5858792
  http://www.cnblogs.com/JesseV/archive/2009/11/17/1605015.html


1 常用的服务器:

(1)IIS
(2)Apache (linux用的最多的)是一种web服务器,使用C语言写的
(3)Tomcat是Apache 总项目的一个,也是一种web服务器,是用java语言写的。叫做jsp和servelet的容器。

  三个概念的理解:
  Servlet容器<Web容器<应用服务器?
  Servlet容器的主要任务就是管理Servlet的生命周期;
  Web容器也称之为web服务器,主要任务就是管理和部署web应用的;
  应用服务器的功能非常强大,不仅可以管理和部署web应用,也可以部署EJB应用,实现容器管理的事务等等。。。
  Web服务器就是跟基于HTTP的请求打交道,而EJB容器更多是跟数据库,事务管理等服务接口交互,所以应用服务器的功能是很多的。
  常见的web服务器就是Tomcat,但Tomcat同样也是Servlet服务器;
  常见的应用服务器有WebLogic,WebSphere,但都是收费的;
  没有Servlet容器,可以用Web容器直接访问静态Html页面,比如安装了apache等;如果需要显示Jsp/Servlet,就需要安装一个Servlet容器;但是光有servlet容器也是不够的,它需要被解析为html显示,所以仍需要一个web容器;所以,我们常把web容器和Servlet容器视为一体,因为他们两个容器都有对方的功能实现了,都没有独立的存在了,比如tomcat!

2 动态的网页技术:

CGI(Common GateWay Interface)
API(NSAPI ,ISAPI)
ASP(active server page)
PHP(personal home page)
JSP/servelet(java server page)


3 servelet 简介:

(1)servelet 是一个服务器小应用程序。
(2)用来完成B/S架构下,客户端请求的响应处理
(3)平台独立,性能优良,能以线程的方式运行。
(4)Servelet一般在容器中运行。
(5)常见的servlet容器:Tomcat
  一个servlet就是Java编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然servlet可以对任何类型的请求产生响应,但通常只用来扩展Web服务器的应用程序。


4 Servlet的工作模式

(1)客户端(很可能是web浏览器)通过Http提出请求
(2)Web服务器接收请求并将其发给Servlet。
(3)Servlet程序将接收该http请求并执行某种处理。
(4)Servlet会将处理后的结果向web服务器返回应答。
(5)Web服务器将从Servlet收到的应答发回给客户端。
  运行时阶段当容器接受到访问特定的servlet请求时,针对这个请求,创建对应的ServletRequest对象和 ServletResponse对象,并调用servlet的service()方法,service()根据从ServletRequest对象中获得 客户的请求信息并将调用相应的doxxx方法等进行响应,再通过ServletResponse对象生成响应结果,然后发送给客户端,最后销毁创建的ServletRequest 和ServletResponse

5 Servlet生命周期:
  1)  装载Servlet : 在WEB.XML种配置<load-on-startup></load-on-startup>,指定当Web应用启动时,装载Servlet的次序。   
                                 当值为正数或零时:Servlet容器先加载数值小的servlet,再依次加载其他数值大的servlet.   
                                 当值为负或未定义:Servlet容器将在Web客户首次访问这个servlet时加载它
            然而,Server通常会提供一个管理的选项,用于在Server启动时强制装载和初始化特定的Servlet。
  2)  Server创建一个Servlet的实例
3)  Server调用Servlet的init()方法
4)  一个客户端的请求到达Server(要看配置文件中如何配置,也许是最先的步骤)
5)  Server创建一个请求对象
6)  Server创建一个响应对象
7)  Server激活Servlet的service()方法,传递请求和响应对象作为参数
8)  service()方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息
9)  service()方法使用响应对象的方法,将响应传回Server,最终到达客户端。service()方法可能激活其它方法以处理请求,如doGet()或doPost()或程序员自己开发的新的方法。
  10) 对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用init()方法。一般Servlet只初始化一次(只有一个对象),当Server不再需要Servlet时(一般当Server关闭时),Server调用Servlet的Destroy()方法。


6 Servlet 中service方法详解:
    每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是上文提到的init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet基于HTTP协议,继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可
    HttpServlet 中重写了GenericServlet的service(),同时也对其进行了重载!源码如下:
    



/**
* 通过参数的向下转型,然后调用重载的
*/
//重写
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
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);//调用重载的方法
    }
//重载
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if(method.equals("GET"))
{
long lastModified = getLastModified(req);
if(lastModified == -1L)
{
doGet(req, resp);
} else
{
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if(ifModifiedSince < (lastModified / 1000L) * 1000L)
{
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else
{
resp.setStatus(304);
}
}
} else
if(method.equals("HEAD"))
{
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else
if(method.equals("POST"))
doPost(req, resp);
else
if(method.equals("PUT"))
doPut(req, resp);
else
if(method.equals("DELETE"))
doDelete(req, resp);
else
if(method.equals("OPTIONS"))
doOptions(req, resp);
else
if(method.equals("TRACE"))
{
doTrace(req, resp);
} else{
String errMsg = lStrings.getString("http.method_not_implemented");
Object errArgs[] = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}




7 Servlet / Filter / Listener 的介绍和使用
    从使用上看可以分为三种:简单Servlet、过滤Servlet(Filter) 和监听Servlet(Listener)
  加载顺序为:context-param -> listener -> filter -> servlet

1) 过滤器:

  是以一种组件的形式绑定在web应用程序当中的,与其他的Web应用程序组件不同的是,过滤器是采用链的方式进行处理的。一旦加入过滤器,所有的请求先交给过滤器处理,然后再访问相应的web资源的访问限制。

  实现过滤器:如果定义一个过滤器,则直接让一个类实现javax.servlet.Filter接口即可。
  Public void init(FilterConfig filterConfig)Throws ServletException
  public void doFilter(ServletRequest request,Servlet response,FilterChain chain)
  实现具体的过滤操作,然后通过FilterChain让请求继续向下传递。chain.doFilter(request,response);
  
  过滤器的销毁 public void destroy()

2) 过滤器的应用:

实例一:编码过滤器EncodingFilter.java

为所有页面设置统一的编码:如果按照之前的做法,在每一个JSP或者Servlet中都重复编写request.setCharacterEncoding("GBK")的语句肯定是不可取的,会造成大量的代码重复。

<!-- 编码过滤 -->
方法1:
在web.xml中配置:



<filter>
<filter-name>encoding</filter-name>
<filter-class>com.myTest.setCharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在servlet中写:



public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("GB18030");
response.setCharacterEncoding("GB18030");
chain.doFilter(request, response);
}
方法2:
<!-- 编码过滤 -->



<filter>
<filter-name>encoding</filter-name>
<filter-class>
com.myTest.setCharacterEncodingFilter
</filter-class>
<init-param>
<param-name>charset</param-name>
<param-value>GB18030</param-value>
</init-param>
</filter>



public void init(FilterConfig config) throws ServletException {
// TODO Auto-generated method stub
this.charSet=config.getInitParameter("charset");//取得初始化参数

}
实例二:登陆验证:最早的做法是通过session的方式完成,但是每个页面都这样的话,则肯定造成大量代码的重复,而通过过滤器的方法即可避免这种重复操作。
注意:向下转型:将ServletRequest转为HttpServletRequest。
总结:过滤器属于自动执行的一种servlet,过滤器依然需要在web.xml文件中进行配置。过滤器常用的功能是可以完成常用的编码过滤,及登录验证。



2) 监听器

  第三种servlet程序称为监听servlet,主要功能负责Web的各种操作,当相关的事件触发后将产生事件并对此事和request三种操作进行监听。
  (-)监听器主要对三个事件的动作监听:
  1 对servletContext的监听
  2 对session的监听
  3 对request的监听
  
  示例一:当你需要在处理任何客户端请求之前创建一个数据库连接,并且希望在整个应用过程中该连接都是可用的,这个时候ServletContextListener接口就会十分有用了。
  http://chenchh.iteye.com/blog/669956
  示例二:监听器:在线人员统计
  http://blog.csdn.net/zhangkai08111/article/details/2787972
Session的操作:
当一个新用户打开一个动态页时,服务器会为新用户分配session,并触发HttpsessionLisener接口中的sessionCreate()事件,但是在用户销毁时时却有两种不同的方式触发sessionDestroy()事件。
方式一:调用HttpSession接口中的invalidate()方法,让一个session失效。
方式二:超过了配置session的超时时间,session超时时间可以直接在项目中的web.xml中配置。
<session-config>
<session-timeout>5</session-timeout>
<session_config>
默认的超时时间为30分钟。

3) Servlet跳转:

1.客户端跳转:在Servlet中要想进行客户端跳转,(地址栏会发生变化)直接使用HttpServletResponse接口的sendRedirect()方法即可。(但是要注意的是,此跳转只能传递session范围的属性,而无法传递request范围的属性,这是因为request属性范围只有在服务器端跳转中才可以使用)。
2.服务器端跳转:在Servlet中没有像JSP中的<jsp:forward>指令,所以如果要想执行服务器端跳转,就必须依靠RequestDispatcher接口完成。
提供两方法:forword()和include()可完成跳转实现。
但是还不够:如果要想使用此接口还要使用ServletRequest接口进行方法的实例化。
ServletRequest接口进行方法的实例化:Public RequestDispatcher getRequestDispatcher(String path){}
服务器端跳转之后,页面路径不会发生改变,而且此时可以在跳转后的JSP文件中接收到session及request范围的属性。




Servlet 单例多线程详解:
当Servlet容器收到一个Servlet请求,调度线程从线程池中选出一个工作者线程,将请求传递给该工作者线程,然后由该线程来执行Servlet的service方法。当这个线程正在执行的时候,容器收到另外一个请求,调度线程同样从线程池中选出另一个工作者线程来服务新的请求,容器并不关心这个请求是否访问的是同一个Servlet.当容器同时收到对同一个Servlet的多个请求的时候,那么这个Servlet的service()方法将在多线程中并发执行。
Servlet容器默认采用单实例多线程的方式来处理请求,这样减少产生Servlet实例的开销,提升了对请求的响应时间,对于Tomcat可以在server.xml中通过<Connector>元素设置线程池中线程的数目。
  PS:
  Servlet并非只是单例的. 当container开始启动,或是客户端发出请求服务时,Container会按照容器的配置负责加载和实例化一个Servlet(也可以配置为多个,不过一般不这么干).不过一般来说一个servlet只会有一个实例。
  1) Struts2的Action是原型,非单实例的;会对每一个请求,产生一个Action的实例来处理。
2) Struts1的Action,Spring的Ioc容器管理的bean 默认是单实例的.
  
Struts1 Action是单实例的,spring mvc的controller也是如此。因此开发时要求必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
  Spring的Ioc容器管理的bean 默认是单实例的。
  Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)。
  当Spring管理Struts2的Action时,bean默认是单实例的,可以通过配置参数将其设置为原型。(scope="prototype )
http://www.iyunv.com/kf/201302/189179.html
http://wenku.baidu.com/view/4bf3802cb4daa58da0114ad1.html
http://blog.csdn.net/ji_ju/article/details/8603387

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-344190-1-1.html 上篇帖子: 系统集成项目管理工程师重点知识 下篇帖子: 从程序员到CTO的Java技术路线图
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表