Servlet
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet相关的知识,希望对你有一定的参考价值。
1.Servlet的概述
1.1 认识Servlet
在Servlet出现之前服务器处理请求的流程是如下图所示的,这样的访问存在着很多的不足之处:
Servlet是基于对CGI的改善;
Servlet是sun公司提供的一种用于开发动态web资源的技术,为了方便web服务器对动态web资源(所谓动态web资源就是可以运行在服务器上的java程序)的管理,sun公司在其api中定义了一个Servlet接口,服务器针对接口进行调用,我们编写的应用程序针对接口进行实现,习惯性地,我们把实现了Servlet接口的java类统称为Servlet
开发人员写好一个java类,到底有哪些方法tomcat服务器是不可能知道的,tomcat服务器需要执行我们编写的java类就需要知道我们的java类有哪些方法,然后在适当的时间调用这些方法, 所以我们在写的java程序要想运行在服务器上就必须要实现一个特殊的接口 Servlet.java
interface Servlet { ... }
Servlet 接口中就定义了可以被tomcat服务器调用的java方法,通常来讲,我们将实现了Servlet接口的java类称之为 Servlet,编写好的Servlet需要web.xml文件中做配置才能供外界访问
1.2 Servlet的工作流程
1.3 Servlet接口
2. 走进Servlet
2.1 实现Servlet
下面我们通过一些Servlet实例来查看一下实现接口和继承HttpServlet:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>ServletPractice</display-name> <!--在web容器中配置servlet容器 --> <servlet> <!--servlet实例名称,可以随便起 --> <servlet-name>ServletInterface</servlet-name> <!--指定Servlet类名,由包名和类名构成 --> <servlet-class>servlet.Interface.ServletInterface</servlet-class> <!-- 配置Servlet初始化参数 --> <init-param> <!--参数名 --> <param-name>pName1</param-name> <!--参数值 --> <param-value>我是初始化参数pName1</param-value> </init-param> <init-param> <param-name>pName2</param-name> <param-value>我是初始化参数pName2</param-value> </init-param> </servlet> <servlet> <servlet-name>ServletExtends</servlet-name> <servlet-class>servlet.extend.ServletExtends</servlet-class> </servlet> <servlet> <servlet-name>ServletExtendsDemo</servlet-name> <servlet-class>servlet.extend.ServletExtendsDemo</servlet-class> </servlet> <servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>servlet.login.LoginServlet</servlet-class> </servlet> <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>servlet.extend.FirstServlet</servlet-class> </servlet> <!--配置servlet的访问方式 --> <servlet-mapping> <!--对应要访问的servlet实例名称 --> <servlet-name>ServletInterface</servlet-name> <!-- 以斜杠开头,把一个路径与一个Servlet绑定在一起 ,访问时,前边的服务器域名+端口号+应用程序路径就是访问路径--> <!-- 随便起,必须以斜杠开头! --> <url-pattern>/ServletInterface</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ServletExtends</servlet-name> <url-pattern>/ServletExtends</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ServletExtendsDemo</servlet-name> <url-pattern>/ServletExtendsDemo</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/LoginServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/FirstServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
package servlet.Interface; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class ServletInterface implements Servlet{ @Override public void destroy() { //Servlet销毁前会被调用 System.out.println("Servlet销毁前调用!"); } @Override public ServletConfig getServletConfig() { // 返回一个 ServletConfig对象,它包含了servlet的初始化和起始参数 System.out.println("不是Servlet生命周期的方法,作用是创建一个Servlet容器!"); return null; } @Override public String getServletInfo() { // 返回有关servlet的信息,例如作者、版本、版权。 System.out.println("不是生命周期方法,不常用的方法!"); return null; } @Override public void init(ServletConfig arg0) throws ServletException { // 创建Servlet实例之后,马上调用,被servlet 容器调用以指明一个servlet被放进服务中。 String name = arg0.getServletName(); System.out.println("返回该servlet实例的名称。"+name); String str = arg0.getInitParameter("pName"); System.out.println("返回一个包含给定名字的初始化参数,若此参数不存在就返回一个空值。"+str); String str1 = arg0.getInitParameter("pName2"); System.out.println("返回一个包含给定名字的初始化参数,若此参数不存在就返回一个空值。"+str1); System.out.println("init方法是在服务器装入Servlet容器时执行的,负责初始化Servlet容器对象。可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init()。"); } @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { // 被servlet container调用以允许servlet响应一个请求。 System.out.println("每次处理请求时,tomcat都会调用这个方法。(请求处理方法)"); } }
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP ‘index.jsp‘ starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h1>POST请求</h1> <form action="/ServletPractice/ServletExtends" method="post"> <input type="submit" value="发送POST请求"/> </form> </body> </html>
package servlet.extend; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; public class ServletExtends extends HttpServlet{ //重写service方法 @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { System.out.println("重写service方法,此方法在每次处理请求时调用"); } }
从上面我们看到实现接口的话需要对接口中的所有方法进行实现,而实际开发中,我们需要的仅是有限的几个方法,所以实现接口会造成代码冗余,不可取;而继承类,则只需对所需方法进行重写即可,简单,实用;
package servlet.extend; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletExtendsDemo extends HttpServlet{ //重写doGet方法,被server调用 (通过service方法) 以允许一个 servlet处理一个 GET请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("重写doGet方法"); } }
一个登陆小案例:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘form1.jsp‘ starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h1>登录案例</h1> <!-- action必须是项目名+Servlet路径 --> <form action="/ServletPractice/LoginServlet" method="post"> 用户名:<input type="text" name="username"/> <input type="submit" value="登录"/> </form> </body> </html>
package servlet.login; 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 LoginServlet extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // tomcat默认使用iso,而iso不支持中文 /* * 我们需要做两件事: * 1. 让tomcat使用utf-8编码发送数据! * 2. 告诉浏览器我们使用的是utf-8 * 以上两件事一个方法调用即可,设置Content-Type这个响应头即可 */ resp.setHeader("Content-Type", "text/html;charset=UTF-8"); /* * 1. 使用request获取请求参数,参数名username * 2. 判断是否为itcast * 3. 是itcast:使用response设置状态码为404,指定错误信息; * 4. 不是itcast:使用response设置响应体为:<h1>登录成功</h1> */ // 使用request获取请求参数 String username = req.getParameter("username"); if(username.equals("itcast")){ // resp.setStatus(404); resp.sendError(404, "用户名不正确"); }else { //设置响应体 PrintWriter pw = resp.getWriter();//获取用户响应字符数据的输出流! pw.print("<h1>登录成功</h1>"); pw.close(); } } }
2.2 配置<servlet>
2.2.1 <servlet>的配置
2.2.2 <servlet-mapping>的配置
下面可一个实例:
package servlet.extend; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class FirstServlet extends HttpServlet { /*以get方式访问页面时执行该函数 * 执行doGet()函数之前会先执行getLastModified()方法,如果浏览器发现返回的数值,与上次返回的数值相同,则认为该文档没有更新,浏览器采用缓存而不执行doGet() * 如果getLastModified()返回-1,则认为是时刻更新的,总是执行该函数*/ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /*void log(java.lang.String msg) 将指定的消息写到一个servlet日志文件,由servlet的名字预先挂起。 */ this.log("执行doGet()...."); this.execute(req, resp); } //以post方式访问页面时,执行该方法,执行前不会执行getLastModified() @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.log("执行doPost()...."); this.execute(req, resp); } /*返回该servlet生成的文档的更新时间,对get访问方式有效,返回的时间相对于1970年1月1日08:00:00的毫秒数,如果是-1则默认为是实时更新,默认返回的是-1*/ @Override protected long getLastModified(HttpServletRequest req) { this.log("getLastModified()...."); return -1; } //执行方法 private void execute(HttpServletRequest request,HttpServletResponse response) throws IOException{ //设置请求和响应的编码方式 request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); //获取访问该servlet的URL String url = request.getRequestURI(); //获取访问该servlet的访问方式 String method = request.getMethod(); //客户端提交的指定参数的值,返回一个请求参数的字符串值。若该参数不存在,则返回一个空值。 String value = request.getParameter("param"); //设置响应的文档类型 response.setContentType("text/html"); //设置响应体 PrintWriter pw = response.getWriter();//获取用户响应字符数据的输出流! pw.println("<!DOCTYPE html>"); pw.println("<html>"); pw.println("<head><title>Servlet入门</title></head>"); pw.println("<body>"); pw.println("<form action = ‘"+url+"‘ method = ‘get‘>" +"<input type = ‘text‘ name=‘param‘ value=‘param string‘>" +"<input type=‘submit‘ value=‘以Get方式查询页面‘"+url+">" +"</form>"); pw.println("<form action = ‘"+url+"‘ method = ‘post‘>" +"<input type = ‘text‘ name=‘param‘ value=‘param string‘>" +"<input type=‘submit‘ value=‘以Post方式查询页面‘"+url+">" +"</form>"); //由客户端浏览器读取该文档的更新时间 pw.println("<script>document.write(‘本页面最后的访问时间:‘+document.lastModified);</script>"); pw.println("</body>"); pw.println("</html>"); pw.close(); } }
3. Request&&Response
以上是关于Servlet的主要内容,如果未能解决你的问题,请参考以下文章