JavaWeb——Servlet

文章目录

    • Servlet简介
    • Servlet工作原理
    • 编写Servlet映射
        • 注册方式一
        • 注册方式二
    • Servlet核心对象
      • ServletContext
        • 应用场景——资源共享
        • 应用场景——获取初始化参数
        • 应用场景——请求转发
        • 应用场景——读取资源文件
      • HttpServletResponse
        • 应用场景—— 向浏览器输出消息
        • 应用场景——验证码功能
        • 应用场景——下载文件
        • 应用场景——实现重定向
      • HttpServletRequest
        • 应用场景——获取前端传递的参数、`请求转发`

Servlet简介

Servlet通常指的就是实现Servlet接口的java类,通过对http请求进行处理并响应结果,用以开发动态web。

  • Servlet是sun公司开发动态web的一门技术
  • 通常把实现了Servlet接口的Java程序叫做Servlet。
  • Servlet在sun公司有两个默认实现类HttpServletGenericServlet
  • HttpServlet类继承GenericServlet类,GenericServlet类继承Servlet接口,故我们的类只需要继承HttpServlet类即可。
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);
    }
}

Servlet工作原理

JavaWeb——Servlet_第1张图片
用户在上网时,由客户端浏览器发送http请求至服务器,服务器根据用户请求方式及地址从磁盘中加载对应的Servlet程序文件到Servlet容器。服务器解析http请求为request对象转发request对象到相应Servlet中进行处理,Servlet处理后返回response对象,服务器再将response对象转为http响应,响应给客户端浏览器。

编写Servlet映射

要通过浏览器访问java程序,而浏览器需要连接web服务器,所以需要在web服务中注册Servlet,还要给它一个浏览器能够访问的路径。

注册方式一

@WebServlet注解

// test只是个名字而已,value为访问地址
@WebServlet(name = "test", value = "/hello")
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);
    }
}
注册方式二

web.xml

<web-app>
  
  
  <servlet>
    
    <servlet-name>SpenceServletservlet-name>
    
    <servlet-class>com.spence.HelloServletservlet-class>
  servlet>
  
  
  <servlet-mapping>
    
    <servlet-name>SpenceServletservlet-name>
    
    <url-pattern>/spenceurl-pattern>
  servlet-mapping>

web-app>

注意:标签与标签一一对应,且标签要在标签上面

Servlet核心对象

ServletContext

ServletContext是上下文对象,用于管理整个web应用
web容器在启动时,会为每个web程序(每个Service)都创建一个对应的ServletContext对象,它代表当前web应用。但要注意,每个web程序(Servlet类)中创建的ServletContext对象其实是同一个对象,因此可通过ServletContext对象使得各个Servlet类中的数据互通共享(ServletContext对象凌驾于所有Servlet类之上,它是由web容器(服务器)创建的)。

应用场景——资源共享

向ServletContext对象中存入数据

public class SetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String userName = "哥哥";
        // 将一个数据以键值对形式保存在了 servletContext 中
        servletContext.setAttribute("userName", userName);
    }

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

从ServletContext对象中取出对象

public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String userName = (String) servletContext.getAttribute("userName");
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println(userName);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
应用场景——获取初始化参数

可在web.xml配置文件中写入一些初始化参数

<web-app>
  ...
  <context-param>
    <param-name>jdbc_urlparam-name>
    <param-value>jdbc:mysql://localhost:3306/mybatisparam-value>
  context-param>
    ...
web-app>web-app>

通过ServletContext对象中getInitParameter方法读取初始化参数

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    String url = servletContext.getInitParameter("jdbc_url"); // 读入初始化参数
    PrintWriter writer = resp.getWriter();
    writer.println(url);
}
应用场景——请求转发

通过ServletContext对象中getRequestDispatcher方法写入转发请求路径,再通过RequestDispatcher对象的forward方法实现转发。相当于指明一个新的请求路径,把请求和响应参数传入到新的请求中(该种情况不同于重定向,不会改变浏览器页中URL地址)。

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/jdbc"); // 转发的请求路径
    requestDispatcher.forward(req, resp); // 调用forward实现转发
}
应用场景——读取资源文件

想办法搞出一个文件流即可。

  • 在java目录下新建properties文件
  • 在resources目录下新建properties文件

发现:都被打包到了同一个路径下—> class,我们俗称这个路径为classpath。

在resources目录下新建 db.properties 文件

username=root
password=123456

