servlet
Servlet
一.Servlet接口定义了五个方法
1.void init(ServletConfig config) throws ServletException
当Servlet第一次被请求时,Servlet容器会调用这个方法,之后不会再调用
2. void service(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException
除了第一次被请求时同时调用init()和dervice两个方法外,其余每次请求都只是调用service方法
3. void destroy()
销毁servlet对象时调用
4. java.lang.String getServletInfo()
返回servlet描述
5. ServletConfig getServletConfig()
返回由Servlet容器传给init方法的ServletConfig
package app; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebServlet; /*WebServlet 用来声明一个Servlet,命名servlet时,还可以暗示容器, * usrlPatterns 告诉容器,/my样式表示应该调用Servlet */ @WebServlet( name = "Myservlet", urlPatterns = {"/my"}) public class MyServlet implements Servlet { //transient变量不能被序列化 private transient ServletConfig servletConfig; //init方法只会调用一次,并接受servletConfig @Override public void init(ServletConfig servletConfig) throws ServletException{ this.servletConfig = servletConfig; } @Override public ServletConfig getServletConfig(){ return servletConfig; } @Override public String getServletInfo(){ return "My Servlet"; } /*Service 发送字符串"hello from MyServlet"给浏览器 *对于每个http请求,Servlet容器都会创建一个ServletRequest实例,并将它传给Servlet的Service方法 * */ @Override public void service(ServletRequest request,ServletResponse response) throws ServletException,IOException{ String servletName = servletConfig.getServletName(); response.setContentType("text/html"); //在发送任何HTML标签前,应该先调用setContentType()方法,设置响应的内容类型 PrintWriter writer = response.getWriter(); //返回一个可以向客户端发送文本的printWriter String id = request.getParameter("id");//返回指定请求参数的值 writer.print("<html><head></head>" + "<body>Hello from " + servletName + " id = " + id + "</body></html>"); //发送数据 } @Override public void destroy(){ } public static void main(String[] args){ } }
二.ServletRequest接口有一些方法
public int getContentLength() /返回请求主体的字节数,如果不知道字节长度,返回-1 public java.lang.String getContentType() //返回请求主体的MIME类型,如果不知道类型返回null public java.lang.String getParameter(java.lang.String name) //返回指定请求参数的值 public java.lang.String getProtocol() //返回这个HTTP请求协议名称和版本
public java.lang.String getParameter(java.lang.String name) 用法
-
String id = request.getParameter("id"); writer.print("<html><head></head>" + "<body>Hello from " + servletName + " id = " + id + "</body></html>");
三.servletResponse
java.servlet.ServletResponse 接口表示一个Servlet响应,哎调用Servlet的service方法前,Servlet容器先创建一个ServletResponse,并将它作为第二个参数传给Service方法,ServletResponse隐藏了向浏览器发送响应的复杂过程
ServletResponse接口的方法
public java.io.PrintWriter getWriter() //返回一个可以向客户端发送文本的printWriter, 它就是getOutputStream,但这个方法只能发送二进制数据
使用方法
四.ServletConfig
当Servlet 容器初始化 Servlet 时, Servlet 容器会给 Servlet 的 init 方法传入一个 ServletConfig, ServletConfig封装可以通过@WebServlet或者部署描述符传给Servlet的配置信息这样传入的每一条信息就叫一个初始参数,一个初始参数由key和value两个元件
为了从Servlet内部获取到初始参数的值,要在Servlet容器传给Servlet的init方法的 ServletConfig中调用getInitParameter方法, getInitParameter的方法签名如下:
java.lang.String getInitParameter(java.lang.String name) //返回所有初始参数名称的一个Enumeration(目录)
java.util.Enumeration<java.lang.String> getInitParameterNames()
-
Stirng contactName = servletConfig.getInitParameter("contactName"); //返回contactName参数的值
示例
package app; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; @WebServlet(name = "ServletConfigDemoServlet", urlPatterns = {"/servletConfigDemo"}, initParams = { //给Servlet 传入两个参数(admin和email) @WebInitParam(name="admin", value="Harry Taciak"), @WebInitParam(name="email", value = "admin@example.com") }) public class ServletConfigDemoServlet implements Servlet{ private transient ServletConfig servletConfig; @Override public void destroy() { // TODO Auto-generated method stub } @Override public ServletConfig getServletConfig() { return servletConfig; } @Override public String getServletInfo() { return "ServletConfig Demo1"; } @Override public void init(ServletConfig servletConfig) throws ServletException { this.servletConfig = servletConfig; //接受servletConfig } @Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { ServletConfig servletConfig = getServletConfig();// String admin = servletConfig.getInitParameter("admin"); //得到admin的value String email = servletConfig.getInitParameter("email"); //的到Email的value response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.print("<html><head></head><body>" + "Admin: " + admin + "<br /> Eamil: " + email + "</body></html>"); } }
浏览器查看结果
五.ServletContext
ServletContext 表示Servlet 应用程序,每个Web应用程序只有一个上下文, 在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的 Web应用都会由一个ServletContext对象.
通过在ServletConfig 中调用getServletContext方法, 可以获得ServletContext.
有了ServletContext, 就可以共享从应用程序的所有资料处访问到的信息,并且可以动态注册Web对象,前者将对象保存在ServletContext中的一个内部Map中,保存在Servlet中对象被称为属性
ServletContext中的下列方法负责处理属性:
java.lang.Object get.Attribute(java.lang.String name)//attribute(属性)
java.util.Enumeration<java.lang.String> getAttributeNames() //Enumeration(数目)
void setAttribute(java.lang.String name, java.lang.Objetc object);//
六. GenericServlet 抽象类
抽象类GenericServlet 实现了Servlet和ServletConfig接口,并完成了以下任务
- 将init方法中的ServletConfig赋给了一个类级变量,以便通过调用getServletConfig获取
- 未Servlet接口中的所有方法提供默认的实现
- 提供默认方法,包围ServletConfig中的方法
package app; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.GenericServlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebInitParam; @WebServlet(name = "GenricServletDemoServlet", urlPatterns = { "/generic" }, initParams = { @WebInitParam(name="admin", value="jiangfeilong"), @WebInitParam(name="email", value="admin@example.com") } ) public class GenericServletDemoServlet extends GenericServlet{ /** * */ private static final long serialVersionUID = 62500890L; //版本id @Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { ServletConfig servletConfig = this.getServletConfig(); String admin = servletConfig.getInitParameter("admin"); String email = servletConfig.getInitParameter("email"); response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.print("<html><head></head><body>" + "Admin: " + admin + "<br /> Eamil: " + email + "</body></html>"); } }
运行
七: HttpServlet
java.servlet.http中的许多类继承了javax.servlet中的类型
HttpServlet | javax.servlet.GenericServletServlet | javax.servletServlet(接口) |
HttpSession(接口) | httpservletRequest(接口) | javax.servlet.ServletRequset(接口) |
Cookie | HttpServletResponse(接口) | javax.servlet.ServletResponse(接口) |
1.HttpServlet
HttpServlet覆盖了GenericServlet中的Service方法,并通过下列签名再添加了一个Service方法,参数链表都是http开头
protected void service(HttpServletRequest, HttpServletResponse response) throws ServletException, java.io.IOException
Servlet容器调用javax.servlet.Servlet中原始的Service方法,HttpServlet中的编写方法如下:
public void service(ServletRequset req,ServletResponse res) throws ServletException, IOException{ HttpServletRequset requset; HtttpServletResponse response; try{ request = (HtppServletRequest) req; response = (httpServletResponse) res; }catch (ClassCastException e){ throw new ServletException("non--Http request or response"); } service(request,response); }
HttpServlet特性是GenericServlet所不具备的,不用覆盖方法,而是覆盖doGet或这doPost,在少数情况下花卉覆盖以下任意方法: doHead, doPut , doTrace, doOptions 和 doDelete
2.HttpServletRequest
HttpServletRequest 表示Http环境中的Servlet请求,它扩展javax.servlet.ServletRequest接口,并增加了下列几个方法
java.lang.String getContextPath()//放回表示请求上下文的URI部分
Cookie[] getCookies(); //返回Cookie对象数组
java.lang.String getHeader(java.lang.String name)//返回指定HTTP标题的值
java.lang.String.getMethod() //返回生成这个请求的http方法的名称
java.lang.String getQueryString() //返回请求URL中的查询字符
HttpSession getSession() //返回与这个请求相关的会话对象,如果没有,将会创建一个新的会话对象
HttpSession getSession(boolean create) //返回与这个请求相关的会话对象,如果没有,并且create参数为true,将会创建一个新的会话对象
3.HttpServletResponse
HttpServletResponse 表示HTTP环境中的Servlet响应,下面是它里面定义的部分方法:
void addCookie(Cookie cookie) /给一个响应对象添加一个cookie
void addheader(java.lang.String name, java.lang.String value) //给一个响应对象添加一个header
void sendRedirect( java.lang.String location)//发送一条响应码,将浏览器跳转到指定的位置
4.处理HTTP表单
包含多个知道select元素(<select multiple>表示的select元素)发出一个字符串数组,必须通过ServletRequest.getParameterValues处理
复选框比较奇特,核查过的复选框会发送字符串"on"到服务器,未经核查的复选框不向服务器发送任何数据
单选框将被选择的值发送到服务器,如果没有选择任何值,将不会发送任何内容到服务器
如果一个表单中包含多个输入同名的元素,那么所有值都会被提交,并且必须利用ServletRequest.getParameterValues来获取它们,ServletRequest.getParameter将只返回最后一个值
当浏览器发送请求时,会调用ServletHttp 的doGet方法,当有表单提交时会调用doPost()方法
HttpServlet类
package app; import java.io.*; import java.io.IOException; import java.io.PrintWriter; import java.util.regex.*; import java.util.Enumeration; 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 = "FormServlet", urlPatterns = "/form") public class FormServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String[] nReplace = { "NAME", "ADDRESS", "COUNTRY", "DELMETHOD", "CATALOG", "INSTRUCTIONS", "PARAMETERNAMES" }; private static final String[] names = { "name", "address", "country", "delivery", "catalog", "instruction", "parameternames" }; private static final String[] nValue = new String[7]; //当html页面的标签<form method ="get" >是get方法时会调用此方法 @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter writer = response.getWriter(); String path = this.getServletContext().getRealPath("/WEB-INF/form.html"); String s = null; s = read(path); writer.print(s); } //当html页面的标签<form method ="post" >是post方法时会调用此方法 @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter writer = response.getWriter(); StringBuilder INSTRUCTIONS = new StringBuilder(); StringBuilder PARAMETERNAMES = new StringBuilder(); for (int i = 0; i < 4; i++) nValue[i] = request.getParameter(names[i]); // 得到元素的值 String[] instructions = request.getParameterValues("instruction"); if (instructions != null) { for (String instruction : instructions) INSTRUCTIONS.append(instruction + "<br>"); nValue[5] = INSTRUCTIONS.toString(); } if (request.getParameter("catalog") == null) nValue[4] = "No"; else nValue[4] = "Yes"; Enumeration<String> parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { String parameterName = parameterNames.nextElement(); PARAMETERNAMES.append(parameterName + "<br />"); nValue[6] = PARAMETERNAMES.toString(); } String path = this.getServletContext().getRealPath("/WEB-INF/order_form.html"); String s = null; s = read(path); for (int i = 0; i < nReplace.length; i++) s = replace(s, nReplace[i],nValue[i]); writer.print(s); } public static String replace(String html, String nReplace, String nameValue) { String str = html; Pattern pattern = Pattern.compile(">" + nReplace); Matcher matcher = pattern.matcher(html); if(nameValue !=null ) str = matcher.replaceAll(">" +nameValue); else str = matcher.replaceAll(">"); return str; } public static String read(String path) throws IOException { StringBuilder sb = new StringBuilder(); try (BufferedReader in = new BufferedReader(new FileReader(new File(path).getAbsoluteFile()))) { try { String s = null; while ((s = in.readLine()) != null) { sb.append(s + "\n"); } } finally { if (in != null) try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } catch (IOException e) { throw new RuntimeException(e); } return sb.toString(); } }
get页面(html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Order Form</title> </head> <body> <h1>Order Form</h1> <form method='post'> <table> <tr> <td>Name:</td><td><input name='name' /></td> </tr> <tr> <td>Address:</td> <!--文本区域 会将文字发送给服务器,如若没有任何内容,则会发送空字符""给服务器 --> <td><textarea name="address" id="" cols="40" rows="5"></textarea></td> </tr> <tr> <td>Country:</td> <!-- 下拉框select 如果被选择,会将option选项的文字发送给服务器,不会向服务器返回任何值, getParameter()为null --> <td><select name='country'> <option>Canada</option> <option>United States</option> </select></td> </tr> <tr> <td>Delivery Method:</td> <!-- radio 如果没有选择,不会向服务器返回任何值, getParameter()为null--> <td><input type="radio" name="delivery" id="" value="First Class" />First Class <input type="radio" name="delivery" value="Second" />Second Class </td> </tr> <tr> <td>Shipping Instructions:</td> <!-- 多个区域不输入内容,默认发送个<br> --> <td><textarea name="instruction" id="" cols="40" rows="5"></textarea></td> </tr> <tr> <td> </td> <td><textarea name="instruction" id="" cols="40" rows="5"></textarea></td> </tr> <tr> <td>P lease send me the latest product catalog:</td> <!-- 单选框checkbox 将被选中按钮的值发送到服务器,如果没有选择任何按钮,将没有任何内容被发送到服务器 getParameter()为null--> <td><input type="checkbox" name="catalog" /></td> </tr> <tr> <td> </td> <td><input type="reset" /> <input type="submit" /></td> </tr> </table> </form> </body> </html>
post页面(html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Order Form</title> </head> <body> <h1>Order Form</h1> <table> <tr> <td>Name:</td><td>NAME</td> </tr> <tr> <td>Address:</td> <td>ADDRESS</td> </tr> <tr> <td>Country:</td> <td>COUNTRY</td> </tr> <tr> <td>Shipping Instructions:</td> <td>INSTRUCTIONS</td> <tr> <td>Delivery Method:</td> <td>DELMETHOD</td> </tr> <tr> <td>Catalog Request: </td> <td>CATALOG </td> </tr> </table> <div style="border:1px solid #ddd; margin-top:40px;font-size:90%"> Debug info<br />PARAMETERNAMES </div> </body> </html>