用Servlet开发简单的登录页面--会逐步优化

第一个Servlet程序

package edu.xatu;

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 HelloWordServlet extends HttpServlet {

    protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter pw = response.getWriter ();
        pw.println ( "Hello World !" );
    }
}

运行结果:
在这里插入图片描述

servlet生命周期

package edu.xatu;

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 HelloWordServlet extends HttpServlet {

    @Override
    public void init () throws ServletException {
        System.out.println ("初始化时第一次被调用!");
    }

    @Override
    protected void service (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter ().println ( "service 方法" );
    }

    @Override
    public void destroy () {
        System.out.println ("在关闭服务器的情况下调用destroy方法");
    }

}

运行结果:
在这里插入图片描述

控制台在为关闭服务器和关闭服务器的情况下的运行结果(注意对比前后的时间所输出的内容):

在这里插入图片描述

开发登陆系统,含登录页面、成功页面、失败页面等

创建loginServlet:

package edu.xatu;

import edu.xatu.entity.User;

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 LoginServlet extends HttpServlet {
    protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String user = request.getParameter ( "username" );
        String pwd = request.getParameter ( "password" );
        User u = new User ();
        u.setUsername ( "张三" );
        u.setPassword ( "153@" );
        if (user.equals ( u.getUsername () ) && pwd.equals ( u.getPassword () )){
            request.getRequestDispatcher ( "/success.jsp" ).forward ( request,response );
        }else {
            request.getRequestDispatcher ( "/error.jsp" ).forward ( request,response );
        }
    }
}

请求的初始化登录表单:

在这里插入图片描述

有没有注意到上面图片中的请求路径,是…login.jsp页面,这说明,是直接请求登录页面。这样做是有个缺点,就是使得请求路径透明化,这样也是不安全的,对吧。

所以要修改,如何修改呢?

在LoginServlet类中加入,doGet方法:

  protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher ( "/login.jsp" ).forward ( request,response );
    }

这样请求路径就可以随便更改了。

页面效果:
在这里插入图片描述

没密码的情况下提交:

在这里插入图片描述

在输入信息错误的情况下:
在这里插入图片描述

在用户名和密码都正确的情况下:
在这里插入图片描述

error.jsp :

页面出错,点击
<a href="login.jsp">重新登录</a></br>

success.jsp :

  登录成功!

login.jsp :

   <script type="text/javascript">
        function validate() {
            if (login.username.value == ""){
                alert("账号不能为空!");
                return;
            }
            if (login.password.value == ""){
                alert("密码不能为空!");
                return;
            }
            login.submit();
        }
    </script>
    <form name="login" action="/login" method="post">
        用户名:<input type="text" name="username" value="${username}"><br>
        密码:  <input type="password" name="password" value="${pwd}"><br>
        <input type="submit" value="登录" onclick="validate()">
    </form>

开发会话跟踪的Servlet,能统计并显示同一个会话中用户访问该Servlet的次数

创建SessionServlet:

package edu.xatu;

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

public class SessionServlet extends HttpServlet {

    protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession (true);    //获取session 对象
        Object count = session.getAttribute ( "COUNTER" );  //取出session对象内存储的值
        int counter = 0;
        if (count == null){
            counter = 1;
            //将第一次计数存入session
            session.setAttribute ( "COUNTER",new Integer ( 1 ) );
        }else {
            counter = ((Integer)count).intValue();
            counter ++;     //计数器加一
            //将计数器存入session中
            session.setAttribute ( "COUNTER",new Integer ( counter ) );
        }
        request.getRequestDispatcher ( "/welcome.jsp" ).forward ( request,response );
    }
}

welcome.jsp:

  	欢迎来到本系统!<br>
  <%
    response.getWriter ().println ("该Servlet的访问次数:"+session.getAttribute ( "COUNTER" ));
  %>
  <sub></sub><%--sub设置下标--%>

运行结果:
在这里插入图片描述

它会随着刷新次数的增加而增加。

但是这样设计,显然不好。因为访问次数不可能放在页面左上方,因此,引入sub标签,试着将这个值放在下标位置,应该如何设计呢?

welcome.jsp中代码变动后:

  <body>
  <%
    Object o = session.getAttribute ( "COUNTER" );
  %>
  欢迎来到本系统!
  <sub>Servlet的访问次数:<%= o %></sub><%--sub设置下标--%>
  </body>

运行结果:

在这里插入图片描述

感觉是不是很好呢?

然后是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">
    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>edu.xatu.filter.EncodingFilter</filter-class>
    </filter>
    <servlet>
        <servlet-name>HelloWordServlet</servlet-name>
        <servlet-class>edu.xatu.HelloWordServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>edu.xatu.LoginServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>SessionServlet</servlet-name>
        <servlet-class>edu.xatu.SessionServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloWordServlet</servlet-name>
        <url-pattern>/abc</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet-mapping>
        <servlet-name>SessionServlet</servlet-name>
        <url-pattern>/session</url-pattern>
    </servlet-mapping>