通过ServletContext对象中 getResourceAsStream 方法读取文件

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    // 通过 getResourceAsStream 方法读取文件  /WEB-INF/classes/db.properties 为打包后文件所在相对路径
    InputStream iStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties"); // File流为绝对路径,在线上不方便使用
    Properties prop = new Properties();
    prop.load(iStream);
    // 获取配置文件中信息
    String username = prop.getProperty("username");
    String password = prop.getProperty("password");
    PrintWriter writer = resp.getWriter();
    writer.println(username +":"+ password);
}

HttpServletResponse

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

  • 如果要获取客户端请求过来的数据:去HttpServletRequest对象中找
  • 如果要给客户端响应过去一些数据:向HttpServletRequest对象添加

负责向浏览器发送数据的方法:

// 平常的流
ServletOutputStream getOutputStream() throws IOException;
// 字符
PrintWriter getWriter() throws IOException;

负责向浏览器发送一些响应头的方法

// 设置响应的编码
void setCharacterEncoding(String var1);
// 设置响应字符串长度
void setContentLength(int var1);
// 设置流长度
void setContentLengthLong(long var1);
// 设置类型
void setContentType(String var1);
...
应用场景—— 向浏览器输出消息

getOutputStream、getWriter等

应用场景——验证码功能
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 让浏览器3秒自动刷新一次
    resp.setHeader("refresh", "3");
    // 在内存中创建一个图片
    BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_BGR);
    // 得到图片
    Graphics2D g = (Graphics2D)image.getGraphics(); // 画笔
    // 设置画笔颜色
    g.setColor(Color.PINK);
    // 给图片填充数据
    g.fillRect(0, 0, 80, 20);
    // 给图片写入数据
    g.setColor(Color.BLUE);
    g.setFont(new Font(null, Font.BOLD, 20));
    g.drawString(makeNum(), 0, 20);
    // 告诉浏览器,这个请求用图片的方式打开
    resp.setContentType("image/jpeg");
    // 不让浏览器缓存
    resp.setDateHeader("expires", -1);
    resp.setHeader("Cache-Control", "no-cache");
    resp.setHeader("Pragma", "no-cache");
    // 把图片写给浏览器
    ImageIO.write(image, "jpg", resp.getOutputStream());
}

// 生成随机数
private String makeNum(){
    Random random = new Random();
    String num = random.nextInt(9999999) + "";
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < 7-num.length(); i++) {
        sb.append("0");
    }
    return sb.toString()+num;
}
应用场景——下载文件
1. 获取要下载文件的路径
2. 下载的文件名
3. 让浏览器能够支持所需下载的东西
4. 创建下载文件的输入流
5. 创建缓冲区
6. 获取OutputStream对象
7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 1. 获取要下载文件的路径
    // String realPath = this.getServletContext().getRealPath("/pic_01.png");
    String realPath = "D:\\IDEA_WorkSpace\\my-demo\\maven-03-web\\web-03-test\\src\\main\\resources\\static\\img\\pic_01.png";
    // 2. 下载的文件名
    String fileName = realPath.substring(realPath.lastIndexOf("//") + 1);
    // 3. 让浏览器能够支持所需下载的东西
    // resp.setHeader("content-disposition", "attachment;fileName"+fileName);
    // 中文文件名用 URLEncoder.encode 编码,否则有可能乱码
    resp.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "utf-8"));
    // 4. 创建下载文件的输入流
    FileInputStream fileInputStream = new FileInputStream(realPath);
    // 5. 创建缓冲区
    int len = 0;
    byte[] buffer = new byte[1024];
    // 6. 获取OutputStream对象
    ServletOutputStream outputStream = resp.getOutputStream();
    // 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
    while ((len = fileInputStream.read(buffer))>0){
        outputStream.write(buffer,0 , len);
    }
    fileInputStream.close();
    outputStream.close();
}
应用场景——实现重定向

一个web资源收到客户端请求后,他会通知客户端去访问另外一个web资源,这个过程叫重定向(该过程不同于转发,客户端浏览器中URL会发生改变)。
常见场景:用户登录
重定向方法:void sendRedirect(String var1) throws IOException;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 重定向
    resp.sendRedirect("/test3/image");
    /**
     * resp.sendRedirect("/test3/image");
     * 等价于
     * resp.setHeader("Location", "/test3/image");
     * resp.setStatus(302);
     */
}

HttpServletRequest

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

应用场景——获取前端传递的参数、请求转发
String getParameter(String var1);
String[] getParameterValues(String var1);
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String[] hobbies = req.getParameterValues("hobbies");
	// 这里的 / 代表当前的web应用
    req.getRequestDispatcher("/success.jsp").forward(req, resp);
}

你可能感兴趣的:(Web开发,servlet,tomcat,javaweb)