【狂神javaweb(三)】Servlet*重点(创建-配置-Context-request-response)

6.servlet

6.1.简介

  • Servlet是Sun公司开发动态web的一门技术
  • Sun公司在这些api中提供了一个接口叫: Servlet , 开发一个servlet程序, 只需两个步骤
    • 编写一个类, 实现servlet接口
    • 把开发好的java类部署到web服务器中

把实现了Servlet接口的java程序叫做: Servlet

6.2.HelloServlet

Servlet接口Sun公司有两个默认的实现类

  • HttpServlet
  • GenericServlet

1, 构建一个普通Maven项目

删除src文件

image-20220305224934179

添加一个module,main目录下添加java , resource

image-20220305231203046

修改子项目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">
</web-app>

2,maven父子工程的理解

在父项目中的pom.xml添加了

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

在子项目中pom添加了

<parent>
  <artifactId>web-02-servlet</artifactId>
  <groupId>com.ccc</groupId>
  <version>1.0-SNAPSHOT</version>
</parent>

父项目中的java子项目可以直接使用

遇到的问题:

创建maven项目-使用web模板不自动添加parent标签

我这里手动添加的, 或者创建的时候不选模板,手动添加web

3,编写一个Servlet程序

1编写一个普通类, 实现Servlet接口 , 继承HTTPServlet
2重写doPost, doGet方法
package com.ccc.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter(); //响应流
        writer.println("Hello, Servlet");
    }

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

3编写servlet的映射
  • 为什么需要映射: 我们写的是java程序, 要通过浏览器访问, 而浏览器需要连接web服务器, 所以我们需要在web服务中注册我们写的servlet, 还需一个浏览器能访问的地址
<!--注册servlet-->
<!---->
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.ccc.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet请求路径-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
4, 添加Tomcat

image-20220306000357247

5,启动成功 , 请求hello

image-20220306150914306

image-20220306150946638

6.3.Servlet原理

Servlet大致原理

6.4.Servlet-Mapping

  • 1一个Servlet可以指定一个映射路径

    • <!--servlet请求路径-->
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello</url-pattern>
      </servlet-mapping>
      
  • 2一个servlet可以指定多个映射路径

    • <!--servlet请求路径-->
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello</url-pattern>
      </servlet-mapping>
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello1</url-pattern>
      </servlet-mapping>
      
  • 3一个servlet可以指定通用映射路径

    • <!--servlet请求路径-->
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello/*</url-pattern>
      </servlet-mapping>
      
  • 4默认请求路径

    • <!--servlet请求路径-->
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <!--尽量避免这么写, 会直接访问到servlet, 不走index-->
          <url-pattern>/*</url-pattern>
      </servlet-mapping>
      
  • 5指定后缀或前缀等等

    • <!--自定义后缀注意: * 前面不能加路径-->
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <!--不管前面输入什么, 只要后面是.abcd就走hello-->
          <url-pattern>*.abcd</url-pattern>
      </servlet-mapping>
      

6.5.Servlet-Mapping优先级

指定了固有的映射路径优先级最高, 找不到走默认请求

image-20220306162503217

默认走error

image-20220306162702767

hello走hello

image-20220306162730059

其他走error

image-20220306162737996

6.6.ServletContext

web容器启动时, 会为每个web程序创建一个对应的ServletContext对象, 代表了当前的web应用

应用:

1,共享数据

在Servlet1中保存数据, 在servlet2中读取

Servlet1中保存
package com.ddd.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = "张三";
        //获取ServletContext
        ServletContext context = this.getServletContext();
        //放入数据
        context.setAttribute("name",name);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
Servlet2中读取
package com.ddd.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class GetContextServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*获取ServletContext*/
        ServletContext context = this.getServletContext();
        //取值
        String name = (String) context.getAttribute("name");
        //输出到页面
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().println("获取到了: "+name);
    }

    @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">
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.ddd.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>getc</servlet-name>
        <servlet-class>com.ddd.servlet.GetContextServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
    </servlet-mapping>
</web-app>
访问测试

注意: 想要获取到servlet1中保存的数据, 需先进去1 set进去, 2中才能读取到

直接进入2 无法读取

image-20220306171158751

先进入1中放入

image-20220306171217350

在读取

image-20220306171230538

2,获取初始化参数

<!--配置web初始化参数-->
<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/database</param-value>
</context-param>

通过servletcontext获取

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    /*获取ServletContext*/
    ServletContext context = this.getServletContext();
    /*获取参数 */
    String url = context.getInitParameter("url");
    resp.getWriter().println(url);
}

