tomcat和servlet的关系

一、什么是servlet?

处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,并且Servlet是为了解决实现动态页面而衍生的东西。理解这个的前提是了解一些http协议的东西,并且知道B/S模式(浏览器/服务器)。

二、tomcat和servlet的关系

Tomcat 是Web应用服务器,是一个Servlet/JSP容器. 
Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户. 
而Servlet是一种运行在支持Java语言的服务器上的组件. 
Servlet最常见的用途是扩展Java Web服务器功能,提供非常安全的,可移植的,易于使用的CGI替代品. 
从http协议中的请求和响应可以得知,浏览器发出的请求是一个请求文本,而浏览器接收到的也应该是一个响应文本。 
但是并不知道是如何转变的,只知道浏览器发送过来的请求也就是request,我们响应回去的就用response。 
①:Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象, 
所有的HTTP头数据读可以通过request对象调用对应的方法查询到。 
②:Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象, 
通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器 
Java Servlet API 是Servlet容器(tomcat)和servlet之间的接口,它定义了serlvet的各种方法, 
还定义了Servlet容器传送给Servlet的对象类,其中最重要的就是ServletRequest和ServletResponse。 
所以说我们在编写servlet时,需要实现Servlet接口,按照其规范进行操作。

三、编写Servlet代码

1、创建一个MyServlet继承HttpServlet,重写doGet和doPost方法,根据请求的方式是get还是post,然后用不同的处理方式来处理请求。 
2、在web.xml中配置MyServlet,为什么需要配置? 
让浏览器发出的请求知道到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用。

  <servlet>
    <servlet-name>servlet</servlet-name>
    <servlet-class>controller.MyServlet</servlet-class>
  </servlet>
   <servlet-mapping>
    <servlet-name>servlet</servlet-name>
    <url-pattern>/servlet</url-pattern>
  </servlet-mapping>

按照步骤,首先浏览器通过http://localhost:8080//servlet来找到web.xml中的url-pattern,这就是第一步,匹配到了url-pattern后,就会找到第二步servlet的名字servlet,知道了名字,就可以通过servlet-name找到第三步,到了第三步,也就能够知道servlet的位置class了。然后到其中找到对应的处理方式进行处理。

四 、 创建servlet的原理

1 、 servlet的生命周期是什么?

服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(ServletConfig conf)。 
该servlet对象去处理所有客户端请求,在service(ServletRequest req,ServletResponse res)方法中执行。 
最后服务器关闭时,才会销毁这个servlet对象,执行destroy()方法。

2、servlet的生命周期中,可以看出,执行的是service方法,为什么我们就只需要写doGet和doPost方法呢?为什么创建的servlet是继承自httpServlet,而不是直接实现Servlet接口?

(1).httpServlet的继承结构

httpServlet继承GenericServlet,GenericServlet实现了Servlet接口和ServletConfig接口。 
GenericServlet(通用Servlet)的作用是什么? 
GenericServlet实现Servlet接口的方法,简化编写servlet的步骤。

(2).ServletConfig和ServletContext

getServletConfig()方法来获取ServletConfig对象,ServletConfig对象可以获取到Servlet的一些信息,例如ServletName、ServletContext、InitParameter、InitParameterNames。 
通过查看ServletConfig这个接口就可以知道,ServletConfig接口中ServletContext对象是servlet上下文对象,功能有很多,获得了ServletContext对象,就能获取大部分我们需要的信息,比如获取servlet的路径和servlet方法。

(3).Servlet接口中的内容和作用

Servlet生命周期的三个关键方法,init、service、destroy。 
获取ServletConfig,而通过ServletConfig又可以获取到ServletContext。 
而GenericServlet实现了Servlet接口后,也就说明我们可以直接继承GenericServlet,就可以使用上面我们所介绍Servlet接口中的那几个方法了,能拿到ServletConfig,也可以通过ServletConfig拿到ServletContext,不过那样太麻烦,不能直接获取ServletContext,所以GenericServlet除了实现Servlet接口外,还实现了ServletConfig接口,那样,就可以直接获取ServletContext了。因为httpServlet继承了GenericServlet,所以我们可以直接使用httpServlet。

(4).GenericServlet类的内容详解

Servlet和ServletConfig接口所实现的方法,有9个,这很正常, 
但是我们可以发现,init方法有两个,一个是带有参数ServletConfig的,一个有无参的方法.

    public class ServletDemo extends GenericServlet {
    @Override
    public void init() throws ServletException {
        // TODO Auto-generated method stub
        super.init();
        }
    @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        super.init(config);
        }
    }

