Java进阶学习第九天——Servlet入门

文档版本开发工具测试平台工程名字日期作者备注
V1.02016.04.21lutianfeinone

Servlet开发

Servlet简介

  • Servlet是sun公司提供的一门用于开发动态web资源的技术。
  • Sun公司在其API中提供了一个servlet接口,用户若想要开发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
    • 编写一个Java类,实现servlet接口。
    • 把开发好的Java类部署到web服务器中。


Servlet快速入门

用servlet向浏览器输出“hello servlet”。

  • 步骤如下:
    • 编写一个类,实现Servlet接口,重写5个方法。
      • 编写一个类HelloServlet,继承GenericServlet类,重写一个方法。
public class TestDemo1 implements Servlet {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        res.getWriter().write("hello Miaolu ...");

    }
}
  • 配置文件,配置Servlet信息。
        <!-- 先配置Servlet信息 -->
        <servlet>
            <!-- 配置Servlet名称,名称必须唯一 -->
            <servlet-name>ServletDemo1</servlet-name>
            <!-- 配置Servlet的完全路径(包名+类名) -->
            <servlet-class>cn.itcast.servlet.ServletDemo1</servlet-class>
        </servlet>

        <!-- 配置Servlet映射(访问路径) -->
        <servlet-mapping>
            <!-- 配置Servlet名称,和上面的名称必须相同 -->
            <servlet-name>ServletDemo1</servlet-name>
            <!-- 配置虚拟路径(访问路径) -->
            <url-pattern>/demo1</url-pattern>
        </servlet-mapping>
* 编译(一般用不到)
    * `javac -d . HelloServlet.java`
    * 问题:`HelloServlet.java: 4 : 软件包 javax.servlet 不存在`
    * 解决:`set classpath=%classpath%;servlet-api.jar    `设置临时的环境变量,只对当前的窗口有效。
  • servlet 执行过程


Servlet的生命周期

  • 生命周期:实例被创建,对外提供服务销毁
  • Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。

  • Servlet实例被创建后,调用init方法进行初始化

  • Servlet默认情况下什么时候被创建呢?
    • 第一次访问的时候,实例才被创建。
    • init方法调用几次呢?
      • 只被调用一次。
  • 注意事项:

    • 如果想重写init方法,重写无参数的init方法。
  • 对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

  • 从服务器中移除服务,调用destroy方法。

  • Servlet实例什么时候被销毁呢?

    • 服务器关闭,手动移除。
    • destroy仅调用一次。
  • 针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。

Servlet的关系
  • Servlet接口
    • GenericServlet(重写5个方法)
      • HttpServlet(继承GenericServlet实现了Servlet接口)
        • MyServlet
* 新建servlet模板工程*
  • 新建文件时,选择Servlet
  • 将红框中的勾去掉

  • 将红框中的名字简化成类名

  • 开发步骤(最终)

    • 编写一个类,继承HttpServlet
    • 重写doGet和doPost方法
      • 在doPost方法中调用doGet方法。
      • 表单是get方式,调用doGet
      • 表单是post方法,调用doPost方法
      • doGet和doPost互相调用。代码复用。
  • 修改Servlet模板

    • 先找到MyEclipse的安装路径。
      • \myeclipse10.7\Common\plugins\com.genuitec.eclipse.wizards.xxxx.jar
    • 找到jar包:com.genuitec.eclipse.wizards_9.0.0.me201211011550.jar
      • 千万别解压,右键–选择压缩工具打开
      • 将templates–Servlet.java文件拖到桌面
      • 将Servlet.java文件做如下修改后再拖回压缩包。
      • 拖回去之前,先把MyEclipse关闭。
      • 注:将注释及多余代码全部删掉,并在doPost方法中加入如下doGet方法调用。


Servlet自动加载
  • Servlet默认是第一次访问时候创建实例。通过配置,服务器启动,创建实例。
  • init做初始化的操作,非常消耗时间的。

  • <servlet>标签下:要放在servlet标签内的最后位置。

    • <load-on-startup>3</load-on-startup>
    • 值是正整数
    • 如果值越小,优先级越高。


WEB开发中路径的问题

