【JavaWeb】综合案例:用户登录

这个综合案例是Web应用种常见的业务:用户登录。


1.用户登录案例需求

  • 1.编写login.html登录页面,username & password 两个输入框
  • 2.使用Druid数据库连接池技术,操作mysql,查询dong数据库中user表
  • 3.使用JdbcTemplate技术封装JDBC
  • 4.登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您
  • 5.登录失败跳转到FailServlet展示:登录失败,用户名或密码错误

2.案例分析

在这里插入图片描述

案例结构图

在这里插入图片描述


3.开发步骤

3.1 创建数据库环境

根据需求,建立一个dong数据库,在数据下创建user表。

CREATE DATABASE dong;
USE dong;

CREATE TABLE USER(
	id INT PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(32) UNIQUE NOT NULL,
	PASSWORD VARCHAR(32) NOT NULL
);
INSERT INTO USER(username,PASSWORD) VALUES('zhangsan',123456);

user表;

在这里插入图片描述

3.2 创建项目,导入jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ozhaciia-1597940676080)(D:\文档存储\JAVA\技术路线\阶段2 JavaWeb+黑马旅游网\07 -Request和Respons\笔记图\用户登录案例\jar包.png)]

百度网盘:jar包资源,提取码:wdgi


3.3 编写html页面,配置文件

login.html页面

  • login.html中form表单的action路径的写法:虚拟目录+Servlet的资源路径。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/LoginServlet" method="post">
        用户账号:<input type="text" placeholder="请输入账号" name="username"><br>
        用户密码:<input type="text" placeholder="请输入密码" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

druid.properties配置文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/dong?useSSL=false
username=root
password=201703457
initialSize=5
maxActive=10
maxWait=3000

3.4 结构目录

在这里插入图片描述


3.5 创建包com.dong.domain,创建类User
/**
 * 用户实体类
 */
public class User implements java.io.Serializable {
    private int id;
    private String username;
    private String password;

    public User() {
    }

    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;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
3.6 创建包com.dong.util,编写工具类JDBCUtils
/**
 * JDBC工具类,使用Druid连接池
 */
public class JDBCUtils {

    private static javax.sql.DataSource ds;

    static {
        try {
            //1.加载配置文件
            java.util.Properties prop = new java.util.Properties();
            //使用ClassLoader加载配置文件,获取字节输入流
            java.io.InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            prop.load(is);

            //2.初始化数据库连接池对象
            ds = DruidDataSourceFactory.createDataSource(prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接池对象
     *
     * @return
     */
    public static javax.sql.DataSource getDataSource() {
        return ds;
    }

    /**
     * 获取数据库连接对象
     *
     * @return
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}
3.7 创建包com.dong.dao,创建类UserDao,提供login方法
/**
 * 操作数据库的类
 */
public class UserDao {

    //声明JDBCTemplate对象共用
    private JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 登录方法
     *
     * @param loginUser
     * @return user包含用户全部数据,没有查询到,放回null
     */
    public User login(User loginUser) {
        try {
            //1.编写sql语句
            String sql = "select * from user where username=? and password=?";
            //2.调用JDBCTemplate对象的查询方法
            User user = jdbcTemplate.queryForObject(sql //sql语句
                    , new BeanPropertyRowMapper<User>(User.class) //RowMapper接口实现类,将数据自动封装成指定对象
                    , loginUser.getUsername() //sql参数
                    , loginUser.getPassword()); // sql参数

            return user;
        } catch (Exception e) {
            e.printStackTrace();//以后会将异常记录到日志文件中
            return null;
        }
    }
}
3.8 创建包com.dong.test,创建类UserDaoTest,测试login方法
public class UserDaoTest {
    /**
     * 测试login方法能否查询成功
     */
    @Test
    public void loginTest(){
        User loginuser = new User();
        loginuser.setUsername("zhangsan");
        loginuser.setPassword("123456");

        UserDao dao = new UserDao();
        User user = dao.login(loginuser);
        System.out.println(user);
    }
}
3.9 编写com.dong.web.servlet.LoginServlet类
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.设置解码格式
        req.setCharacterEncoding("utf-8");
        //2.获取请求体参数username和password
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //3.将username和password封装成User对象
        User loginuser = new User();
        loginuser.setUsername(username);
        loginuser.setPassword(password);
        //4.调用UserDao的login方法
        UserDao dao = new UserDao();
        User user = dao.login(loginuser);
        //5.判断user是否为null
        if (user==null){
            //登录失败跳转到FailServlet
            req.getRequestDispatcher("/FailServlet").forward(req,resp);
        }else {
            //登录成功,将用户信息存在request域,跳转SuccessServlet
            req.setAttribute("user",user);
            req.getRequestDispatcher("/SuccessServlet").forward(req,resp);
        }
    }
}
3.10 编写FailServlet和SuccessServlet类
@WebServlet(name = "FailServlet", urlPatterns = "/FailServlet")
public class FailServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //在页面输出:登录失败,用户名或密码错误!
        //设置编码格式
        response.setContentType("text/html;charset=utf-8");
        //输出
        response.getWriter().write("登录失败,用户名或密码错误!");
    }
}
@WebServlet(name = "SuccessServlet", urlPatterns = "/SuccessServlet")
public class SuccessServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //在页面输出:登录成功,用户名xxx欢迎您!
        //设置编码格式
        response.setContentType("text/html;charset=utf-8");
        //获取请求域中存储的数据
        User user = (User) request.getAttribute("user");
        //输出
        response.getWriter().write("登录成功,用户名"+user.getUsername()+"欢迎您!");
    }
}

启动服务器

1.访问login.html
在这里插入图片描述

