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等)。
继续用文本编辑器,新建一个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下,访问,可以看到结果。
Servelet 3.0引入@WebServlet注释。在java代码里做些修改:
@WebInitParam可以设置Servlet的初始化参数,而后通过Servlet的getServletConfig().getInitParameter方法可以访问这些参数:
InitParamServlet
zp.javaee.InitParamServlet
name
zp
. . .
. . .
Filter可以用来处理特定url的事件:
SimpleFilter
SimpleFilter
SimpleFilter
/*
Listener可以监听网站的事件,比如:
org.javaeerecipes.chapter01.recipe01_07.StartupShutdownListener
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("");
}
}
覆盖servlet的destroy方法,在里面释放资源。
安装
从下载安装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
*
*
*
* @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("
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";
}//
}
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("
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文件:
xsi:schemaLocation=" /web-app_3_0.xsd"
version="3.0">
打包布署
新建一个名为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 {
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( "
...
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中定义:
. . .
. . .
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片段:
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片段:
监听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");
}
}
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());
}
}
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 Cookie Set 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方法,在里面释放资源。