配置虚拟路径(访问路径)
  • 由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。

  • <servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name><servlet-class>,分别用于设置Servlet的注册名称Servlet的完整类名

  • 一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name><url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。


路径匹配问题
  • 完全路径匹配
    • /开头的。eg:/demo5
    • 访问:http://localhost/day09/demo5
  • 目录匹配
    • /开头的:/*,任意后缀都可以访问。
    • 访问:http://localhost/day09/demo5可以访问
  • 扩展名匹配

    • 不能以/开头的, eg:*.do *.action
    • 访问:http://localhost/day09/demo5.do
  • 优先级完全路径匹配 > 目录匹配 > 扩展名匹配(重点)

  • 练习题:


相对路径
  • 一个文件相对于另一个文件的位置的关系
  • 不能以/开头 写法: ./demo当前目录==demo../demo:表示上级目录。
  • 访问1.html: http://localhost/day09/1.html
  • 访问demo5: http://localhost/day09/demo5
  • 从1.html中去访问demo5:./demo5 demo5

  • 访问2.html: http://localhost/day09/html/2.html

  • 访问demo5: http://localhost/day09/demo5
  • 从2.html访问demo5: ../demo5


绝对路径(推荐使用)
  • /开头的
  • 访问demo5: http://localhost/day09/demo5
  • 从1.html使用绝对路径访问demo5:http://localhost/day09/demo5
  • 简写方式:/day09/demo5

  • 客户端绝对路径

    • /day09/demo5 需要写项目名
  • 服务器绝对路径

    • /demo5 不能写项目名
  • 客户端关于路径问题的编程结论

  • *.html *.jsp : 内都使用绝对路径
  • *.css:内部使用相对路径—- 背景图片
  • *.js:中使用绝对路径


ServletConfig对象和配置文件相关

  • 当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servletinit方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息

  • 配置初始化参数

    • 需要在<servlet> </servlet>标签下配置。
    • 如果要是配置在某个servlet的标签下,那么只能在该servlet中获取初始化参数。
  • 在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数

  • String getServletName() 获取配置文件中servlet的名称

  • String getInitParameter(String name) 获取初始化参数

  • Enumeration getInitParameterNames() 获取初始化参数的所有名称

    <init-param>
        <param-name>username</param-name>
        <param-value>root</param-value>
    </init-param>
public class ServletDemo6 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 测试ServletConfig对象的api
        // 先获取ServletConfig对象
        ServletConfig config = getServletConfig();
        // 获取配置文件中serlvet的名称
        System.out.println("servlet的名称:"+config.getServletName());

        // 获取初始化的参数
        String username = config.getInitParameter("username");
        String password = config.getInitParameter("password");
        System.out.println(username+" : "+password);

        Enumeration<String> e = config.getInitParameterNames();
        while(e.hasMoreElements()){
            String name = e.nextElement();
            String value = config.getInitParameter(name);
            System.out.println(name+" : "+value);
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}


ServletContext对象(域对象) (重要)

  • WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。

    • 一个WEB应用对应一个ServletContext对象
    • 一个WEB应用下有多个Servlet程序
    • 所有的servlet程序都共享同一个ServletContext对象
  • ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。

  • 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象

  • 作用:

    • 获取WEB应用全局初始化参数
      • String getInitParameter(String name)
      • getInitParameterNames()
      • 在web.xml中配置全局初始化参数
            <context-param>
                <param-name>encoding</param-name>
                <param-value>GBK</param-value>
            </context-param>
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 先获取ServletContext对象
        ServletContext context = getServletContext();
        // 获取初始化参数
        String encoding = context.getInitParameter("encoding");
        System.out.println("编码:"+encoding);

        Enumeration<String> e = context.getInitParameterNames();
        while(e.hasMoreElements()){
            String name = e.nextElement();
            // 通过name获取值
            String value = context.getInitParameter(name);
            System.out.println(name+" : "+value);
        }
    }


  • 实现数据的共享(重要)

    • void setAttribute(String name, Object object) : 存入数据
    • void removeAttribute(String name) : 删除数据
    • Object getAttribute(String name) : 获取数据
  • 读取资源文件(重要)

    • InputStream getResourceAsStream(String path) 通过文件的地址获取输入流
    • String getRealPath(String path) 通过文件的地址获取文件的绝对磁盘路径
public class ReadServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        read5();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    /**
     * 通过ServletContext对象获取文件的绝对磁盘路径
     * 获取src目录下文件
     * @throws IOException 
     */
    public void read5() throws IOException{
        // 获取对象
        String path = getServletContext().getRealPath("/WEB-INF/classes/db.properties");
        // System.out.println(path);
        // C:\apache-tomcat-6.0.14\webapps\day09\WEB-INF\classes\db.properties

        // 获取输入流
        InputStream in = new FileInputStream(path);
        print(in);
    }

    /**
     * 获取WebRoot目录目录下db.properties文件
     * @throws IOException
     */
    public void read4() throws IOException{
        // ServletContext读取文件
        InputStream in = getServletContext().getResourceAsStream("/db.properties");
        // 打印方式
        print(in);
    }

    /**
     * 获取包目录下db.properties文件
     * @throws IOException
     */
    public void read3() throws IOException{
        // ServletContext读取文件
        InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/cn/itcast/context/db.properties");
        // 打印方式
        print(in);
    }

    /**
     * 获取src目录下db.properties文件
     * @throws IOException
     */
    public void read2() throws IOException{
        // ServletContext读取文件
        InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
        // 打印方式
        print(in);
    }

    /**
     * 传统方式读取资源文件
     *     交给服务器处理,相对的位置tomcat/bin
     * @throws IOException 
     */
    public void read1() throws IOException{
        // 获取输入流
        InputStream in = new FileInputStream("src/db.properties");
        print(in);
    }

    /**
     * 在控制台打印内容
     * @param in
     * @throws IOException
     */
    public void print(InputStream in) throws IOException{
        Properties pro = new Properties();
        // 加载
        pro.load(in);
        // 获取文件中的内容
        String username = pro.getProperty("username");
        String password = pro.getProperty("password");
        String desc = pro.getProperty("desc");

        System.out.println("用户名:"+username);
        System.out.println("密码:"+password);
        System.out.println("描述:"+desc);
    }

}

