动态 WEB 开发核心-Servlet(学习笔记-自用)

该笔记用于回顾复习,如有错误请批评指正,参考资料:韩顺平java web笔记、黑马程序员

一、Servlet

(1)servlet介绍

    Servlet (java服务器小程序)在开发动态 WEB 工程中,得到广泛的应用,掌握好 Servlet 非常重要了, Servlet(基石)是 SpringMVC 的基础

(2)servlet的执行过程

(3)servlet两种继承方式

1.方式一:继承GenericServlet

需要重写service方法,每创建一个servlet类都需要进行配置,在web.xml里进行配置

servlet1类:

public class servlet1 extends GenericServlet {

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
       
    }
}

 web.xml:

   <servlet>
        <servlet-name>servlet1</servlet-name>
        <servlet-class>serveletdemo.servlet1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet1</servlet-name>
        <url-pattern>/s1</url-pattern>
    </servlet-mapping>

配置好tomcat即可启动,启动后在原先的地址加上 <url-pattern>自定义的路径

2.方式二:继承HttpServlet

需要重写doGet方法和doPost方法

servlet类:

public class servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       
    }
}

web.xml:

    <servlet>
        <servlet-name>servlet2</servlet-name>
        <servlet-class>serveletdemo.servlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet2</servlet-name>
        <url-pattern>/s2</url-pattern>
    </servlet-mapping>

实际开发中,直接继承HttpServlet即可

(4)servlet生命周期(从出生到死亡)

主要有三个方法

  •  init()  初始化阶段
  •  service()  处理浏览器请求阶段
  •  destroy()  终止阶段
public class servlet3 extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("我出生了");
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("接收到了客户端请求");
    }
    @Override
    public void destroy() {
        System.out.println("我死了(销毁)");
    }
}

(5)解决线程安全问题

 Servlet采用单实例多线程方式运行,因此是线程不安全的。何为线程安全问题?当多个线程同时修改同一个共享数据时,后修改的数据会将先修改的数据覆盖,对数据先进行修改的用户读取到的不是自己修改后的数据,这就是线程安全问题。

解决方式1:

//servlet线程安全问题
public class servlet4 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.定义成员变量
        String username = null; //方法1:解决线程安全问题

       
            //获取用户名
            username = req.getParameter("username");
            //响应给浏览器
            PrintWriter writer = resp.getWriter();
            writer.print("welcome"+username);
            writer.close();
        }

    }

解决方式2:

//servlet线程安全问题
public class servlet4 extends HttpServlet {
    private String username;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
        //方法2:解决线程安全问题
        synchronized (this){
            //获取用户名
            username = req.getParameter("username");
            //响应给浏览器
            PrintWriter writer = resp.getWriter();
            writer.print("welcome"+username);
            writer.close();
        }

    }
}

(6)servlet不同的映射方式


  //  1.指定名称的方式
    <servlet>
        <servlet-name>servlet5</servlet-name>
        <servlet-class>serveletdemo.servlet5</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet5</servlet-name>
        <url-pattern>/s5</url-pattern>
    </servlet-mapping>


 // 2. / 开头+通配符方法  
    <servlet>
        <servlet-name>servlet5</servlet-name>
        <servlet-class>serveletdemo.servlet5</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet5</servlet-name>
        <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>


// 3.通配符+固定格式结尾方式   
    <servlet>
        <servlet-name>servlet5</servlet-name>
        <servlet-class>serveletdemo.servlet5</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet5</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

三种映射方式在地址栏的输入:

采用方式1:http://localhost:8080/servlet/s5

采用方式2:http://localhost:8080/servlet/servlet/*

采用方式3:http://localhost:8080/servlet/*.do

(*号为通配符代表输入任何都可以访问)

(7)servlet多映射的使用

通过一个案例说明:

servle类:

public class servlet6 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     //定义商品金额
      int money=1000;

      //拿到访问资源路径
        String path = req.getRequestURI();
        path=path.substring(path.lastIndexOf("/"));

        //条件的判断
      if ("/vip".equals(path)){
          System.out.println("商品原价为"+money+"。优惠后是:"+(money*0.9));
      }else if ("/vvip".equals(path)){
          System.out.println("商品原价为"+money+"。优惠后是:"+(money*0.5));
      }else {
          System.out.println("商品原价为"+money);
      }

    }
}