首先看init(ServletConfig config)方法,因为init(ServletConfig config)中带有ServletConfig对象,为了方便能够在其他地方也能直接使用ServletConfig对象,而不仅仅局限在init(ServletConfig config)方法中,所以创建一个私有的成员变量config,在init(ServletConfig config)方法中就将其赋值给config,然后通过getServletConfig()方法就能够获取ServletConfig对象了,可以通过全局变量保存ServletConfig对象。 
在GenericServlet类中增加一个init()方法,如果以后需要在init方法中需要初始化别的数据,只需要重写init()这个方法,而不需要去覆盖init(ServletConfig config)这个方法。

再来看service(ServletRequest req, ServletResponse res) 方法

    public class ServletDemo extends GenericServlet {
    @Override
    public void service(ServletRequest arg0, ServletResponse arg1)
    throws ServletException, IOException {
        // TODO Auto-generated method stub
    }
}

在GenericServlet类中并没有实现该内容,因为在它下面还有一层,还有一个子类继承GenericServlet,并实现该方法,service方法中的参数还是ServletRequest,ServletResponse,并没有跟http相关对象挂钩。

(5).HttpServlet类详解

这个类主要的功能是实现service方法的各种细节和设计。并且通过类名可以知道,该类就跟http挂钩了。

public class ServletDemo extends HttpServlet {
    @Override
    protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
    throws ServletException, IOException {
        // TODO Auto-generated method stub
        super.service(arg0, arg1);
    }
    @Override
    public void service(ServletRequest arg0, ServletResponse arg1)
    throws ServletException, IOException {
        // TODO Auto-generated method stub
        super.service(arg0, arg1);
    }
}

五.四个重点的对象。ServletConfig、ServletContext,request、response

1.ServletConfig对象

getServletConfig(); //获取ServletConfig对象
getServletName();  //获取servlet的名称,也就是我们在web.xml中配置的servlet-name
getServletContext(); //获取ServletContext对象
getInitParameter(String); //获取在servlet中初始化参数的值。这里注意与全局初始化参数的区分。这个获取的只是在该servlet下的初始化参数
getInitParameterNames(); //获取在Servlet中所有初始化参数的名字,也就是key值,可以通过key值,来找到各个初始化参数的value值。注意返回的是枚举类型

注意:在上面我们所分析的源码过程中,我们就知道,其实可以不用先获得ServletConfig,然后在获取其各种参数, 
可以直接使用其方法,比如上面我们用的ServletConfig().getServletName();可以直接写成getServletName(); 
而不用在先获取ServletConfig();了,原因就是在GenericServlet中,已经帮我们获取了这些数据,我们只需要直接拿就行。

2.ServletContext对象

getServletContext();
getServletConfig().getServletContext();
//这两种获取方式的区别就跟上面的解释一样,第一种是直接拿,
//在GenericServlet中已经帮我们用getServletConfig().getServletContext()拿到了ServletContext。
//我们只需要直接获取就行了,第二种就相当于我们自己在获取一遍,两种是一样的。

功能:tomcat为每个web项目都创建一个ServletContext实例,tomcat在启动时创建,服务器关闭时销毁,在一个web项目中共享数据,管理web项目资源,为整个web配置公共信息。通俗点讲,就是一个web项目,就存在一个ServletContext实例,每个Servlet都可以访问到它。 
1、web项目中共享数据,

setAttribute(String name, Object obj);// 在web项目范围内存放内容,以便让在web项目中所有的servlet读能访问到
getAttribute(String name);// 通过指定名称获得内容
removeAttribute(String name);// 通过指定名称移除内容   

2、整个web项目的初始化参数,这个就是全局初始化参数,每个Servlet中都能获取到该初始化值

getInitPatameter(String name);  //通过指定名称获取初始化值
getInitParameterNames();  //获得枚举类型

3、获取web项目资源

getServletContext().getRealPath("/WEB-INF/web.xml");//获取web项目下指定资源的路径
InputStream getResourceAsStream(java.lang.String path);//获取web项目下指定资源的内容,返回的是字节输入流
getResourcePaths(java.lang.String path);//指定路径下的所有内容。

3.request对象

request就是将请求文本封装而成的对象,所以通过request能获得请求文本中的所有内容,请求头、请求体、请求行 。

String getHeader(java.lang.String name);// 获得指定头内容String
long getDateHeader(java.lang.String name);// 获得指定头内容Date
int getIntHeader(java.lang.String name);//  获得指定头内容int
Enumeration getHeaders(java.lang.String name);// 获得指定名称所有内容