</web-app>

User:

package edu.xatu.entity;

public class User {
    private String username;
    private String password;

    public String getUsername () {
        return username;
    }

    public void setUsername (String username) {
        this.username = username;
    }

    public String getPassword () {
        return password;
    }

    public void setPassword (String password) {
        this.password = password;
    }
}

处理乱码的Filter:

package edu.xatu.filter;

import javax.servlet.*;
import java.io.IOException;

public class EncodingFilter implements Filter {

    public void doFilter (ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        req.setCharacterEncoding ( "utf-8" );
        resp.setCharacterEncoding ( "utf-8" );
        chain.doFilter ( req, resp );
    }

}

运用jdbc与Servlet简单处理登录验证的问题

连接名为me的数据库,查询t_user表,验证输入的用户名和密码是否正确,要求使用PrepareStatement进行操作。

顺着这个呢,我们来做一下:

完成这些事,大概有以下几步:

1,创建数据库me,表t_user,加几个实例如下如所示:

在这里插入图片描述

这里的细节就略了,毕竟这不是我想表达的重点。

2,接下来是改动LoginServlet即可

package edu.xatu;

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.sql.*;
import java.util.*;

public class LoginServlet extends HttpServlet {
    protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String user = request.getParameter ( "username" );
        String pwd = request.getParameter ( "password" );
        String driverClass = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/me";
        String username1 = "root";
        String password = "";
        //数据库连接接口
        Connection conn = null;
        //执行sql语句的接口
        PreparedStatement prst = null;
        ResultSet rs = null;
        try {
            //加载驱动类到虚拟机
            Class.forName ( driverClass );
            //连接数据库
            conn = DriverManager.getConnection ( url,username1,password );
            String sql = "select * from t_user where username="+"'"+user+"'"+"and password="+"'"+pwd+"'";

            prst = conn.prepareStatement ( sql );
            rs = prst.executeQuery ();
            Map<String,String> map = new HashMap <> (  );
            while (rs.next ()){
                map.put ( rs.getString ( "username" ),rs.getString ( "password" ) );
                if (user.equals ( rs.getString ( "username" ) ) && pwd.equals ( rs.getString ( "password" ))){
                    request.getRequestDispatcher ( "/success.jsp" ).forward ( request,response );
                }
            }
            if (map.isEmpty ()) request.getRequestDispatcher ( "/error.jsp" ).forward ( request,response );
        } catch (Exception e) {
            e.printStackTrace ();
        }finally {
            try {
                if (prst != null)
                    prst.close ();
                if (conn != null)
                    conn.close ();
            } catch (SQLException e) {
                e.printStackTrace ();
            }
        }

    }

    protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher ( "/login.jsp" ).forward ( request,response );
    }
}

这里面有几点注意事项:
1,mysql-connector-java-5.1.32.jar包放在WEB-INF的lib下(不然会出错哦);

2,书写格式:引入变量之后的sql:

 String sql = "select * from t_user where username="+"'"+user+"'"+"and password="+"'"+pwd+"'";

3.怎样保证引入jdbc后,仍然在该Servlet中处理转发成功,失败或者其他页面呢?

​ 这是一个比较难的问题,首先考虑的是,如果输入的结果与数据库中的不匹配,那么rs.next() 返回值为 false

所以,按照这样的逻辑就是加一个条件判断就行,注意加的位置应该在while前面:

if (!rs.next ()){...}

即:
在这里插入图片描述

如果出现上述编辑,那么运行结果只会出现一个(debug可知),成功页面就无法出现,异常信息是:

after end of result set

查找原因是rs.next() 用完之后会释放关闭和数据库的连接,这就导致while的rs.next()始终为false,无法向下执行。

那怎么只保证rs.next()出现一次呢,首先应该想到用某容器保存rs.next(),无果,就只能保存登陆信息。

 while (rs.next ()){
                map.put ( rs.getString ( "username" ),rs.getString ( "password" ) );
                if (user.equals ( rs.getString ( "username" ) ) && pwd.equals ( rs.getString ( "password" ))){
                    request.getRequestDispatcher ( "/success.jsp" ).forward ( request,response );
                }
            }

因为每次用户登陆失败则map就会使空的,当然没有涉及多用户同时登陆

  if (map.isEmpty ()) request.getRequestDispatcher ( "/error.jsp" ).forward ( request,response );

综上所述,最基本的前后端就串在一起了,是不是有意思的事情开始了呢?

发布了101 篇原创文章 · 获赞 49 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Austin_/article/details/102871202
今日推荐