web.xml:

  <servlet>
            <servlet-name>servlet6</servlet-name>
            <servlet-class>serveletdemo.servlet6</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>servlet6</servlet-name>
            <url-pattern>/servlet/*</url-pattern>
        </servlet-mapping>

在web.xml下的,我采用了第二种映射方式,当我启动servlet后地址栏输入路径 /vip则打9折,若/vvip则打5折

(8)servlet创建时机

核心代码 <load-on-startup>1</load-on-startup> ,在web.xml的servlet中加入。

Servlet创建时机

二、ServletConfig

(1)介绍

  1. ServletConfig 类是为 Servlet 程序的配置信息的类
  2. Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建
  3. Servlet 程序默认是第 1 次访问的时候创建,ServletConfig 在 Servlet 程序创建时,就创建一个对应的 ServletConfig 对 象

ServletConfig 类能干什么:

1. 获取 Servlet 程序的 servlet-name 的值

2. 获取初始化参数 init-param

3. 获取 ServletContext 对象

(2)配置方式

< init-param>在web.xml中配置时,相当于键值对,<init-param> 是用于在 Java Servlet 中配置初始化参数的标签。这些参数在 Servlet 初始化时被加载,并且可以在 Servlet 的生命周期内被用来配置或影响 Servlet 的行为。

<param-name>相当于key,<param-value>相当于value。

<!--  servletConfig配置方式  -->
    <servlet>
        <servlet-name>sc1</servlet-name>
        <servlet-class>servletconfigDemo.sc1</servlet-class>

    <!-- 配置servletConfig初始化参数-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>desc</param-name>
            <param-value>this is servletCofig</param-value>
        </init-param>

    </servlet>
    <servlet-mapping>
        <servlet-name>sc1</servlet-name>
        <url-pattern>/sc1</url-pattern>
    </servlet-mapping>

(3)常用方法

 

通过代码演示:

servlet类:

public class sc1 extends HttpServlet {
    //获取 servletConfig 对象
    //1-声明servletConfig对象
    private ServletConfig config;

    //2.通过init方法,来对servletConfig进行赋值
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config=config;
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
    doPost(request,respons);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
        //3.演示servletConfig的方法

        //--根据key获取对应value值
        String encoding = config.getInitParameter("encoding");
        System.out.println(encoding);


/**
1、keys.hasMoreElements() 是 Java 中 Enumeration 接口的一个方法。
Enumeration 是一个旧的迭代接口,用于遍历集合中的元素。
hasMoreElements() 方法用于检查是否还有更多的元素可以遍历。

2、keys.nextElement(); 是 Java 中 Enumeration 接口的一个方法,
用于获取并返回集合中的下一个元素。
*/
        //--获取所有key and value
        Enumeration<String> keys = config.getInitParameterNames();
        while (keys.hasMoreElements()){
            //获取每一个key
            String s = keys.nextElement();
            //根据key获取value
            String value = config.getInitParameter(s);
            System.out.println(s+","+value);
        }

        //--获取servletConfig的名称
        String servletName = config.getServletName();
        System.out.println(servletName);
    }
}

web.xml:

<!--  servletConfig配置方式  -->
    <servlet>
        <servlet-name>sc1</servlet-name>
        <servlet-class>servletconfigDemo.sc1</servlet-class>

    <!-- 配置servletConfig初始化参数-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>desc</param-name>
            <param-value>this is servletCofig</param-value>
        </init-param>

    </servlet>
    <servlet-mapping>
        <servlet-name>sc1</servlet-name>
        <url-pattern>/sc1</url-pattern>
    </servlet-mapping>

三、ServletContext

(1)介绍

1. ServletContext 是一个接口,它表示 Servlet 上下文对象

2. 一个 web 工程,只有一个 ServletContext 对象实例

3. ServletContext 对象 是在 web 工程启动的时候创建,在 web 工程停止的时销毁

4. ServletContext 对象可以通过 ServletConfig.getServletContext 方法获得对 ServletContext

对象的引用,也可以通过 this.getServletContext()来获得其对象的引用。

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

可以用来做什么:

1. 获取 web.xml 中配置的上下文参数 context-param [信息和整个 web 应用相关,而不是 属于某个 Servlet]

2. 获取当前的工程路径,格式: /工程路径 =》 比如 /servlet

3. 获 取 工 程 部 署 后 在 服 务 器 硬 盘 上 的 绝 对 路 径 ( 比 如 : D:\hspedu_javaweb\servlet\out\artifacts\servlet_war_exploded)

4. 像 Map 一样存取数据, 多个 Servlet 共享数据。

(2)配置方式

(3)常用方法

代码演示:

public class servletcontextDemo extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
    //1.获取servletcontex对象
        ServletContext context = getServletContext();

    //2.获取全局配置参数:getInitParameter(String key)根据key 获取value
        String value = context.getInitParameter("globalDesc");
        System.out.println(value);

        //获取应用的虚拟目录
        String path = context.getContextPath();
        System.out.println(path);

        //根据虚拟目录获取绝对路径
        String realPath = context.getRealPath("/");
        System.out.println(realPath);

/**
 * 获取文件路径
 *这是我自己创建了几个txt文件
 */
        String b = context.getRealPath("/b.txt");
        String c = context.getRealPath("/WEB-INF/c.txt");
        String a = context.getRealPath("/WEB-INF/classed/a.txt");
        System.out.println(b);
        System.out.println(c);
        System.out.println(a);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
    doGet(request,respons);
    }
}

(4)servletConfig和ServletContext结合

servletContext:

public class servletcontextDemo extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
      System.out.println(realPath);

        /**
         *设置共享数据
         */
        context.setAttribute("username","milo");

        //删除共享数据
        context.removeAttribute("username");

    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
    doGet(request,respons);
    }
}

servletConfig:

public class sc1 extends HttpServlet {
    //获取 servletConfig 对象
    //1-声明servletConfig对象
    private ServletConfig config;

    //2.通过init方法,来对servletConfig进行赋值
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config=config;
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
    doPost(request,respons);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
   

        //--获取servletContext对象
        ServletContext servletContext = config.getServletContext();
        System.out.println(servletContext);

        //获取刚才(servletContext)设置好的共享数据
        Object username = servletContext.getAttribute("username");
        System.out.println(username);
    }
}

四、注解开发

之前我们都是在web.xml进行配置,这个注解开发可以带给我们省去在web.xml进行配置,方便了很多

主要步骤就是在类的开头添加@WebServlet("/自定义的映射路径")

@WebServlet("/demo3")
public class demo3 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
    
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse respons) throws ServletException, IOException {
    doGet(request,respons);
    }
}

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值