【笔记】JavaWeb-02-Servlet


servlet

1. servlet简介

  • 开发动态web

  • servlet接口:

    • 编写一个类,实现servlet接口

    • 把开发好的Java类部署到web服务器中

2. HelloServlet

Servlet有两个默认的实现类:HttpServlet,

 

  1. 构建一个普通的maven项目,删掉src目录

  2. 添加servlet依赖:(jsp也要用到,一同添加)(ps:类似于python导包

        
       <dependencies>
           
           <dependency>
               <groupId>javax.servletgroupId>
               <artifactId>javax.servlet-apiartifactId>
               <version>4.0.1version>
               <scope>providedscope>
           dependency>
           
           <dependency>
               <groupId>javax.servlet.jspgroupId>
               <artifactId>javax.servlet.jsp-apiartifactId>
               <version>2.3.3version>
               <scope>providedscope>
           dependency>
    ?
       dependencies>
  3. 关于maven父子项目:

    父项目的pom.xml中有modules:

        <modules>
           <module>servlet-01module>
       modules>

    子项目的pom.xml中有parent:

        <parent>
           <artifactId>javaweb-02-servletartifactId>
           <groupId>com.mystudygroupId>
           <version>1.0-SNAPSHOTversion>
       parent>

    父项目中的jar包子项目可以直接用

  4. maven环境优化

    • 更新web.xml 4.0版本

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                           http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
              version="4.0"
              metadata-complete="true">
      <display-name>Archetype Created Web Applicationdisplay-name>
      web-app>
    • 将maven的结构搭建完整(添加resources、java文件夹)

  5. 编写一个servlet程序

    1. 编写一个普通类

    2. 实现Servlet接口,这里直接继承HttpServlet类

      public class HelloServlet extends HttpServlet {
      ?
         // get和post是请求实现的不同方式,可以互相调用,业务逻辑都一样
      ?
         @Override
         protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //       ServletOutputStream outputStream = resp.getOutputStream();
             PrintWriter writer = resp.getWriter(); //响应流
             writer.print("Hello,Servlet!!");
      ?
        }
      ?
         @Override
         protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
             doGet(req, resp);
        }
      }
      ?
  6. 编写servlet的映射

    为什么需要映射:我们写的是Java程序,但是通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们写的servlet,还需要给它一个浏览器能访问的路径。

        
       <servlet>
           <servlet-name>helloservlet-name>
           <servlet-class>com.mystudy.servlet.HelloServletservlet-class>
       servlet>
       
       <servlet-mapping>
           <servlet-name>helloservlet-name>
           <url-pattern>/hellourl-pattern>
       servlet-mapping>

    注意:/hellohello前面的斜杠一定要加

  7. 配置Tomcat

    注意:配置项目发布的路径即可

  8. 启动测试

 

3. servlet原理

  1. 浏览器发送Http请求到服务器端;

  2. Web容器(例如Tomcat)接受到http请求,若是第一次访问Tomcat,则会生成一个servlet对应的target文件,并把我们写的实现类编译为.class文件;

  3. web容器产生两个对象,Request和Response;

  4. Request和Response对象作为参数调用Servlet中的Service方法;

  5. Request会从service (请求)拿到请求并且把请求之后的响应交给Response;

  6. 最后从Response对象返回到web容器中;

  7. Web容器把返回内容响应给客户端。

 

4. servlet-mapping

参考:Servlet原理和Mapping映射关系 - 知乎 (zhihu.com)

4.1 优先级问题

指定了固有的映射路径优先级最高,如果找不到就会走默认的映射。

例子:404页面

image-20220101150213955

web.xml

    
   <servlet>
       <servlet-name>errorservlet-name>
       <servlet-class>com.mystudy.servlet.ErrorServletservlet-class>
   servlet>
   
   <servlet-mapping>
       <servlet-name>errorservlet-name>
       <url-pattern>/*url-pattern>
   servlet-mapping>

ErrorServlet.java

public class ErrorServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.setContentType("text/html");
       resp.setCharacterEncoding("utf-8");
?
       PrintWriter writer = resp.getWriter();
       writer.print("

404

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

5. ServletContext

5.1 数据共享

类似于session功能,一个servlet中的值可以传递给另一个servlet

因此必须按顺序运行

例子

HelloServlet.java

public class HelloServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       ServletContext context = this.getServletContext();
?
       String username = "惺惺相惜";  // 数据
       context.setAttribute("username",username);  // 将数据保存在ServletContext中(键值对的形式)
?
       System.out.println("hello!");
  }
?
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
  }
}

GetServlet.java

public class GetServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.setContentType("text/html");
       resp.setCharacterEncoding("utf-8");
?
       ServletContext context = this.getServletContext();
?
       String username = (String)context.getAttribute("username");
       resp.getWriter().print("名字为:"+username);
  }
?
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
  }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                     http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0"
        metadata-complete="true">
   <servlet>
       <servlet-name>helloservlet-name>
       <servlet-class>com.mystudy.servlet.HelloServletservlet-class>
   servlet>
   <servlet-mapping>
       <servlet-name>helloservlet-name>
       <url-pattern>/hellourl-pattern>
   servlet-mapping>
?
   <servlet>
       <servlet-name>getcservlet-name>
       <servlet-class>com.mystudy.servlet.GetServletservlet-class>
   servlet>
   <servlet-mapping>
       <servlet-name>getcservlet-name>
       <url-pattern>/getcurl-pattern>
   servlet-mapping>
web-app>

注意

  • 必须先运行/hello再运行/getc。获取到username的值,才能进行传递,否则getc/得到的值为null;

  • 这里创建了一个新的模块,注意要重新配置tomcat的war文件。(具体原因?)

    image-20220101163928910

 

5.2 获取初始化参数

先在web.xml设置初始化参数(例如mysql的url)


   <context-param>
       <param-name>urlparam-name>
       <param-value>jdbc:mysql://localhost:3306/mybatisparam-value>
   context-param>

写servlet应用ServletDemo03.java

public class ServletDemo03 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       ServletContext context = this.getServletContext();
?
      String url = context.getInitParameter("url");
      resp.getWriter().print(url);
  }
?
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
  }
}

运行结果:

image-20220101165549315

5.3 请求转发

getRequestDispatcher("/路径")

public class ServletDemo04 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       ServletContext context = this.getServletContext();
?
//       分开的写法
//       RequestDispatcher requestDispatcher = context.getRequestDispatcher("/getp"); //定义转发的目的地
//       requestDispatcher.forward(req,resp); //转发。(req,resp参数为默认)
//       合并的写法
       context.getRequestDispatcher("/getp").forward(req,resp);
  }
?
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
  }
}

image-20220101181128672

5.4 读取资源文件

properties类

  • 在java目录下新建properties

  • 在resources目录先新建properties

发现:都被打包到了同一路径下(classes),我们称之为classpath。

思路:需要一个文件流 getResourceAsStream()

重点:properties所在的路径

image-20220101184124653

public class ServletDemo05 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/mystudy/servlet/aa.properties");
?
       Properties prop = new Properties();
       prop.load(is);
       String user = prop.getProperty("username");
       String pwd = prop.getProperty("password");
?
       resp.getWriter().print(user+": "+pwd);
  }
?
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
  }
}