JDBC整理

数据库配置文件

创建 db.properties 资源文件,存放配置信息

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaweb?useSSL=true&useUnicode=true&characterEncoding=utf-8
username=root
password=123456

操作数据库公共类

建立 dao 包,然后创建 BaseDao

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class BaseDao {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    //静态代码块,类加载的时候初始化
    static {
        Properties properties = new Properties();
        //通过类加载器读取对应的资源
        InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        driver = properties.getProperty("driver");
        url = properties.getProperty("url");
        username = properties.getProperty("username");
        password = properties.getProperty("password");
    }
    //获取数据库的连接
    public static Connection getConnection(){
        Connection connection = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url,username,password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    //编写预编译查询公共方法
    public static ResultSet execute(Connection con, PreparedStatement pre, ResultSet rs, String sql, Object[] params) throws SQLException {
       rs=null;
       if(con!=null){
           pre = con.prepareStatement(sql);
           for (int i = 0; i < params.length; i++) {
               pre.setObject(i+1,params[i]);
           }
           rs = pre.executeQuery();
       }
       return rs;
    }

    //编写预编译增删改公共方法
    public static int execute(Connection con, PreparedStatement pre, String sql, Object[] params) throws SQLException {
        int updateRows = 0;
        if(con!=null){
            pre = con.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                pre.setObject(i+1,params[i]);
            }
            updateRows = pre.executeUpdate();
        }
        return updateRows;
    }

    //释放资源
    public static boolean closeResource(Connection con, PreparedStatement pre, ResultSet rs){
        boolean flag = true;
        if(con!=null){
            try{
                con.close();
                con = null; //GC回收
            }catch (SQLException e){
                e.printStackTrace();
                flag = false;
            }
        }
        if(pre!=null){
            try {
                pre.close();
                pre = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }
        if(rs!=null){
            try {
                rs.close();
                rs = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }
        return flag;
    }
}

字符编码过滤器

建立 filter 包,然后在包下建立CharacterEncodingFilter

import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {}
}

在 web.xml 下注册编码过滤器,路径根据自己需要更改

<!-- 字符编码过滤器-->
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.qiu.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

建立实体对象

建立 pojo 包,然后根据数据库建立对应的实体类

以user表为例,建立 User 类,根据数据库字段建立对应私有属性,然后建立 get/set 方法,创建有参/无参构造方法

数据库操作实体类

建立 user 包,然后建立 UserDao 接口,面向接口编程

public interface UserDao {
    //得到要登录的用户信息
    public User getLoginUser(Connection con, String username, String password) throws SQLException;

    //修改当前用户密码
    public int updatePwd(Connection con, String username, String password)throws SQLException;
}

编写接口实现类 UserDaoImpl

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDaoImpl implements UserDao {
    //得到要登录的用户
    public User getLoginUser(Connection con, String username, String password) throws SQLException {
        PreparedStatement pre = null;
        ResultSet rs = null;
        User user = null;
        if(con!=null){
            String sql = "select * from user where username=? and password=?";
            Object[] params = {username,password};
            rs = BaseDao.execute(con, pre, rs, sql, params);
            if(rs.next()){
                user = new User();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
            }
            BaseDao.closeResource(null,pre,rs);
        }
        return user;
    }

    //修改当前用户密码
    public int updatePwd(Connection con, String username, String password) throws SQLException {
        PreparedStatement pre = null;
        int updateRows = 0;
        if(con!=null){
            String sql = "update user set password = ? where username = ?";
            Object[] params = {password,username};
            updateRows = BaseDao.execute(con, pre, sql, params);
            BaseDao.closeResource(null, pre, null);
        }
        return updateRows;
    }
}

业务层接口及实现类

建立 service 包,并在 service 包下建立 user

然后编写 UserService 接口

public interface UserService {
    //得到登录信息
    public User login(String username, String password);

    //根据用户ID 修改密码
    public boolean updatePwd(String username, String password);
}

编写接口实现类UserServiceImpl

public class UserServiceImpl implements UserService {
    //业务层都会调用dao层,所以我们要引入dao层
    private UserDao userDao;
    public UserServiceImpl(){
        userDao = new UserDaoImpl();
    }

    @Override
    public User login(String username, String password) {
        Connection con = null;
        User user = null;
        con = BaseDao.getConnection();
        //通过业务层调用对应的具体的数据库操作
        try {
            user = userDao.getLoginUser(con,username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            BaseDao.closeResource(con,null,null);
        }
        return user;
    }

    @Override
    public boolean updatePwd(String username, String password){
        Connection con = null;
        boolean flag = false;
        //根据用户ID 修改密码
        try{
            con = BaseDao.getConnection();
            if(userDao.updatePwd(con, username, password)>0){
                flag=true;
            }
        }catch (SQLException e){
            e.printStackTrace();
            try {
                con.rollback();//数据库回滚操作
            } catch (SQLException ex) { ex.printStackTrace(); }
        }finally {
            BaseDao.closeResource(con,null,null);
        }
        return flag;
    }
}

控制层实现类

建立 servlet 包,然后建立 user

在user包下建立 LoginServlet 类来处理登录请求

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 {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        //和数据库中的账号密码进行对比,调用业务层
        UserService userService = new UserServiceImpl();
        User user = userService.login(username, password);

        if(user!=null){
            //将用户信息放到Session中
            req.getSession().setAttribute(Constants.USER_SESSION,user);
            //跳转到主页
            resp.sendRedirect(req.getContextPath()+"/main/success.jsp");
        }else{
            //转发回登录页面,顺带提示它,用户名或者密码错误
            req.setAttribute(Constants.MESSAGE,"用户名或者密码错误");
            req.getRequestDispatcher("/login/login.jsp").forward(req,resp);
        }
    }

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

注册 LoginServlet

<!--login-->
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.qiu.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login.do</url-pattern>
</servlet-mapping>

在user包下建立 UserServlet 类来处理修改密码请求

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 UserServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从Session里面拿到username
        Object obj = req.getSession().getAttribute(Constants.USER_SESSION);
        String newpassword = req.getParameter("newpassword");
        boolean flag = true;
        if(obj!=null && !StringUtils.isNullOrEmpty(newpassword)){
            UserService userService = new UserServiceImpl();
            flag = userService.updatePwd(((User)obj).getUsername(),newpassword);
            if(flag){
                req.setAttribute(Constants.MESSAGE,"密码修改成功,请退出重新登录");
                req.getSession().removeAttribute(Constants.USER_SESSION);
            }else{
                req.setAttribute(Constants.MESSAGE,"密码修改失败");
            }
        }else{
            req.setAttribute(Constants.MESSAGE,"新密码存在问题");
        }
        req.getRequestDispatcher("/main/updatePwd.jsp").forward(req,resp);
    }

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

注册 UserServlet

<!--user-->
<servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>com.qiu.servlet.user.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/main/user.do</url-pattern>
</servlet-mapping>
<servlet>

编写常用工具类

建立 util 包,然后建立常用变量工具类 Constants

以后的常量放在工具类下

public class Constants {
    public final static String USER_SESSION = "userSession";
    public final static String MESSAGE = "message";
}

编写注销功能

思想:移除Session,然后重定向到登录页面

在servlet包中的user包内建立LogoutServlet类

public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //移除用户的Constants.USER_SESSION
        req.getSession().removeAttribute(Constants.USER_SESSION);
        resp.sendRedirect(req.getContextPath()+"/login/login.jsp");//返回登录页面
    }

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