请求体的获取 – 请求参数的获取分两种,一种get请求,一种post请求 
get请求参数:http://localhost:8080/MyServlet?username=123&password=123 
post请求参数:<form method="post"><input type="text" name="username">

String request.getParameter(String);// 获得指定名称,一个请求参数值。
String[] request.getParameterValues(String);// 获得指定名称,所有请求参数值。例如:checkbox、select等
Map<String , String[]> request.getParameterMap();// 获得所有的请求参数  

请求转发

request.getRequestDispatcher(String path).forward(request,response);  
//path:转发后跳转的页面,这里不管用不用"/"开头,都是以web项目根开始,因为这是请求转发
//请求转发只局限与在同一个web项目下使用,所以这里一直都是从web项目根下开始的

特点:浏览器中url不会改变,也就是浏览器不知道服务器做了什么,是服务器帮我们跳转页面的,并且在转发后的页面,能够继续使用原先的request,因为是原先的request,所以request域中的属性都可以继续获取到。

4.response对象

response.setHeader(java.lang.String name, java.lang.String value) ;//设置指定的响应头,常用。
response.setHeader("Refresh",3);//设置每隔3秒就自动刷新一次,

重定向(页面跳转) 
方式一:手动方案

response.setStatus(302);  //状态码302就代表重定向
response.setHeader("location","http://www.baidu.com");

方式二:使用封装好的,通过response.sendRedirect("http://www.baidu.com"); 
特点:服务器告诉浏览器要跳转的页面,是浏览器主动去跳转的页面,浏览器的地址栏中url会变,是浏览器重新发起一个请求到另外一个页面,所以request是重新发起的,跟请求转发不一样,原先request域中的属性不能获取。 
重定向没有任何局限,可以重定向web项目内的任何路径,也可以访问别的web项目中的路径,并且这里就用”/”区分开来。 
如果使用了”/”开头,就说明我要重新开始定位了,不访问刚才的web项目,自己写项目名,可以访问服务器上的其他项目。 
如果没有使用”/”开始,那么就知道是访问原来那个web项目下的servlet,就可以省略项目名了。

六. 实例代码

  -->实现javax.servlet.Servlet接口  -->
  -->继承javax.servlet.GenericServlet类 (适配器模式) -->
  -->继承javax.servlet.http.HttpServlet类 (模板方法设计) -->
  -->继承HttpServlet
  最常用的就是继承HttpServlet,我们使用起来很方便
public class servletdemo extends HttpServlet{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write("");
        out.print("");
        //创建cookie,
        Cookie cookie = new Cookie("name", "Value");
        //设置cookie的有效时间,单位是秒
        cookie.setMaxAge(1);
        /*负数:cookie的数据存在浏览器缓存中
          * 0:删除。路径要保持一致,否则可能删错人。
          * 正数:缓存(持久化到磁盘上)的时间*/
        //设置cookie的path
        cookie.setPath(request.getContextPath());
        /*客户端在访问服务器另外资源时,根据访问的路径来决定是否带着Cookie到服务器
        *当前访问的路径如果是以cookie的path开头的路径,浏览器就带。否则不带。
        cookie.setMaxAge(0);相当于删除cookie*/
        //把cookie信息写回到客户端
        response.addCookie(cookie);

        //Cookie遍历
        Cookie[] cookies = request.getCookies();//获取客户端的所有Cookie对象
        for (int i = 0;cookies!=null && i < cookies.length; i++) {
            System.out.println(cookies[i].getName());
            System.out.println(cookies[i].getValue());
            System.out.println(cookies[i].getPath());
            System.out.println(cookies[i].getMaxAge());
        }
        //session
        request.getSession().setAttribute("","");
        //得到session对象
         HttpSession session = request.getSession();
        //session操作
        session.getAttribute("");
        session.setAttribute("", "");
        session.getId();
        //请求转发
        request.getRequestDispatcher("").forward(request, response);
        /*转发是服务器行为,重定向是客户端行为
        1.转发在服务器端完成的;重定向是在客户端完成的
        2.转发的速度快;重定向速度慢
        3.转发的是同一次请求;重定向是两次不同请求
        4.转发不会执行转发后的代码;重定向会执行重定向之后的代码
        5.转发地址栏没有变化;重定向地址栏有变化
        6.转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成 */
        //请求重定向
        response.setStatus(302);
        response.sendRedirect("");
        //告知客户端不缓存
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        response.setDateHeader("expires", 0);