image-20220306172823164

3,请求转发

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*获取ServletContext*/
        ServletContext context = this.getServletContext();
        //请求转发到/gp
        context.getRequestDispatcher("/getp").forward(req,resp);
    }
    <servlet>
        <servlet-name>dm4</servlet-name>
        <servlet-class>com.ddd.servlet.ServletDemo04</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>dm4</servlet-name>
        <url-pattern>/dm4</url-pattern>
    </servlet-mapping>

image-20220306173806457

  • 转发请求路径不变

4,读取资源文件

Properties

  • 在java目录下新建properties
  • 在resource目录下新建properties /WEB-INF/classes/db.properties
username=zs
password=123321

发现: 都被打包到了同一个目录下:classes , 俗称classpath

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

    /*获取ServletContext*/
    ServletContext context = this.getServletContext();
    /*把资源转成流*/
    InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
    Properties properties = new Properties();
    properties.load(is);
    String uname = properties.getProperty("username");
    String pwd = properties.getProperty("password");
    resp.getWriter().println(uname+"::"+pwd);
}

测试读取

image-20220306180746816

6.7.HTTPServletResponse

web服务器接收到客户端http请求时, 针对这个请求, 分别创建了一个代表请求的HttpServletRequest对象, 一个代表响应的HttpServletResponse对象

1,简单分类

**负责向浏览器发送数据的方法: **
public ServletOutputStream getOutputStream() throws IOException;
public PrintWriter getWriter() throws IOException; //中文常用
负责向浏览器发送响应头的方法
public void setCharacterEncoding(String charset);

public void setContentLength(int len);

public void setContentLengthLong(long len);

public void setContentType(String type);
public void setHeader(String name, String value);

响应状态码
    /**
     * Status code (200) indicating the request succeeded normally.
     */
    public static final int SC_OK = 200;

    /**
     * Status code (300) indicating that the requested resource
     * corresponds to any one of a set of representations, each with
     * its own specific location.
     */
    public static final int SC_MULTIPLE_CHOICES = 300;

    /**
     * Status code (404) indicating that the requested resource is not
     * available.
     */
    public static final int SC_NOT_FOUND = 404;

    /**
     * Status code (500) indicating an error inside the HTTP server
     * which prevented it from fulfilling the request.
     */
    public static final int SC_INTERNAL_SERVER_ERROR = 500;

    /**
     * Status code (502) indicating that the HTTP server received an
     * invalid response from a server it consulted when acting as a
     * proxy or gateway.
     */
    public static final int SC_BAD_GATEWAY = 502;

2,常见应用

  • 输出信息
  • 下载文件
    1. 要获取下载文件的路径
    2. 下载的文件名
    3. 设置浏览器下载参数
    4. 获取下载文件的输入流
    5. 创建缓冲区
    6. 获取outputstream对象
    7. 将fileoutputstream写入到buffer缓冲区, 将缓冲区内容输出到客户端
package com.eee.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Enumeration;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 要获取下载文件的路径
        String realPath = "E:\\dx\\xx\\java\\code\\web-02-servlet\\response\\src\\main\\resources\\Servlet大致原理.png";
        //2. 下载的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        //3. 设置浏览器下载参数
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
        //4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
        //5. 创建缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
        //6. 获取outputstream对象
        ServletOutputStream out = resp.getOutputStream();
        //7. 将fileoutputstream写入到buffer缓冲区, 将缓冲区内容输出到客户端
        while ((len = in.read(buffer))>0){
            out.write(buffer,0,len);
        }
        out.close();
        in.close();
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

6.8.HttpServletRequest

HttpServletRequest代表客户端的请求, 用户通过http协议访问服务器, http请求中的所有信息会被封装到HttpServletRequest中, 通过这个对象的方法, 可以获得客户端的所有信息

1, 获取前段传递的参数,请求转发

image-20220307220533354

package com.rrr.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;

public class LoginServlet extends HttpServlet   {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //处理乱码
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        //获取表单数据
        String username = req.getParameter("username");
        String pwd = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println(username+"--"+pwd);
        System.out.println(Arrays.toString(hobbies));
        //请求转发                                 /代表当前web应用, 不需要加项目名称
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
    }

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

2,重定向和转发的区别

URL地址栏 状态码

  • 转发: 地址不会变 307 转发地址只需写项目下面的地址
  • 重定向: 地址栏会变化 302 重定向地址需写全地址

request传参

  • 转发: 页面能接收
  • 重定向: 页面接收不到
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值