Java 杂谈程序员@IT·互联网

Servlet_如何使用Servlet?

2017-05-23  本文已影响0人  明天你好向前奔跑

Servlet

1.1、 Servlet概念

Servlet是服务器端的一个java小程序。它用于:处理,响应请求。

Servlet概念

1.2、 Servlet的创建方式

在创建Servlet时一定要在web.xml中添加<servlet></servlet>和<servlet-mapping><servlet-mapping>标签

为什么要在web.xml中设置url-pattern访问实现Servlet接口的类?

在项目src编写的实现类,tomcat将其编译成字节码文件放在WEB-INF中,外界不能直接访问,因此通过映射路径访问。

1.3、 Servlet的生命周期

创建ServletDemo类.PNG 实现Servlet接口.PNG web.xml配置.PNG 结果.PNG

1.4、 Web.xml配置的背后细节

输入地址:http://localhost:8080/项目名称/映射路径

背后细节:

      <!--
         这是创建的一个Servlet,Servlet的类的路径为当前项目下的Servlet包下的Servlet类,为这个Servlet起了个别名ServletDemo
        网页访问路径:http://localhost:8080/项目名称/类的映射路径
       -->
      <servlet>
        <servlet-name>ServletDemo</servlet-name>
        <servlet-class>ServletDemo.ServletDemo</servlet-class>
      </servlet>
      
      <!-- 
            两个Servlet-name必须一致,url-pattern中为servlet-class的映射路径,通过它可以访问到这个Servlet
       -->
      <servlet-mapping>
        <servlet-name>ServletDemo</servlet-name>
        <url-pattern>/demo</url-pattern>
      </servlet-mapping>


    第一步:服务器通过映射路径url-pattern的demo对应的servlet-mapping的servlet-name
    第二步:根据得到的servlet-name在web.xml中寻找和它名字相同的servlet标签下的servlet-name
    第三步:根据对应的servlet-class中真实路径寻找到Servlet实现类的全路径从而访问
Sevlet配置文件的访问细节

1.4.1、 Web.xml中映射路径的配置

1.5、 继承HttpServlet类创建一个Servlet

public class ServletDemo2 extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("*******doGet*******");
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("*******doPost*******");
    }
}

写完java的Servlet实现类后,完成web.xml配置。

  <servlet>
    <servlet-name>ServletDemo</servlet-name>
    <servlet-class>ServletDemo2.ServletDemo2</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>ServletDemo</servlet-name>
    <url-pattern>/demo</url-pattern>
  </servlet-mapping>

结果:每访问一次输出一次doGet。(doGet和doPost服务器根据提交方式选择执行)

1.5.1、 HttpServlet子类调用doGet或doPost方法的背后细节

1:浏览器输入:    http://localhost:8080/项目名/demo

2: 在web.xml里面找到了ServletDemo这个类

3: 获得请求,调用ServletDemo这个类中的service方法。

4: 子类使用继承的父类HttpServlet中的Service(ServletRequest req,ServletResponse res)方法,
    

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

    HttpServletRequest request;
    HttpServletResponse response;
    try {
        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;
    } catch (ClassCastException e) {
        throw new ServletException("non-HTTP request or response");
    }
    service(request, response);
}