2.点击登录,提交表单数据

登录成功:
在这里插入图片描述

登录失败:
在这里插入图片描述


4.程序优化

当请求参数非常多的时候,比如用户的注册页面发向服务器的请求,包含很多用户的信息数据。

像这种情况下,会需要大量而枯燥的获取getParameter获取参数的代码,每次获取一个参数值,效率低,而且还需要将数据都封装到JavaBean(User)对象中,重复操作太多。

现在对LoginServlet类做如下优化,简化上述操作:

1.使用方法Map<String,String[]> getParameterMap(): (重点)获取所有请求参数的map集合。

2.使用BeanUtils工具类,简化数据封装。

简单了解一下这个工具类,BeanUtils位于org.apache.commons.beanutils.BeanUtils下面,是专门提供给我们用于封装JavaBean的。

需要了解它里面的三个方法:都是静态方法

  • setProperty(Object bean, String name, Object value):设置bean对象中name属性的值
  • getProperty(Object bean, String name):获取bean对象中name属性的值
  • populate(Object bean, Map map):(重点)将map集合的键值对信息,封装到对应的JavaBean对象中。
    这个方法会遍历map<key, value>中的key,如果bean中有这个属性,就把这个key对应的value值赋给bean的属性。

优化后的LoginServlet类:

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.设置解码格式
        req.setCharacterEncoding("utf-8");

        /*//2.获取请求体参数username和password
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //3.将username和password封装成User对象
        User loginuser = new User();
        loginuser.setUsername(username);
        loginuser.setPassword(password);*/

        //2.获取所有的请求体参数,当请求参数非常多的时候,非常方便
        Map<String, String[]> map = req.getParameterMap();
        //3.创建User对象
        User loginuser = new User();
        //3.1使用BeanUtils封装,提供的bean工具类自动封装map集合中数据为JavaBean对象
        try {
            BeanUtils.populate(loginuser,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        //4.调用UserDao的login方法
        UserDao dao = new UserDao();
        User user = dao.login(loginuser);
        //5.判断user是否为null
        if (user==null){
            //登录失败跳转到FailServlet
            req.getRequestDispatcher("/FailServlet").forward(req,resp);
        }else {
            //登录成功,将用户信息存在request域,跳转SuccessServlet
            req.setAttribute("user",user);
            req.getRequestDispatcher("/SuccessServlet").forward(req,resp);
        }
    }
}

5.JavaBean

如果对JavaBean不熟悉,这里简单回顾一下

5.1 JavaBean:标准的Java类,这样的类一般会有以下几个要求:

  • 1.类必须被public修饰
  • 2.必须提供空参和全参的构造器
  • 3.成员变量必须使用private修饰
  • 4.提供公共setter和getter方法

5.2 JavaBean的功能,就是封装数据。

5.3 了解JavaBean中属性和成员变量的概念

成员变量:就是我们声明在类中的变量,像private String name;等

属性:setter和getter方法截取后的产物,截取后的产物(属性)大多数情况下与成员变量在名称上一致。
截取过程,例如getHehe() --> Hehe–> hehe,setHehe() --> Hehe–> hehe;

在User实体类添加以下代码,并修改toString()方法,加上输出gender的值:

private String gender;

public void setHehe(String gender){
    this.gender = gender;
}

public String getHehe(){
    return gender;
}

编写一个测试方法,验证属性和成员方法的区别:

5.3.1 设置bean的成员变量

@Test
public void test(){
    User user = new User();
    try {
        BeanUtils.setProperty(user,"gender","male");
        System.out.println(user);

        String gender = BeanUtils.getProperty(user, "gender");
        System.out.println(gender);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mlz4MNPE-1597940676086)(D:\文档存储\JAVA\技术路线\阶段2 JavaWeb+黑马旅游网\07 -Request和Respons\笔记图\用户登录案例\bean的成员变量与属性1.png)]

原因是没有属性gender,没有setGender()和getGender()方法,也就是没有setter和getter方法截取后的产物为gender的属性。

需要加上setGender()和getGender()方法后,才能设置bean的成员变量gender。

private String gender;

public void setGender(String gender){
    this.gender = gender;
}

public String getGender(){
    return gender;
}

public void setHehe(String gender){
    this.gender = gender;
}

public String getHehe(){
    return gender;
}

再次运行测试方法,结果:
在这里插入图片描述


5.3.2 设置bean的属性

在User实体类添加以下代码,并修改toString()方法,加上输出gender的值:

private String gender;

public void setHehe(String gender){
    this.gender = gender;
}

public String getHehe(){
    return gender;
}

测试方法

@Test
public void test1(){
    User user = new User();
    try {
        BeanUtils.setProperty(user,"hehe","male");
        System.out.println(user);

        String gender = BeanUtils.getProperty(user, "hehe");
        System.out.println(gender);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

再次运行测试方法,结果:
在这里插入图片描述

可以看到bean中没有hehe成员变量,但是有hehe属性,属性值为male,并且成员变量gender的值也被设置为male了。

因为有setHehe()和getHehe()方法,setHehe()和getHehe()方法截取后的产物为hehe的属性。setProperty()、getProperty()方法底部会调用hehe对应的setter和getter方法,所有可以设置和获取属性值hehe。

可以证明JavaBean中属性和成员方法的区别,不清楚也没有关系,大多数情况下属性与成员变量是一致的。


介绍完毕,非常简单的一个案例,但知识点却不少,可以很好的融会贯通一些点。学无止境,每天都要全力以赴!

推荐阅读:
【JavaWeb】HTTP协议详细
【JavaWeb】Request对象详解


欢迎点赞评论,指出不足,笔者由衷感谢哦!~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值