        System.out.println(request.getMethod());//获得请求方式
        System.out.println(request.getRequestURL());//返回客户端发出请求时的完整URL
        System.out.println(request.getContextPath());//当前应用的虚拟目录
        System.out.println(request.getRequestURI());//返回请求行中的资源名部分
        System.out.println(request.getQueryString());//返回请求行中的参数部分
        System.out.println(request.getHeaderNames());//得到所有头信息name
        //Properties
        //获取资源路径
        //此处填写的路径一定要注意是WEB服务器部署后的路径
        String path=this.getServletContext().getRealPath("/test.properties");
        //创建Properties
        Properties pro =new Properties();
        pro.load(new FileInputStream(path));//读入文件test.properties

        //通过调用GenericServlet的getServletContext方法得到ServletContext对象
        ServletContext setServletContext=this.getServletContext();
        //向ServletContext添加一个键值对
        setServletContext.setAttribute("name", "value");

/*获取非表单数据,先set后get,可以remove
void setAttribute(String name, Object value);
Object getAttribute(String name);
Void removeAttribute(String name);
 */
//服务器和客户端浏览器编码要统一,否则会乱码
//      resp.setCharacterEncoding("UTF-8");//设置服务器编码
//      resp.setHeader("content-type", "text/html;charset=UTF-8");//通过响应消息头设置客户端浏览器编码
//      resp.setContentType("text/html;charset=UTF-8");//此行代码封装了上面两行代码
//      PrintWriter out=resp.getWriter();//得到一个字符输出流
//      out.write("Response文本信息");//向客户端响应文本内容

//获取编码  //第一种方式
//      String encoding=config.getInitParameter("encoding");
//      System.out.println("第一种方式"+encoding);
//      //第二种方式
//      System.out.println("第二种方式"+this.getServletConfig().getInitParameter("encoding"));
        //第三种方式
//      System.out.println("第三种方式"+super.getInitParameter("encoding"));

    }

}
public class DownloadFileDemo extends HttpServlet{
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        //通过路径得到输出流
        String path =this.getServletContext().getRealPath("/WEB-INF/classes/cn/servlet/Servlet.jpg");
        FileInputStream file=new FileInputStream(path);
        //创建输出流
        ServletOutputStream sos=resp.getOutputStream();
        //得到文件名
        String filename=path.substring(path.lastIndexOf("\\")+1);//分割字符串,取最后一个‘"\\‘"符号后面的1个字符
        //设置文件名的编码
        filename=URLEncoder.encode(filename,"UTF-8");//将编码改为UTF-8
        //告知客户端下载文件
        resp.setHeader("content-disposition", "attachment;filename="+filename);
        resp.setHeader("content-type","image/jpg");
        //输出
        int len=1;
        byte[] b=new byte[1024];
        while((len=file.read(b))!=-1) {
            sos.write(b,0,len);
        }
        sos.close();
        file.close();
    }
}
public class ServletDemo  implements Servlet{
        //Servlet生命周期的方法
        //在servlet第一次被访问时调用
        //实例化
        public ServletDemo(){
            System.out.println("ServLetDemo执行了,在servlet实例化时调用");
        }
        //Servlet生命周期的方法
        //在servlet第一次被访问时调用
        //初始化
        public void init(ServletConfig arg0) throws ServletException {
            System.out.println("init执行了,在servlet第一次被访问时调用");

        }
        //Servlet生命周期的方法
        //每次访问时都会被调用
        //服务
        public void service(ServletRequest arg0, ServletResponse arg1)
                throws ServletException, IOException {
            //System.out.println("hello servlet");
            System.out.println("service执行了,每次访问时都会被调用");
        }
        //Servlet生命周期的方法
        //销毁
        public void destroy() {
            System.out.println("destroy执行了,销毁");
        }
        public ServletConfig getServletConfig() {
            System.out.println("getServletConfig");

            return null;
        }
        public String getServletInfo() {
            System.out.println("getServletInfo");

            return null;
        }
}

原文地址:https://www.cnblogs.com/jiangzhaowei/p/9373625.html

时间: 2024-10-05 05:21:36

tomcat和servlet的关系的相关文章

【tomcat】servlet原理及其生命周期

1.什么是servlet? Servlet(Servlet Applet),全称Java Servlet,是用Java编写的服务器端程序.而这些Servlet都要实现Servlet这个接口.其主要功能在于交互式的浏览和修改数据,生成动态Web内容.Servlet运行于支持Java的应用服务器中. 2.tomcat和servlet的关系? Servlet 与 Servlet 容器(tomcat)的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力.虽然它们是彼此依存的,但是又相互独立

