Servlet基础
来源:互联网 发布:深入浅出数据分析阅读 编辑:程序博客网 时间:2024/04/30 10:27
servlet 是运行在 Web 服务器中的小型 Java 程序(即:服务器端的小应用程序)。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
1、servlet是一个接口,首先浏览器发送请求到服务器,服务器找应用的web.xml。然后寻找来找到实现了servlet这个接口的类,创建类,启动类里面的init()方法,然后调用Service方法完成请求,然后传回到服务器,服务器返回给浏览器
创建一个servlet的过程
一:创建一个类实现Servlet,实现相应的方法。如图所示,init()和构造方法只在第一次创建的时候执行,接下来就是调用Service方法,不会执行init(),只会刷新Service方法,当应用被卸载的时候调用destory()方法
public class ServletDemo1 implements Servlet { /** * 构造方法和init方法都只执行一次,在打开这个页面的时候 * service打开和刷新的时候都会执行 * destory方法在应用被卸载的时候调用 * */ public ServletDemo1() { System.out.println("构造方法执行了"); } @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("init"); } @Override public ServletConfig getServletConfig() { System.out.println("getServletConfig"); return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("service"); } @Override public String getServletInfo() { System.out.println("getServletInfo"); return null; } @Override public void destroy() { System.out.println("destroy"); }}
二:修改WEB-INF当中的web.xml文件,给servlet提供一个可访问的URI地址。
- 首先服务器通过uri找到应用然后找到与uri对应的< servlet-mapping>这个节点,找打servlet的名字
- 服务器是通过 < url-pattern>这个节点来匹配来寻找的,这里给的名字是/app
- 通过< servlet-name>找到实现servlet这个类的名字,然后找到对于的servelt节点,然后找到类的路径。
- 服务器自己创建对应的类,然后调用service()方法来完成交互
- service()方法中的参数servletRequest和servletResponse是服务器传递的,一个是请求的信息,一个是返回的消息
- 访问http://localhost:8080/firstJavaWeb/app就可以得看到控制台的输出
<servlet> <servlet-name>servletDemo1</servlet-name> <servlet-class>com.yanglin.servlet.ServletDemo1</servlet-class></servlet><servlet-mapping> <servlet-name>servletDemo1</servlet-name> <url-pattern>/app</url-pattern></servlet-mapping>
2、Servlet的声明周期:
实例化–>初始化–>服务->销毁
上类中的已经说明参看类
3、Servlet的三种创建方式
- 实现Servlet接口,如上所示
- 继承javax.servet.GenericServlet类(适配器模式)
继承javax.servlet.http.HttpServlet类(模板方法设计模式)设计当中经常使用。
接下里讲解HttpServlet创建Servlet类,如下所示,需要重写两个方法doPost()和doGet()
public class ServletDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }}
HttpServlet 这个类的使用了多态的机制,我们来看一下其所有的方法。
它继承了GenericServlet这个类,所有这里有service(ServletRequest,ServletResponse)这两个方法这个方式是实现Servlet这个接口的。所有当服务器访问这个类的时候是类型是这样的。
Servlet s = new HttpServlet()
这里是父类的引用指向了子类对象,这是这个父类是父类的父类。这里重写的了这个方法,所有动态绑定调用的是HttpServlet()这个类的Service方法。方法的实现源码
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException("non-HTTP request or response"); } service(request, response); }
从源码中可以看到,HttpServletRequest,HttpServletResponse 是继承了ServletRequest ,ServletResponse 这两个接口,应该是有拓展的。最有调用HttpServlet自己的service(HttpServletRequest,HttpServletResponse )来处理,方法源码:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < (lastModified / 1000 * 1000)) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
这里这个类处理了请求方式,主要是调用doPost()和doGet()方法。判断方法后分别调用不同的方法来处理。这里给我们封装了一些实用的细节,我们只需要实用这个模板然后重写里面的doPost()和doGet()等方法来实现我们知己的需求就行了。
小技巧:使生成的servlet更清新一些 找到:MyEclipse\Common\plugins目录
把com.genuitec.eclipse.wizards_9.0.0.me201108091322.jar复制到上面目录
3、servet映射细节:处理url的规则
- servet映射细节: 通配符* 代表任意字符串
- url-pattern: *.do 以*.字符串的请求都可以访问 注:不要加/
- url-pattern: /* 任意字符串都可以访问
url-pattern: /action/* 以/action开头的请求都可以访问
优先级:从高到低
绝对匹配(具体的url)–> /开头匹配(一/开始) –> 扩展名方式匹配(.do或者.action等)
4、线程安全
因为httpServlet的service()方法都是多线程的,所以会导致最好不要有全局变量,引用全局变量会导致变量共享。
5、Servlet获取配置信息
- ServletConfig的使用
1.获取servlet的配置信息,这个配置信息是写在web.xml当中的例如如下,有编码的配置信息,就可以通过ServletConfig获取,而且获取的方式多样,这里说两个看代码。 - 获取ServletContext()
<servlet> <servlet-name>ServletDemo2</servlet-name> <servlet-class>ServletDemo2</servlet-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param></servlet>
//way 1获取ServletConfig来得到局部编码String s = this.getServletConfig().getInitParameter("encoding");//way 2能得到全局的配置信息,和这个servlet下面的配置信息String encoding = this.getInitParameter("encoding");
一般而言使用的是第二个,因为httpServlet继承的GenericServlet实现了getInitParameter()这个方法。但是这个只能获取全局的配置信息,以及这个servlet下面的配置信息。不能获取其他servlet的配置信息。
5、ServletContext
ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。是单实例。
- 在一定范围内(当前应用),使多个Servlet共享数据。
在ServletDemo2的service()中写如下
//通过调用GenerServlet的getServletContext得到ServletContextServletContext context = this.getServletContext();context.setAttribute("name","zeroyoung");
在ServletDemo的service()下可以访问到如下
ServletContext context = this.getServletContext();String name = (String) context.getAttribute("name");//String encoding = this.getInitParameter("encoding");System.out.println(name);
- 获取全局配置信息
就是如上一节当中的,this.getInitParameter()这个方法,全局web.xml如下。
<context-param> <param-name>encoding</param-name> <param-value>GBK</param-value></context-param>
<context-param> <param-name>encoding</param-name> <param-value>GBK</param-value> </context-param>
- 获取资源路径:可以获取这个应用当中所有的资源文件
方法:getRealPath(String path)
需要注意的是在src下面的文件,在部署的时候都是放到web-inf这个目录下的classes目录下面的。所有当你在src下面创建一个a.properties文件的时候路径需要些成“/WEB-INF/classes/a.properties”
//获取资源路径,在src路径下面的东西,最后打包到服务器上的时候是在WEB-INF/classes目录下面的 //其中都得以/开始,因为这个代表对着项目目录下 String path = this.getServletContext().getRealPath("/WEB-INF/classes/a.properties"); Properties p = new Properties(); p.load(new FileInputStream(path)); System.out.println(p.get("key"));
这里也说明了properties文件读取方式
Properties p = new Properties();
p.load(new FileInputStream(path));
System.out.println(p.get(“key”));
最有给出这些servlet中类的关系图:
如果是通过参数调用的就叫依赖,而当时通过方法得到的就叫挂链。
这里里面servlet继承依赖多个接口,从而具备不同的功能,然后通过其他类的实现这个类,从而具备功能。
- Servlet基础----Hello Servlet!!!
- Servlet基础
- Servlet基础
- Servlet基础
- servlet基础
- Servlet 基础
- Servlet基础
- servlet基础
- Servlet 基础
- Servlet基础
- Servlet基础
- servlet基础
- Servlet基础
- Servlet ---- 基础
- servlet基础
- Servlet基础
- servlet基础
- Servlet基础
- 第七讲项目2-输入3个数,输出其中的最大值
- WIN7 下 explorer 进行的文件移动COPY HOOK
- heartbeat高可用集群+负载均衡+ldirectord后端安全检查
- Build a UI with Layout Editor(翻译文章)Android Studio 可视化界面编辑器
- ContentResolver query方法 参数详解
- Servlet基础
- oracle 11g 静默安装
- openwrt x86 版安装纪实
- ios 视频直播之蓝牙接入并转码成AAC
- 进程间通信 - 邮槽实现
- 【java设计模式】——浅谈设计模式 单例模式
- websphere常用的命令
- Unity3d 5.x角色动画的创建与加载.
- [HTML/CSS]布局学习笔记-企业网站导航首页