05-在Idea中编写Servlet程序

前情回顾

截至目前,我们已经总结了,如何配置Tomcat服务器(到官网下载资源,将bin目录配置到Path环境变量中,增加CATALINA_HOME环境变量),将Tomcat lib目录下的servlet-api.jar添加到CLASSPATH环境变量中,这样我们就可以使用JAVA EE的servlet接口。我们还学习了如何编写一个Servlet程序,它需要实现五个接口,知道了Tomcat是通过web.xml文件将路由和servlet程序关联。
本节内容,是借助Idea来实现上述过程,并且进一步学习GenericServlet接口以及ServletConfig,ServletContext对象。

利用Idea来创建项目并配置相关环境

新建一个空项目

这里选择Empty Project,键入javaTest作为项目名称
在这里插入图片描述

创建新模块

这里不选择Jakarta EE, 而选择New Module
在这里插入图片描述

为模块引入框架支持

在这里插入图片描述
勾选Web Application选项,因为我们想要开发的是Web应用
在这里插入图片描述
现在可以看到目录结构按照Serlvet规范的目录给我们自动生成了,项目根路径就是web,但要注意的是这里不意味着我们的项目名称就是web,这里是虚拟的,后面在真正运行时可以配置项目名称。
在这里插入图片描述

配置Tomcat环境

在这里插入图片描述
在这里插入图片描述这一步是配置Tomcat本地开发环境,这里因为是我之前配置过,所以直接呈现这个界面,否则的话需要点击Configure文件找到Tomcat的根路径
在这里插入图片描述
这里就是部署,我们新建一个模块部署
在这里插入图片描述
这里的Application text就是项目根目录名称,你可以自己配置
在这里插入图片描述

添加模块的包依赖

右击模块,点击Module Settings
在这里插入图片描述
添加jar包
在这里插入图片描述
这里加入的两个jar包,CTRL+ALT可以多选
在这里插入图片描述
成功以后你的External Libraries中除了jdk还可以看到你额外添加的包
在这里插入图片描述

编写Servlet程序

在src目录下创建需要的类
在这里插入图片描述
由于我们下面需要连接数据库,所以需要数据库相关的jdbc实现,那么就需要在lib目录下导入相关的包。
在这里插入图片描述
StudentList.java

