数据库配置文件
创建 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 下注册编码过滤器,路径根据自己需要更改
CharacterEncodingFilter
com.qiu.filter.CharacterEncodingFilter
CharacterEncodingFilter
/*
建立实体对象
建立 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
com.qiu.servlet.user.LoginServlet
login
/login.do
在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
UserServlet
com.qiu.servlet.user.UserServlet
UserServlet
/main/user.do
编写常用工具类
建立 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
com.qiu.servlet.user.LogoutServlet
logout
/logout.do
在jsp下面应用logout.do,以a标签为例
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
">退出
登录拦截优化
思想:请求页面时,判断是否存在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() {}
}
注册过滤器
SysFilter
com.qiu.filter.SysFilter
SysFilter
/main/*
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 resultMap = new HashMap();
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" %>
修改密码
修改密码
${message}
补充内容
- 设置欢迎页和 Session 过期时间
/login/login.jsp
30
- fastjson 依赖
com.alibaba
fastjson
1.2.62
- 分包情况:pojo 包、 dao 包、 user包、 service 包、 servlet 包、 filter 包、 util 包