Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1797816
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: Java

2013-07-01 22:16:52

Java Servlet在是第一种Java网页应用的技术。Sun公司在1997年发布了第一个Java Servlet规范。Servlet是所有Java EE应用的基础,JSP和JSF框架最终都把页面编译成Java Servlet。虽然Servlet可以响应任何类型的请求,但它大多数是响应基于web的请求。Servlet必须布署在Java Servlet容器里,比如Oracle的GlassFish(其它的还有JBoss, Apache TomEE, WebLogic等)。


安装

从下载安装GlassFish,用以下命令启动:
/PATH_TO_GLASSFISH/Glassfish/bin/asadmin start-domain domain1
之后访问可进入管理控制台。


java代码

用文本编辑器新建一个名为SimpleServlet.java,然后敲入代码:
package zp.javaee;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SimpleServlet extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * GET and
     * POST methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
           // Place page output here
            out.println("");
            out.println("");
            out.println("Servlet SimpleServlet");
            out.println("");
            out.println("");
            out.println("

Servlet SimpleServlet at " + request.getContextPath() + "

");
            out.println(" ");
            out.println("");
        } finally {
            out.close();
        }
    }

   /**
     * Handles the HTTP GET
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP POST
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet for documentation purposes.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }//
}


编译

命令javac -cp c:\glassfish4\glassfish\modules\javax.servlet-api.jar SimpleServlet.java,编译出SimpleServlet.class。


web.xml

继续用文本编辑器,新建一个web.xml文件:

    xmlns:xsi=""
    xsi:schemaLocation=" /web-app_3_0.xsd"
    version="3.0">
   
        SimpleServlet
        zp.javaee.SimpleServlet
   

   
        SimpleServlet
        /SimpleServlet
   

   
        /SimpleServlet
   



打包布署

新建一个名为SampleServlet的文件夹,在它下面再创建名为”WEB-INF"的文件夹,把web.xml拷贝到这里。在”WEB-INF"下分别建两个名为”classes"和"lib"的文件夹,在class里根据包名建立文件夹,拷贝SimpleServlt拷贝到WEB-INF/classes/zp/javaee下。最后把整个SampleServlet文件夹拷贝到C:\glassfish4\glassfish\domains\domain1\autodeploy下,访问,可以看到结果。

在熟悉了Servlet的底层逻辑后,就不再需要做这些繁琐的事情,而是让IDE去做。


去除web.xml

Servelet 3.0引入@WebServlet注释。在java代码里做些修改:
...
import javax.servlet.annotation.WebServlet;
...
@WebServlet(name = "SimpleServlet", urlPatterns = {"/SimpleServlet"})
public class SimpleServlet extends HttpServlet {
...
在打包时只拷贝这个类的class文件,而不再需要web.xml文件。

注意:一个Servlet对象会被多个Client并发使用,所以它的成员变量在使用时需要进行线程保护。


Servlet的初始化参数

@WebInitParam可以设置Servlet的初始化参数,而后通过Servlet的getServletConfig().getInitParameter方法可以访问这些参数:
...
import javax.servlet.annotation.WebInitParam;
...
@WebServlet (name="InitParamServlet" , urlPatterns={"/InitParamServlet" },initParams={ @WebInitParam(name= "name" , value="zp" ) })
public class InitParamServlet extends HttpServlet {
...
       protected void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException {
...
                     out.println( "

" + getServletConfig().getInitParameter("name" ) + "

");
...

@WebInitParam等价于在web.xml中定义:

   
        InitParamServlet
        zp.javaee.InitParamServlet

       
            name
            zp
       

    . . .
   
    . . .


Filter

Filter可以用来处理特定url的事件:
package zp.javaee;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter("/*" )
public class SimpleFilter implements Filter {

        @Override
        public void destroy() {
               throw new UnsupportedOperationException("Not supported yet.");
       }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {
              String userAddy = request.getRemoteHost();
        filterConf.getServletContext().log("Vistor User IP: " + userAddy);
        chain.doFilter(request, response);
       }

        @Override
        public void init(FilterConfig filterConf) throws ServletException {
               this.filterConf = filterConf;
       }

        private FilterConfig filterConf ;
}
把Filter和SimpleServlet与InitParamServlet打包进同一个网站后,访问和都会在log中打印用户的IP。哪怕是访问不存在的类,Filter仍然会被触发。

@WebFilter注释等价于下面的web.xml片段:

    SimpleFilter
    SimpleFilter


    SimpleFilter
    /*


Listener

Listener可以监听网站的事件,比如:
package zp.javaee;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class SimpleListener implements ServletContextListener {
       
        @Override
        public void contextDestroyed(ServletContextEvent event) {
              System. out.println("Servlet shutdown. . ." );
        System. out.println(event.getServletContext().getServerInfo());
        System. out.println(System.currentTimeMillis());
       }

        @Override
        public void contextInitialized(ServletContextEvent event) {
              System. out.println("Servlet startup. . ." );
        System. out.println(event.getServletContext().getServerInfo());
        System. out.println(System.currentTimeMillis());
       }

}
每次在网站重新布署时,这两个Listener的两个方法就会被触发。

@WebListener等价于web.xml片段:

    org.javaeerecipes.chapter01.recipe01_07.StartupShutdownListener

监听Session事件
package zp.javaee;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class SimpleSessionListener implements HttpSessionListener {

     @Override
     public void sessionCreated(HttpSessionEvent event) {
          event.getSession().setMaxInactiveInterval(60);
          event.getSession().setAttribute("name", "zp");
          System.out.println("Session created");
     }

     @Override
     public void sessionDestroyed(HttpSessionEvent event) {
          System.out.println("Session destoryed");
     }

}

提示:在Servelet的实现里可以调用HttpServletRequest的getSession(true)方法来创建session。

监听Session Attribute事件
package zp.javaee;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener
public class SimpleSessionAttributeListener implements
          HttpSessionAttributeListener {

     @Override
     public void attributeAdded(HttpSessionBindingEvent event) {
          System.out.println("Attribute added session: " + event.getSession().getId());
          System.out.println("Attribute added: " + event.getName() + " - " + event.getValue());
     }

     @Override
     public void attributeRemoved(HttpSessionBindingEvent event) {
          System.out.println("Attribute removed session: " + event.getSession().getId());
          System.out.println("Attribute removed: " + event.getName() + " - " + event.getValue());
     }

     @Override
     public void attributeReplaced(HttpSessionBindingEvent event) {
          System.out.println("Attribute replaced session: " + event.getSession().getId());
          System.out.println("Attribute replaced: " + event.getName() + " - " + event.getValue());
     }

}


下载文件

package zp.javaee;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name="SimpleDownloadServlet" , urlPatterns="/SimpleDownloadServlet")
public class SimpleDownloadServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException {
              String fileToDownload = request.getParameter( "filename");
               final int BYTES = 1024;
        int                 length   = 0;
        ServletOutputStream outStream = response.getOutputStream();
        ServletContext      context  = getServletConfig().getServletContext();
 
        response.setContentType( (context.getMimeType( fileToDownload ) != null) ?
                context.getMimeType(fileToDownload) : "text/plain" );
        response.setHeader( "Content-Disposition", "attachment; filename=\"" + fileToDownload + "\"" );

        InputStream in = context.getResourceAsStream( "/" + fileToDownload);
        byte[] bbuf = new byte[BYTES];
        
        while ((in != null ) && ((length = in.read(bbuf)) != -1))
        {
            outStream.write(bbuf,0,length);
        }

        outStream.flush();
        outStream.close();
       }

}


将请求转接到别的Servlet

package zp.javaee;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name="SimpleDispatcherServlet" , urlPatterns="/SimpleDispatcherServlet" )
public class SimpleDispatcherServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException {
              ServletContext sc = getServletConfig().getServletContext();
              RequestDispatcher rd = sc.getRequestDispatcher("/SimpleDownloadServlet" );
              rd.forward(request, response);
       }
}


重定向到外网

package zp.javaee;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name="SimpleRedirectServlet", urlPatterns="/SimpleRedirectServlet")
public class SimpleRedirectServlet extends HttpServlet {

     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse response)
               throws ServletException, IOException {
          response.sendRedirect("");
     }

}


Cookie

package zp.javaee;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet (name="SimpleWriteCookieServlet" , urlPatterns="/SimpleWriteCookieServlet" )
public class SimpleWriteCookieServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException {
              response.setContentType( "text/html;charset=UTF-8" );
        PrintWriter out = response.getWriter();
        Cookie cookie = new Cookie("name" ,"zp" );
        cookie.setHttpOnly( true );
        cookie.setMaxAge(-30);
        response.addCookie(cookie);
        out.println( "Set CookieSet Cookie");
        out.close();
       }

}

package zp.javaee;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet (name="SimpleReadCookieServlet" , urlPatterns="/SimpleReadCookieServlet" )
public class SimpleReadCookieServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest request,
                     HttpServletResponse response) throws ServletException, IOException {
              response.setContentType( "text/html;charset=UTF-8" );
              PrintWriter out = response.getWriter();
              out.println( "Set Cookie" );
              Cookie[] cookies = request.getCookies();
               for (Cookie cookie : cookies) {
                     out.println( "

" cookie.getName() + " : " cookie.getValue() + "

"
);
                     out.println( "" );
              }
              out.close();
       }
}


析构

覆盖servlet的destroy方法,在里面释放资源。


阅读(4541) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~