package com.javaweb.servlet;
import jakarta.servlet.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
public class StudentList implements Servlet{

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException {
            servletResponse.setContentType("text/html");
            PrintWriter writer = servletResponse.getWriter();
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3306/test_db?useSSL=false";
                String user = "root";
                String passwd = "1234";
                conn = DriverManager.getConnection(url, user, passwd);
                String sql = "select * from student";
                ps = conn.prepareStatement(sql);
                rs = ps.executeQuery();
                while(rs.next()){
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    int age = rs.getInt("age");
                    String s = "<p>编号: " + id + " 姓名: " +name + " 年龄: " + age +"</p>";
                    writer.write(s);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                if(rs != null){
                    try {
                        rs.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                if(ps != null){
                    try {
                        ps.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                if(conn != null){
                    try {
                        conn.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <title>wefwe</title>
</head>
<body>
  <a href="/test/stu">student list</a>
</body>
</html>
<?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>ttt</servlet-name>
        <servlet-class>com.javaweb.servlet.StudentList</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ttt</servlet-name>
        <url-pattern>/stu</url-pattern>
    </servlet-mapping>
</web-app>

下面是效果
在这里插入图片描述
点击超链接以后进行跳转
在这里插入图片描述

探究Servlet的接口方法

GenericServlet

每次我们想编写一个实现Servlet接口的程序,都需要实现5个方法,而很多时候其实只会使用service一个方法,这使得代码变得冗长与丑陋。为了解决这个方法,我们可以利用适配器设计模式,编写一个GenericServlet,它实现了除service方法以外的四个方法,并将service作为抽象方法,以后我们不需要直接实现Servlet接口,而是直接继承GenericServlet。

package com.javaweb.servlet;
import jakarta.servlet.*;

import java.io.IOException;

public abstract class GenericServlet implements Servlet{

    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {}

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    

    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {}
}

对Servlet对象的探究

上面的GenericServlet有着其局限性,在改造它之前,我们先弄清楚几个问题。
Servlet对象的生命周期是怎样的?即谁来创建它,什么时候创建,又什么时候销毁?
作为客户端程序员而言,我们只是实现了service方法,从来没有自己去创建一个Servlet对象。事实上,Servlet对象是由Web服务器程序创建的,具体过程总结如下:

  1. 用户首次发送某个请求
  2. Tomcat创建对应的Servlet对象和ServletConfig对象(后续会探究ServletConfig对象)
  3. Servlet对象init方法被执行,ServletConfig对象作为参数传入
  4. service接口被调用
  5. 后续用户发送同一个请求,Servlet对象不再被创建,只是再次调用service方法
  6. 当服务器关闭时,destroy方法会被调用

我们可以发现有个ServletConfig对象被传入到了init方法中,所以说如果我们不去重写GenericServlet的init方法,ServletConfig就会丢失,所以对GenericServlet做如下改造

package com.javaweb.servlet;
import jakarta.servlet.*;

import java.io.IOException;

public abstract class GenericServlet implements Servlet{

    private ServletConfig config ;
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException;
    @Override
    public final void init(ServletConfig servletConfig) throws ServletException {
        config = servletConfig;
        this.init();
    }
    public void init(){}

    @Override
    public ServletConfig getServletConfig() {
        return config;
    }


    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {}
}

创建一个私用变量config, 在init方法中将ServletConfig对象保存在里面,并且利用getServletConfig接口将该对象返回。事实上这个getServletConfig接口存在的意义就在于此。
用户在继承GenericServlet时就不用重写init方法了,并且我们将其设置成final,用户也重写不了。那用户如果需要在init方法中执行一些初始化操作怎么办呢?可以看到提供了一个无参的init方法供用户重写,并且无参方法在有参方法中得到了执行。

GenericServlet在jakarta EE中也提供了实现,所以以后不用直接实现Servlet接口。

ServletConfig对象是什么东西?

每个Servlet对象可能需要一些初始化信息,而初始化信息可以通过ServletConfig对象提供。
它包含了如下四个方法

String	getInitParameter​(String name);	
Enumeration<String>	getInitParameterNames();	
String	getServletName();
ServletContext	getServletContext();	

解释这几个接口,那么就先得进一步介绍web.xml的其它配置,web.xml的作用不仅仅是将Servlet服务和路径绑定,还可以配置一些初始化信息。

 <servlet>
        <servlet-name>ttt</servlet-name>
        <servlet-class>com.javaweb.servlet.StudentList</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>tes</param-value>
        </init-param>
        <init-param>
            <param-name>message</param-name>
            <param-value>mes</param-value>
        </init-param>
    </servlet>

通过init-param规定了初始化用的参数,一个name对应一个value

public void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException {
        servletResponse.setContentType("text/html");
        PrintWriter writer = servletResponse.getWriter();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        ServletConfig config = getServletConfig();
        Enumeration<String> names = config.getInitParameterNames();
        while(names.hasMoreElements()){
            String name = names.nextElement();
            String val = config.getInitParameter(name);
            String init_param = "init_param: " + name + " init_value: " + val;
            writer.write(init_param);
            writer.write("<br>");
        }
     }

在这里插入图片描述
上面列举了getInitParameterNames和getInitParameter的大概用法。

ServletContext

ServletContext context = getServletContext();
context.getContextPath() //返回一个string,是项目的根路径名称
context.getRealPath(文件名) //获取项目文件的在服务器上的绝对路径

所有的servlet对象共享同一个ServletContext对象,它代表了全局配置信息,在web.xml中可以设置全局共享的初始化参数。

 <context-param>
        <param-name>size</param-name>
        <param-value>10</param-value>
    </context-param>
Enumeration<String> params = context.getInitParameterNames();
        while(params.hasMoreElements()){
            String param = params.nextElement();
            writer.write("<p>" + context.getInitParameter(param)+ "</p>");
        }

和ServletConfig对象一样有着上述的接口。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值