JSP学习 —— 开篇:JSP,servlet容器,Tomcat,servlet容器之间的关系

JSP(JAVA SERVER PAGE)的缩写,其本身就是servlet的简化,是一种动态网页标准,其特点是在HTML代码中嵌入JAVA代码,JSP标签或用户标签来生成网页.至于它为什么会出现,主要原因在于早期的servlet技术在编写代码时经常通篇性的写一大堆HTML标签,静态文本及文本格式等表现逻辑,其开发效率非常之低下:为了解决这种情况,便随之出现了JSP,其静态部分(包括表现逻辑,如图片,文字等等)全用HTML语言来编写,只有需要动态生成的逻辑才由嵌入的JAVA代码来实现. 说到最后,

浅谈Tomcat和Servlet

本文浅谈下对Tomcat和Servlet总体的理解,初学时有用过一段时间,但当时疲于应对如何xml配置和使用,对他们的理解就像是一个黑匣子.现在回顾一下帮助自己加深网络的理解.开始还是先推荐我看的文章和书. https://www.cnblogs.com/zhouyuqin/p/5143121.html 以下都是IBM Developer上的文章,该网站上还是有很多优质文章. https://www.ibm.com/developerworks/cn/java/j-lo-servlet/  Se

Tomcat和Servlet简析

目录 Servlet Tomcat 参考 Servlet Servlet通常指我们继承了Servlet接口的类,我们开发Servlet时一般就是继承HttpServlet重写它的doGet.doPost方法达到提供服务的目的.Servlet不仅仅是这些,我们用的JSP在编译器也会被编译成Servlet类,JSP是一种页面渲染更为方便的Servlet. Servlet是一个提供服务的类,那它是如何发挥作用呢?要了解Servlet,我们有必要了解一下它的容器比如Tomcat.想象一下在一栋大楼里有非

Tomcat部署servlet小应用无法找到相应的servlet类的问题可能原因

今天特别有成就感, 感谢上帝,是他让我不轻易放弃.好了下面简单介绍一下我的问题.我最近在学习 Headfirst servlet JSP 第81页面关于部署一个小应用.但是无论怎么调试无法找到servlet,最开始是web.xml里面的servlet和servlet-mapping位置放错了,在这里也提醒一下各位,请一定要仔细检查这个部署文件,确定没有错. <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi=&qu

30天轻松学习javaweb_修改tomcat的servlet模板

在MyEclipse目录下搜索com.genuitec.eclipse.wizards得到搜索结果 com.genuitec.eclipse.wizards_9.0.0.me201108091322.jar解压出文件夹,修改com.genuitec.eclipse.wizards_9.0.0.me201108091322\templates\Servlet.java 的模板文件使用jar命令将文件夹打包成jar包:1.在dos窗口中进入到解压后的com.genuitec.eclipse.wiza

IT忍者神龟之tomcat、servlet、JSP、JSTL版本支持对应表

Tomcat版本 Servlet版本 Jsp版本 Jstl版本 6.0.x 2.5 2.1 1.2.1.1.x 5.5.x 2.4 2.0 1.1.x 5.0.x 2.4 2.0 1.1 4.1.x 2.3 1.2 1.0 3.3.x 2.2 1.1 jstl对应的jar包说明: (1)JSTL1.0(包含2个jar文件:jstl.jar和standard.jar.这两个jar文件都存在于Standard1.0.x的发布版本中.) 下载地址:http://archive.apache.org/d

[03] Servlet继承关系和生命周期

1.Servlet的继承关系 假如现有我们自定义的一个Servlet,继承HttpServlet,那么实际上它的继承链如下图: 可以看到,核心的部分在于: 两个顶级接口 Servlet ServletConfig 接口的实现类 GenericServlet 基于HTTP协议的实现类 HttpServlet 我们剥离一下,把不需要看的去掉,再把方法显示一下,可清晰知道Servlet的整体继承关系如下: 其中重点摘录部分进行说明: ServletConfig  Servlet的配置信息,常用来在Se

Android——Tomcat+MySQL+Servlet,实现将Client传入的数据写入MySQL

Android客户端将用户的注册信息上传到Tomcat Web服务器,Servlet将注册信息写入到MySQL中. 1,准备工作 (1)在MySQL中创建好要使用的数据库和数据表. (2)设置好Tomcat的数据库连接池. 参见Tomcat数据库连接池配置 2,Android客户端Activity和Layout的设计 (1)一个简单的注册界面,sign_layout.xml sign_layout.xml <LinearLayout xmlns:android="http://schema