//db.properities

username=root33
password=12333
desc=haha33
  • 案例:统计显示网站访问次数

  • CountServlet.java
public class CountServlet extends HttpServlet {

    /**
     * 实例被创建,调用init方法进行初始化
     *     在域对象存入一个变量,赋值为0
     */
    public void init() throws ServletException {
        // 获取ServletContext对象
        getServletContext().setAttribute("count", 0);
    }

    /**
     * 每一次访问,都会执行该方法。
     * 拿出count的变量,值自增,存入到域对象中
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 先获取ServletContext对象
        ServletContext context = getServletContext();
        // 获取count的值,自增
        Integer count = (Integer) context.getAttribute("count");
        // 存入到域对象中
        context.setAttribute("count", ++count);

        // 向页面输出内容
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("<h3>大爷,欢迎再来哦!!</h3>");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
  • ShowServlet.java
/**
 * 显示网站的访问次数
 * @author Administrator
 *
 */
public class ShowServlet extends HttpServlet {

    /**
     * 获取网站的访问次数,输出到客户端
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Integer count = (Integer) getServletContext().getAttribute("count");
        // 向页面输出
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("<h3>该网站一共被访问了"+count+"次</h3>");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
  • HTTP的协议
  • 响应报头:location 与302 重定向应用
package cn.itcast.http;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 和location和302一起完成重定向
 * @author Administrator
 *
 */
public class ServletDmo1 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 向页面输出内容
        response.setContentType("text/html;charset=UTF-8");
        // response.getWriter().write("向班长借钱...");
        // 我没钱
        response.setStatus(302);
        // 告诉我富班长的地址
        response.setHeader("location", "/day09/1.html");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

  • 响应头: refresh 页面定时跳转
package cn.itcast.http;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 页面定时跳转
 * @author Administrator
 *
 */
public class RefreshServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("访问到了...");
        // 页面5秒会跳转
        response.setHeader("refresh", "5;url=/day09/1.html");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
  • 响应报头last-modefied-since 和304状态码 :控制缓存
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值