zoukankan      html  css  js  c++  java
  • JavaEE5 Tutorial_Servlet

    Web资源:web组件,静态web文件如图片

    Web程序:可发布的Web资源集合

    Web程序根目录下有个web-inf文件夹,如果只有jsp和静态资源,里面可以没有web.xml

    根目录下可以直接放东西,也可以新建自定义目录

    自动部署功能在开发完上线后要记得关闭,负责一自动重新部署,所有会话将失效

    包javax.servlet和javax.servlet.http提供了servlet的接口和类
    所有的servlet类都必须实现servlet接口,它定义了servlet的生命周期

    父类可以是GenericServlet类或HttpServlet类

    Web容器控制着Servlet的生命周期,当请求调用某个Servlet时
    找到这个类,实例化,init()初始化,都只有一次
    调用service(),传递request和response,可以反复
    最后调用destroy(),一次

    在生命周期中某些事件发生时,可以绑定一些监听器做一些处理
    可以监听ServletContext,Session,Request

    可以指定某个具体异常到某个页面处理

    Web组件之间共享信息可以通过私有的javaBean属性,公开的域对象的属性,干脆数据库,或者其他Web资源

    域对象有四种:
    Javax.servlet.ServletContext
    Javax.servlet.http.HttpSession
    javax.servlet.ServletRequest的子类
    Javax.servlet.jsp.PageContext

    服务器总是要处理并发的情形,Servlet默认不是线程安全的,要自己编程处理

    service()方法对于HttpServlet来说是通过doMethod()实现的
    通常来说都是接受request,进行一些处理,产生response
    对于HttpServlet,要求首先response一个头部,然后是具体内容

    所有的request都实现了ServletRequest接口,它定义了参数,属性,协议信息和本地化信息
    可以用request的getReader或getInputStream手动处理信息
    对于HttpServlet则是一个HttpServletRequest对象,还包括URL,头部信息,查询串等等

    所有的response都实现了ServletResponse接口
    可以用getWriter或getOutputStream手动输出信息
    HttpServletResponse还包括状态码和Cookie信息等


    过滤器可以对requeset和response过滤,当然都包括头部和内容
    过滤器本身并不产生response,它总是依赖于其他的Web资源
    每个Web资源可以有0或多个filter,这个filterchain在Web资源被实例化的时候会被确定

    Filter,FilterChain及FilterConfig接口定义在javax.servlet包中
    通过实现Filter接口定义一个filter,doFilter()方法传递request,response,filterchain
    filterchain的前面是n个filter,最后面是那个Web资源,会依次往后传递
    不调用doFilter()也就是请求被拒绝

    另外filter也有int()和destroy()
    filter可以有初始参数,会通过FilterConfig对象传递到init()方法,整个filter中都可使用

    filter要想修改response必须在response发送到客户端前截获它
    可以传递一个标准输入流来包装response,然后那个Servlet会被阻塞
    现在可以实现自己的response了
    修改request同理

    filter-mapping默认只会过滤request,也就是客户端发来的URL
    自己内部的forward,include,errorpage不会过滤
    /* 表示对所有URL都过滤
    一个filter可以映射到多个web资源,一个web资源也可以映射多个filter

    通过getRequestDispatcher("URL")来获得一个RequestDispatcher对象进行include或forward
    可以从request调用,也可以从ServletContext调用
    不同的是,request得到的可以不用/开头,ServletContext得到的要用/开头
    他俩都是相对于/myWeb/根路径的
    但如果URL不对的话,RequestDispatcher对象会是null,编程时要判断下

    被include的web资源不能更改原来页面的头部

    如果已经想用ServletOutputStream 或 PrintWriter对象输出了,再调用forward会报错
    之前的那个request会作为forward之后的那个页面的request的一些属性存在

    属性名为:javax.servlet.forward.[request-uri|context-path|servlet-path|path-info|query-string]

    Enumeration a = req.getAttributeNames();
    		while(a!=null&&a.hasMoreElements()){//得到转发前的request
    			Object nextElement = a.nextElement();
    			System.out.println(nextElement+"	"+req.getAttribute((String)nextElement));
    		}
    		System.out.println("
    ");

     


    request.getSession()可以得到HttpSession对象,可以附加各种属性供会话调用
    客户端无法通知一个session结束,只能设置几分钟后自动过期
    调用session的某个方法会让这个时间重置,所以是闲置时间
    不过服务器端可以调用invalidate()让会话失效,并删除session数据

    要想使用session跟踪,要调用resoonse.encodeURL(URL)方法
    当cookie不可用时,会自动将sessionId添加到url后面
    通常这么写,response.encodeURL(request.getContextPath()+”/catalog”);


    调用destroy()也不会立即终止Servlet执行,但等待一定时间后会即刻终止
    用以下措施来保证destroy时所有services都已结束:
    1.

    publicclassShutdownExampleextendsHttpServlet{
    privateintserviceCounter=0;//设置一个字段,表示正有几个线程调用该servlet
    ...
    //有线程进入和退出时进行记录
    protected synchronized void enteringServiceMethod(){
    serviceCounter++;
    }
    protected synchronized void leavingServiceMethod(){
    serviceCounter--;
    }
    protected synchronized int numServices(){
    returnserviceCounter;
    }
    }
    protected void service(HttpServletRequestreq,
    HttpServletResponseresp)
    throwsServletException,IOException{
    enteringServiceMethod();
    try{
    super.service(req,resp);
    }finally{
    leavingServiceMethod();
    }
    }


    2.还在调用service时,资源就被destroy了,那当然不行

    public class ShutdownExample extends HttpServlet{
    private boolean shuttingDown;
    ...
    //同步方法来访问
    protectedsynchronizedvoidsetShuttingDown(booleanflag){
    shuttingDown=flag;
    }
    protectedsynchronizedbooleanisShuttingDown(){
    returnshuttingDown;
    }
    }
    public void destroy(){
    //还有线程在使用的话,通知其要关闭了
    if(numServices()>0){
    setShuttingDown(true);
    }
    /*等待service关闭.*/
    while(numServices()>0){
    try{
    Thread.sleep(interval);
    }catch(InterruptedExceptione){
    }
    }
    }
    


    3.需要长时间执行的方法要经常判断该servlet是否要关闭了

    public void doPost(...){
    ...
    for(i=0;((i<lotsOfStuffToDo)&&
    !isShuttingDown());i++){
    try{
    partOfLongRunningOperation(i);
    }catch(InterruptedExceptione){
    ...
    }
    }
    }
    













  • 相关阅读:
    Java单例模式:为什么我强烈推荐你用枚举来实现单例模式
    为什么阿里Java规约要求谨慎修改serialVersionUID字段
    使用MyCat实现MySQL读写分离
    你知道HTTP协议的ETag是干什么的吗?
    在centos7中安装MySQL5.7
    MySQL实现主从复制功能
    Leetcode题目169.求众数(简单)
    Leetcode题目160.相交链表(简单)
    Leetcode题目155.最小栈(简单)
    Leetcode题目152.乘积最大子序列(动态规划-中等)
  • 原文地址:https://www.cnblogs.com/gcg0036/p/4143606.html
Copyright © 2011-2022 走看看