注册Servlet

<!--logout-->
<servlet>
    <servlet-name>logout</servlet-name>
    <servlet-class>com.qiu.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>logout</servlet-name>
    <url-pattern>/logout.do</url-pattern>
</servlet-mapping>

在jsp下面应用logout.do,以a标签为例

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<a href="<c:url value="/logout.do"/>">退出</a>

登录拦截优化

思想:请求页面时,判断是否存在Session

在 filter 包下建立登录过滤器 SysFilter

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //过滤器,从Session中获取用户
        User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
        if(user==null){ //已被移除或者注销了,或者未登录
            response.sendRedirect(request.getContextPath()+"/login/login.jsp");
        }else {
            chain.doFilter(req, resp);
        }
    }

    @Override
    public void destroy() {}
}

注册过滤器

<!-- 用户登录过滤器-->
<filter>
    <filter-name>SysFilter</filter-name>
    <filter-class>com.qiu.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SysFilter</filter-name>
    <url-pattern>/main/*</url-pattern>
</filter-mapping>

UserServlet优化细节

  • 验证密码使用ajax及时动态优化
  • 实现Servlet复用
  • 使用前引入fastjson依赖
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;
import java.util.HashMap;
import java.util.Map;

//实现Servlet复用
public class UserServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");
        if(method!=null && method.equals("savepwd")){
            this.updataPwd(req,resp);
        }else if(method!=null && method.equals("pwdmodify")){
            this.pwdModify(req,resp);
        }
    }

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

    //修改密码
    public void updataPwd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从Session里面拿到username
        Object obj = req.getSession().getAttribute(Constants.USER_SESSION);
        String newpassword = req.getParameter("newpassword");
        boolean flag;
        if(obj!=null && !StringUtils.isNullOrEmpty(newpassword)){
            UserService userService = new UserServiceImpl();
            flag = userService.updatePwd(((User)obj).getUsername(),newpassword);
            if(flag){
                req.setAttribute(Constants.MESSAGE,"密码修改成功,请退出重新登录");
                req.getSession().removeAttribute(Constants.USER_SESSION);
            }else{
                req.setAttribute(Constants.MESSAGE,"密码修改失败");
            }
        }else{
            req.setAttribute(Constants.MESSAGE,"新密码存在问题");
        }
        req.getRequestDispatcher("/main/updatePwd.jsp").forward(req,resp);
    }

    //验证旧密码,session中有用户的密码
    public void pwdModify(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Object obj = req.getSession().getAttribute(Constants.USER_SESSION);
        String oldpassword = req.getParameter("oldpassword");

        //万能的Map:结果集
        Map<String,String> resultMap = new HashMap<String,String>();
        if(obj==null){//session失效过期了
            resultMap.put("result","sessionError");
        }else if(StringUtils.isNullOrEmpty(oldpassword)){   //输入的密码为空
            resultMap.put("result","error");
        }else{
            String userPassword = ((User)obj).getPassword();
            if(oldpassword.equals(userPassword)){
                resultMap.put("result","true");
            }else{
                resultMap.put("result","false");
            }
        }
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        //JSONArray 阿里巴巴的JSON工具类,转换格式
        writer.write(JSONArray.toJSONString(resultMap));
        writer.flush();
        writer.checkError();
    }
}

updatePwd.jsp 文件,根据环境做不同的修改

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <meta charset="utf-8">
    <title>修改密码</title>
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login/css/style.css"/>
    <link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_1808293_ftumhpfd07g.css"/>
    <script src="${pageContext.request.contextPath}/login/js/jQuery.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div class="form-wrapper">
    <div class="header">
        修改密码
    </div>

    <form action="${pageContext.request.contextPath}/main/user.do" method="post" class="update-form">
        <input type="hidden" name="method" value="savepwd">
        <div class="input-wrapper">
            <div class="border-wrapper">
                <input id="oldpassword" type="password" name="password" placeholder="旧密码" class="border-item" value="" required/>
            </div>
            <div class="border-wrapper">
                <input id="newpassword" type="password" name="newpassword" placeholder="新密码" class="border-item" value="" required/>
            </div>
            <div class="border-wrapper">
                <input id="rnewpassword" type="password" name="rnewpassword" placeholder="确认密码" class="border-item" value="" required/>
            </div>
        </div>
        <div class="action">
            <div id="save" class="btn" onclick="send()">提交</div>
        </div>
    </form>

    <div id="message" style="color:red;font-size: 1.2em;margin-top: 20px">${message}</div>
</div>
<script>
    let oldpassword = null;
    let newpassword = null;
    let rnewpassword = null;
    let saveBtn = null;
    let message = null;
    let path = "${pageContext.request.contextPath}";
    $(function () {
        oldpassword = $("#oldpassword");
        newpassword = $("#newpassword");
        rnewpassword = $("#rnewpassword");
        saveBtn = $("#save");
        message = $("#message");

        oldpassword.on("focus",function (){
            message.html("请输入原来密码!");
         }).on("blur",function () {
            $.ajax({
                type:"GET",
                url:path+"/main/user.do",
                data:{method:"pwdmodify",oldpassword:oldpassword.val()},
                //上面等价于 path+"/main/user.do?method=pwdmodify&oldpassword=oldpassword.val()"
                dataType:"json",
                success:function (data) {
                    if(data.result === "true"){ //旧密码正确
                        message.html("旧密码验证成功!");
                    }else if(data.result ==="false"){
                        message.html("原密码输入不正确!");
                    }else if(data.result ==="sessionError"){
                        message.html("当前用户session过期,请重新登陆!");
                    }else if(data.result ==="error"){
                        message.html("请输入旧密码!");
                    }
                },
                error:function (data) {
                    //请求出错
                    message.html("请求出错!");
                }
            });
        });
        //新密码
        newpassword.on("focus",function () {
            message.html("密码长度必须是大于6位小于20位!");
        }).on("blur",function () {
            if(newpassword.val()!=null && newpassword.val().length>=6
                && newpassword.val().length<20){
                message.html("新密码符合要求!");
            }else{
                message.html("密码输入不符合规范,请重新输入");
            }
        });

        //确认密码
        rnewpassword.on("focus",function () {
            message.html("请输入与上面一致的密码");
        }).on("blur",function () {
            if(newpassword.val()!=null && newpassword.val().length>=6
                && newpassword.val().length<20 && newpassword.val() === rnewpassword.val()){
                message.html("确认密码符合要求!");
            }else{
                message.html("两次密码输入不一致,请重新输入!");
            }
        });

    });
    function send(){
        if(message.html()==="密码修改成功,请退出重新登录" || (oldpassword.val().length!==0 && newpassword.val().length!==0 && rnewpassword.val().length!==0)){
            document.getElementsByClassName("update-form")[0].submit();
        }else{
            message.html("存在未填项,请重新检查!");
        }
    }
</script>
</body>
</html>

补充内容

  • 设置欢迎页和 Session 过期时间
<!--  设置欢迎页-->
<welcome-file-list>
    <welcome-file>/login/login.jsp</welcome-file>
</welcome-file-list>
<!--设置Session默认过期时间(分钟)-->
<session-config>
    <session-timeout>30</session-timeout>
</session-config>
  • fastjson 依赖
<!-- fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>
  • 分包情况:pojo 包、 dao 包、 user包、 service 包、 servlet 包、 filter 包、 util
原文地址:https://www.cnblogs.com/qiu-m/p/13177974.html