5: 调用service(HttpServletRequest request, HttpServletResponse response)方法,根据提交方式调用对应的doXxx()方法

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();

        if (method.equals("GET")) {
            long lastModified = getLastModified(req);
            if (lastModified == -1L) {
                doGet(req, resp);
            }else if (method.equals("POST")){
                doPost(req, resp);
            } 
                ......


6: HttpServlet父类中有doGet()和doPost()方法,但是我们自己重写了doGet和doPost方法,
因此执行自己的doGet(),打印***doGet*****

2、 登陆案例

2.1 需求:写一个表单html登陆网页,提交账号和密码到服务器,服务器进行到数据库中进行校对,如果存在这样的用户数据,就登陆成功,反之就登录失败!

2.2 准备工作:

包的分类.PNG

2.3 实现步骤:

1:导入相应的jar包,并添加至构建路径

要导入的jar包.PNG

2: 编写bean:User类,C3P0Utils工具类,并创建对应的数据库user

数据库user

数据库账号密码信息表.PNG

配置c3p0-config.xml配置文件

c3p0-config.xml配置文件.PNG

编写C3P0Utils工具类

    public class C3P0Utils {
        // 提供获取连接池,获取连接和释放资源的方法
    
        // 根据c3p0-config.xml配置文件创建连接池
        private static DataSource ds = new ComboPooledDataSource();
    
        // 获取连接
        public static Connection getConnection() {
            Connection connection = null;
            try {
                connection = ds.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }
    
        // 释放资源
        public static void release(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection) {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        
        //获取连接池的方法
        public static DataSource getDataSource() {
            return ds;
        }
    }

编写bean:User类

编写用户登录页面及处理请求Servlet登陆类

用户表单页面Login.html

表单登录页面.PNG

处理请求Servlet登陆类

配置HttpServlet子类Login类的web.xml文件

  <servlet>
    <servlet-name>Login</servlet-name>
    <servlet-class>Login.Login</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>Login</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>

将这里url-pattern的映射路径写到Login.html的表单标签的action属性中,提交的数据就能来到Login类处理

到这里,登陆案例就完成了,查看运行结果。

浏览器中输入地址:       http://localhost:8080/day14_ServletLoginDemo/login.html 。

在登陆的表单页面中填入账号密码

username : admin ,  userpsd : admin

数据库中没有这个用户的账号密码,登陆失败

username : lzl  ,   userpsd : lzl

数据库中有该用户的对应的信息,登陆成功  
账密错误演示 账密错误结果 账密正确演示 账密错误演示结果

3、ServletContext

3.1、 ServletContext概念

它是Servlet的上下文 , 每次项目加载到服务器时该项目都会实例化一个ServletContext对象,一个项目有且只有一个ServletContext对象。

3.2、 生命周期

    何时创建:

        1.服务器加载时,被服务器托管的项目都会实例化一个ServletContext对象
        2.项目发布时,实例化一个SoervletConetxt对象

3.3、 ServletContext的作用:

存/取数据

        getAttribute(String name) : 获取属性
        setAttribute(String name , Object obj) : 设置属性

        //1:存数据到关联的web.xml中
        context.setAttribute("name", "aobama");
        
        //2:获取存入到关联的web.xml中的属性
        String str = (String) context.getAttribute("name");

获取项目资源

方式一:
    获取到ServletContext对象,调用getResourceAsStream(String path)方法得到资源的流对象。
    将获取到的流对象用Properties加载出来。
    要注意的是getResourceAsStrem方法中的路径默认是在Tomcat/Webapps/项目名工程下的路径查找,而我们
    的资源被Tomcat默认放在项目工程下的的WEB-INF/classes中保存的,因此填入的路径就填相对路径就可以了

    //需求:获取该项目src下的my.properties文件

    //获取能够加载流文件的对象Properties
    Properties properties = new Properties();
    
    //获取当前项目的ServletContext对象
    ServletContext context = this.getServletContext();
    //获取my.properties文件的流对象
    InputStream inputStream = context.getResourceAsStream("WEB-INF/classes/my.properties");
    
    //将当前流对象用properties加载读取
    properties.load(inputStream);
    
    //获取my.properties文件中的值
    String username = properties.getProperty("username");
    String password = properties.getProperty("password");
    //输出值
    System.out.println("username: "+username);
    System.out.println("password: "+password);



方式二:getRealPath(String path)

    自己创建输入流读取my.properties文件

    // 获取能够加载流对象的Properties对象
    Properties properties = new Properties();

    // 因为FileInputStream中要填入全路径 , 因此调用getRealPath()方法获取文件全路径
    String path = this.getServletContext().getRealPath("WEB-INF/classes/my.properties");

    // 获取文件流对象
    InputStream is = new FileInputStream(path);

    // 加载文件并获取文件中的内容
    properties.load(is);
    String username = properties.getProperty("username");
    String password = properties.getProperty("password");

    System.out.println("username: " + username);
    System.out.println("password:  " + password);

            

方式三:类加载器读取my.properties文件

    //使用类加载器获取my.properties文件资源,这里的字节码对象可以是任意的class对象
    InputStream is = this.getClass().getClassLoader().getResourceAsStream("my.properties");

    //获取Properties对象,将该文件流对象加载
    Properties properties = new Properties();
    properties.load(is);
    
    //获取该资源中的内容
    String username = properties.getProperty("username");
    String password = properties.getProperty("password");
    
    System.out.println("username: "+username);
    System.out.println("password: "+password);


浏览器输入:http://localhost:8080/项目名/映射路径
结果为:        username: jack
            password: 123
类加载器获取流对象的默认路径直接是在WEB-INF/classes下的,因此直接在后面拼接my.properties就可以正确加载。

获取全局参数

在web.xml中在<context-param></context-param>中设置全局参数,与局部参数一样,
有<param-name></param-name>和<param-value></param-value>两个值,设置它们的值,
在与其关联的Servlet中可以通过SevletContext对象的getInitParam(String)方法获得全局参数。

在web.xml中设置全局参数:
    可以把<param-name>和<param-value>看做键值对

  <context-param>
    <param-name>姓名</param-name>
    <param-value>凌霄</param-value>
  </context-param>



ServletContextDemo中获取全局参数代码:    

//获得当前项目的ServletContext对象
ServletContext context = this.getServletContext();

//获取全局参数
System.out.println(context.getInitParameter("姓名"));

浏览器输入 : http://localhost:8080/ServletContextDemo3/demo
结果 : 凌霄

3.4、ServletContext案例一

需求:

在上面的登陆案例基础上,额外添加校对正确后,跳转到登录成功页面,显示内容:登陆成功,等待5秒后跳转。

跳转到新的页面,显示:欢迎某某,您是第n位登陆的用户!

思路:

  1. 在校对账密的Servlet中,如果登陆成功就跳转到登陆成功页面

  2. 编写登陆成功页面,实现5秒后跳转新页面的功能。(实现倒计时)

  3. 编写跳转后的页面。

     由于有计数,因此肯定要在某个地方定义一个计数器,将其定义在web.xml中,
     通过ServletContext对象可以方便的存入与取出该数据进行操作。
    

实现:

核对密码的Servlet代码:
    // 首先配置对应的xml文件,让提交的请求发送到该Servlet处理

    // 获取数据名为username的值
    String username = req.getParameter("username");
    // 获取数据名为userpsd的值
    String userpsd = req.getParameter("userpsd");

    // 获取校对后的用户
    List<User> users = Service.check(username, userpsd, resp);

    if (users.size() > 0) {
        // 计数
        // 获取ServletContext对象,并取得属性为count的值
        ServletContext context = getServletContext();
        Object obj = context.getAttribute("count");// 获得了属性为count的值

        if (obj == null) { // 证明第一个登陆,设置计数器为1
            context.setAttribute("count", 1);
        } else { // 证明不是第一个登陆,取出count的值并+1存入
            context.setAttribute("count", (Integer) obj + 1);
        }

        resp.sendRedirect("Login_Succed.html");// html页面就在项目根目录下,跳转到该页面
    } else {
        resp.getWriter().write("Login Failed");
    }
}
登陆成功页面Login_Succed.html
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script type="text/javascript">
    var count = 5;
    //完成倒计时功能
    function change() {
        setInterval(function name() {
            count--;
            //设置<span>标签内的值
            document.getElementById("span1").innerText = count;

            //5秒后跳转页面
            if (count == -1) {
                location.href = "login2";
            }
        }, 1000);
    };
</script>

</head>
<body onload="change()">
    <h3>
        登陆成功,<span id="span1">5</span>秒钟后跳转!
    </h3>
</body>
</html>
映射路径为login2的LoginSucced的Servlet类
public class LoginSucced extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 防止中文乱码,让客户端和服务端使用的码表一致
        response.setContentType("text/html;charset=UTF-8");

        // 获取ServletContext对象
        ServletContext context = getServletContext();
        // 获得当前属性值count的值
        int count = (Integer) context.getAttribute("count");

        response.getWriter().write("<h3>欢迎光临,您是第" + count + "位登陆的用户!</h3>");
    }

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

****欢迎交流~~****

上一篇 下一篇

猜你喜欢

热点阅读