JavaWeb+JDBC+登录验证
登录界面
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="keys" content="">
<meta name="author" content="">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="/css/login.css">
</head>
<body>
<div class="container">
<form id="loginForm" action="dologin.page" method="post" class="form-signin" role="form">
<h2 class="form-signin-heading"><i class="glyphicon glyphicon-user"></i> 用户登录</h2>
<div class="form-group has-success has-feedback">
<input type="text" class="form-control" id="loginacct" name="loginacct" placeholder="请输入登录账号" autofocus>
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-success has-feedback">
<input type="password" class="form-control" id="userpasswd" name="userpasswd" placeholder="请输入登录密码" style="margin-top:10px;">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<a class="btn btn-lg btn-success btn-block" onclick="dologin()" > 登录</a>
</form>
</div>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="/layer/layer.js"></script>
<script src="/ui/login.js"></script>
</body>
</html>
js
function dologin() {
//非空校验
var loginacct=KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲loginacct").val…("#userpasswd").val();
if(userpasswd==""){
// alert(“用户登录密码不能为空,请输入”);
layer.msg(“用户登录密码不能为空,请输入”,{time:1000,icon:5,shift:6},function(){
});
return;
}
//提交表单
// alert(“提交表单”);
// $("#loginForm").submit();
//使用ajax提交数据
var loadingIndex=null;//layer插件的等待界面的状态变量
$.ajax({
type:“POST”,
dataType:“json”,
url:“UserServlet?method=loginAjax”,
data:{
“loginacct”:loginacct,
“userpasswd”:userpasswd
},
//考虑到发送数据过程中网络延迟等情况,加入layer的等待效果,用户体验良好
beforeSend:function(){//加载的操作,发送数据前
//使用插件的效果
loadingIndex=layer.msg(“处理中”,{icon:16});
},//服务器返回结果后,采取动作
//jsondata–"{“success”:“true”,“result”:"{"":"","":""}",“message”:“info—”}"
success:function(result){
//Json.parse(result.result)
layer.close(loadingIndex);//拿到数据了就应该关闭等待效果
if(result.success){
window.location.href="/DispatcherServlet?method=mainPage";
}else{
layer.msg(“用户登录账号或密码不正确,请重新输入”,{time:1000,icon:5,shift:6},function(){
});
}
}
});//所谓使用json对象,简单理解就是大括号,键值对,各种值的表达形式
}
CSS
body {
padding-top: 40px;
padding-bottom: 40px;
background-color: #eee;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
position: relative;
height: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
##c3po配置文件
<?xml version="1.0" encoding="UTF-8" ?> <![CDATA[ jdbc:mysql://localhost:3306/mes?useUnicode=true&characterEncoding=UTF-8&useServerPrepStmts=true&prepStmtCacheSqlLimit=256&cachePrepStmts=true&prepStmtCacheSize=256&rewriteBatchedStatements=true ]]> com.mysql.jdbc.Driver root root <property name="acquireIncrement">3</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">2</property>
<property name="maxPoolSize">10</property>
</default-config>
## dao.propertice
userDao=com.mes.dao.impl.UserDaoImpl
注解类:
*package com.mes.annotaion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTransaction {
String value() default "openTransaction";
}
base
baseDao
package com.mes.base;
import java.sql.Connection;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.mes.common.ConnectionContext;
import com.mes.utils.MyQueryRunner;
import com.mes.utils.ReflectUtil;
//UserDaoImpl extends BaseDao
public class BaseDao implements Dao {
private Class<T> clazz;
protected MyQueryRunner queryRunner=new MyQueryRunner();
public BaseDao() {
this.clazz = ReflectUtil.getSupserGenericType(getClass());//使用�?个reflect工具类,返回T的类�?
}
@Override
public T queryForBean(String sql, Object... args) {
Connection conn=null;
try {
//获取连接
conn=ConnectionContext.getInstance().get();
return queryRunner.query(conn,sql,args,new BeanHandler<T>(clazz));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("查询出现问题!!");
}
}
}
BaseServlet
package com.mes.base;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.mes.common.JsonData;
/**
-
BaseServlet用来作为其它Servlet的父类
-
一个类多个请求处理方法,每个请求处理方法的原型与service相同! 原型 = 返回值类型 + 方法名称 + 参数列表
/
public class BaseServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 1. 获取method参数,它是用户想调用的方法 2. 把方法名称变成Method类的实例对象 3. 通过invoke()来调用这个方法
/
String methodName = request.getParameter(“method”);
Method method = null;
/*
* 2. 通过方法名称获取Method对象
*/
try {
method = this.getClass().getMethod(methodName,
HttpServletRequest.class, HttpServletResponse.class);
} catch (Exception e) {
throw new RuntimeException(“您要调用的方法:” + methodName + “它不存在!”, e);
}/**
* 3. 通过method对象来调用它
*/
try {//returnResult
Object resultObj=method.invoke(this, request, response);
//如果是json字符串,就直接写回数据给页面
if(resultObj!=null&&resultObj instanceof JsonData) {
//这里要把resultobj也转换成json格式
JsonData jsonData=(JsonData) resultObj;
Gson gson = new Gson();
String jsonStr = gson.toJson(jsonData,JsonData.class);
//"{“success”:“true”,“result”:"{"":"","":""}",“message”:“info—”}"
response.getWriter().print(jsonStr);
return ;
}//如果不是json封装类,则得到跳转路径 String result=(String)resultObj; //"r:/WEB-INF/jsp/index.jsp" if(result != null && !result.trim().isEmpty()) {//如果请求处理方法返回不为空 int index = result.indexOf(":");//获取第一个冒号的位置 if(index == -1) {//如果没有冒号,使用转发 request.getRequestDispatcher(result).forward(request, response); } else {//如果存在冒号 String start = result.substring(0, index);//分割出前缀 String path = result.substring(index + 1);//分割出路径 if(start.equals("f")) {//前缀为f表示转发 request.getRequestDispatcher(path).forward(request, response); } else if(start.equals("r")) {//前缀为r表示重定向 response.sendRedirect(request.getContextPath() + path); } } }
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Dao
package com.mes.base;
public interface Dao {
T queryForBean(String sql,Object... args);
}
common
CommonUtils
package com.mes.common;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
/**
-
包含string的处理
*/
public class CommonUtils {//返回一个不重复的字符串
public static String uuid() {
return UUID.randomUUID().toString().replace("-","").toUpperCase();
}//map转换成bean
public static T toBean(Map map,Class clazz) {
try {
//通过clazz创建实例
T bean=clazz.newInstance();
//使用beanutils.populute封装map数据到bean中
//日期格式转换
ConvertUtils.register(new DateConverter(“yyyy-MM-dd”),java.util.Date.class);
BeanUtils.populate(bean, map);//map.put(“date”,string);
//bean-date:Date
return bean;
} catch (Exception e) {
throw new RuntimeException(e+“封装bean出了问题”);
}}
}
connectionContext
package com.mes.common;
import java.sql.Connection;
//连接的上下文工具,提供全局使用,保证线程变量的安�?
public class ConnectionContext {//想成�?个存放线程的容器//做成单例模式,保证线程安�?
//饿汉�?
private ConnectionContext() {}
private static ConnectionContext instance=new ConnectionContext();
public static ConnectionContext getInstance() {
return instance;
}
//准备本地线程变量
private ThreadLocal<Connection> connectionThreadLocal=//
new ThreadLocal<Connection>();
public void bind(Connection conn) {
connectionThreadLocal.set(conn);
}
public Connection get() {
return connectionThreadLocal.get();
}
public void remove() {
connectionThreadLocal.remove();
}
}
DateConberter
package com.mes.common;
import java.text.SimpleDateFormat;
import org.apache.commons.beanutils.Converter;
public class DateConverter implements Converter{
private String format;
public DateConverter(String format) {
this.format=format;
}
@Override
public Object convert(Class type, Object value) {
try {
//我们遇到的需要转换的值是null,直接返回null
if(value==null) return null;
//接受到值并且需要转换成date类型,这个值如果不是String,不转
if(!(value instanceof String)) {
return value;
}
//把值转换成string
String val=(String)value;
//日期格式化
SimpleDateFormat sdf=new SimpleDateFormat(format);
//返回转换了格式的日期
return sdf.parse(val);
}catch(Exception e) {
throw new RuntimeException(e);
}
}
}
JsonDatapackage com.mes.common;
public class JsonData {
private boolean success=false;
private Object result;
private String message;
public JsonData() {
}
public JsonData(boolean success) {
this.success = success;
}
public JsonData(boolean success, Object result) {
this.success = success;
this.result = result;
}
public JsonData(boolean success, Object result, String message) {
this.success = success;
this.result = result;
this.message = message;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public Object getResult() {
return result;
}
public void setResult(Object result){
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
comtroller
DispatcherServlet
package com.mes.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mes.base.BaseServlet;
//用来转发页面
public class DispatcherServlet extends BaseServlet{
private static String RPATH=“r:/WEB-INF/jsp/”;
private static String FPATH=“f:/WEB-INF/jsp/”;
// /DispatcherServlet?method=loginPage
//登录页面
public String loginPage(HttpServletRequest request,HttpServletResponse response) {
return FPATH+“login.html”;
}
//欢迎页面
public String mainPage(HttpServletRequest request,HttpServletResponse response) {
return FPATH+"main.html";
}
}
UserServlet
package com.mes.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.google.gson.Gson;
import com.mes.base.BaseServlet;
import com.mes.common.CommonUtils;
import com.mes.common.JsonData;
import com.mes.dao.UserDao;
import com.mes.factory.DaoFactory;
import com.mes.pojo.User;
//@Controller
public class UserServlet extends BaseServlet{
private static String RPATH="r:/WEB-INF/jsp/";
private static String FPATH="f:/WEB-INF/jsp/";
//@Resource
//private UserDao<User> userDao;
private UserDao<User> userDao=(UserDao<User>) DaoFactory.getInstance().getDaoByName("userDao");
//用户登录
public JsonData loginAjax(HttpServletRequest request,HttpServletResponse response) {
//准备好一个json对象
JsonData result=new JsonData();
//web2bean 2-to
User user=CommonUtils.toBean(request.getParameterMap(), User.class);
//query4Login queryForLogin
User dbUser=userDao.query4Login(user.getLoginacct());
//比对密码
if(dbUser!=null&&user.getUserpasswd().equals(dbUser.getUserpasswd())) {
//在服务器搞一个空间,用来专门存储这个指定浏览器的登录用户状态
HttpSession session=request.getSession();
session.setAttribute("loginUser",dbUser);
result.setSuccess(true);
}else {
result.setSuccess(false);
}
return result;
}
}
dao
UserDaoImpl
package com.mes.dao.impl;
import java.util.List;
import java.util.Map;
import com.mes.base.BaseDao;
import com.mes.dao.UserDao;
import com.mes.pojo.User;
public class UserDaoImpl extends BaseDao implements UserDao {
@Override
public User query4Login(String loginacct) {
String sql="select * from mes_user where loginacct=?";
Object[] params=new Object[] {loginacct};
User user=queryForBean(sql, params);
return user;
}
}
UserDao
package com.mes.dao;
import java.util.List;
import java.util.Map;
import com.mes.annotaion.MyTransaction;
import com.mes.base.Dao;
public interface UserDao extends Dao{
public User query4Login(String loginacct);
}
factory
DaoFactory
package com.mes.factory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.Properties;
import com.mes.annotaion.MyTransaction;
import com.mes.base.Dao;
import com.mes.common.ConnectionContext;
import com.mes.utils.JdbcUtil;
public class DaoFactory {
//private Object target;
private DaoFactory() {
throw new RuntimeException("不可以反射哟");
}
private DaoFactory(int init) {}
private static DaoFactory instance=new DaoFactory(1);
public static DaoFactory getInstance() {
if(instance==null) {
synchronized(DaoFactory.class) {
if(instance==null) {
instance=new DaoFactory();
}
}
}
return instance;
}
//产生一个dao userDao--userDaoImpl
public Dao getDaoByName(String daoName) {
//获取这个dao-使用properties
Properties prop=new Properties();
InputStream in=DaoFactory.class.getClassLoader()//
.getResourceAsStream("dao.properties");
// InputStream in=new FileInputStream(“dao.properties”);
try {
//加载输入流,读取文件内容
prop.load(in);
//classPath=com.mes.dao.impl.UserDaoImpl
String classPath=prop.getProperty(daoName);
if(classPath==null) {
throw new RuntimeException(“没有文件”);
}
//通过反射的方式将类的全路径名,实例化出一个类对象
Dao targetDao=(Dao) Class.forName(classPath).newInstance();
//this.target=targetDao;
//事务处理-采用的是动态代理技术
targetDao=(Dao) getTransactionDao(targetDao);
return targetDao;
} catch (IOException e) {
throw new RuntimeException(“加载properties出问题”);
} catch (Exception e) {
throw new RuntimeException(“初始化dao出问题”);
}
}
public Object getTransactionDao(Object target) {
return Proxy.newProxyInstance(//
target.getClass().getClassLoader(), //
target.getClass().getInterfaces(), //
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
// 若方法上有事务注解,则执行开启事�?
MyTransaction ann = method.getDeclaredAnnotation(MyTransaction.class);
Connection conn=null;
// 判断注解不为空,取�??
if (ann != null) {
// �?启事�?,以下实现真正的开启事务和关闭事务
// conn.rollback conn.commit
String value = ann.value();
if (value.equals("openTransaction")) {
try {
// 开启一个连接
conn = JdbcUtil.getConnection();
// 开启事务
conn.setAutoCommit(false);// begin;
// connection上下文绑定连接
ConnectionContext.getInstance().bind(conn);
result = method.invoke(target, args);// userDao.add update delete
// int i=10/0;
// conn=ConnectionContext.getInstance().get();
conn.commit();
} catch (Exception e) {
conn.rollback();
throw new RuntimeException(e + “sql执行出问题,执行数据回滚”);
} finally {
// 释放资源
// 接触connection上下文的绑定状�??
ConnectionContext.getInstance().remove();
// 将connection放回连接�?
JdbcUtil.close(conn, null, null);
return result;
}
}
}
//不需要开启事务的
try {
// 开启一个连接
conn = JdbcUtil.getConnection();
// connection上下文绑定连接 statement-sql
ConnectionContext.getInstance().bind(conn);
result = method.invoke(target, args);// userDao.add update delete
} catch (Exception e) {
throw new RuntimeException(e + “sql执行出问题,执行数据回滚”);
} finally {
ConnectionContext.getInstance().remove();
JdbcUtil.close(conn, null, null);
return result;
}
}
});
}
}
poji
package com.mes.pojo;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 2900466913200185672L;
private Integer id;//用户id
private String username;//用户名
private String loginacct;//用户类型
private String userpasswd;//密码
private String email;//电子邮件
public User() {
}
public User(Integer id, String username, String loginacct, String userpasswd, String email) {
super();
this.id = id;
this.username = username;
this.loginacct = loginacct;
this.userpasswd = userpasswd;
this.email = email;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getLoginacct() {
return loginacct;
}
public void setLoginacct(String loginacct) {
this.loginacct = loginacct;
}
public String getUserpasswd() {
return userpasswd;
}
public void setUserpasswd(String userpasswd) {
this.userpasswd = userpasswd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "MesUser [id=" + id + ", username=" + username + ", loginacct=" + loginacct + ", userpasswd="
+ userpasswd + ", email=" + email + "]";
}
}
utils
jdbcUtils
package com.mes.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
//使用连接池,采用的c3p0连接�?
public class JdbcUtil {
//使用c3p0连接�?
private static DataSource ds=new ComboPooledDataSource();//close--List.add(conn)
public static DataSource getDataSource() {
return ds;
}
//自定义一个获取连接池中的连接方法
public static Connection getConnection()throws SQLException{
return ds.getConnection();
}
public static void close(Connection conn,Statement state,ResultSet rs) {
if(rs!=null) {
try {
rs.close();//oop--conn.close()----pool.add(conn)
} catch (SQLException e) {
throw new RuntimeException("关闭返回结果集失败!!!");
}finally {
rs=null;
}
}
if(state!=null) {
try {
state.close();//pool.add(conn)
} catch (SQLException e) {
throw new RuntimeException("关闭statement失败!!�??");
}finally {
state=null;
}
}
if(conn!=null) {//oop
try {
conn.close();//pool.add(conn)
} catch (SQLException e) {
throw new RuntimeException("根本就没有要关闭的连接!!!");
}
}
}
}
MyQueryRunner
package com.mes.utils;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
public class MyQueryRunner extends QueryRunner{
//批量数据操作
@Override
public int[] batch(Connection conn, String sql, Object[][] params) throws SQLException {
int[] result=super.batch(conn, sql, params);
return result;
}
//查询操作,传参数的方法
@Override
public <T> T query(Connection conn, String sql, Object[] params, ResultSetHandler<T> rsh) throws SQLException {
T result=super.query(conn, sql, params, rsh);
return result;
}
//查询不带参数的方�?
@Override
public <T> T query(Connection conn, String sql,ResultSetHandler<T> rsh) throws SQLException {
T result=super.query(conn, sql,rsh);
return result;
}
//dml语句-update insert delete
@Override
public int update(Connection conn, String sql, Object... params) throws SQLException {
int result=super.update(conn, sql, params);
return result;
}
@Override
public int update(Connection conn, String sql, Object param) throws SQLException {
int result=super.update(conn, sql, param);
return result;
}
@Override
public int update(Connection conn, String sql) throws SQLException {
int result=super.update(conn, sql);
return result;
}
}
ReflectUtils
package com.mes.utils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ReflectUtil {
//获取的一个泛型类类型
public static Class getSuperClassGenericType(Class clazz,int index) {
Type genType=clazz.getGenericSuperclass();
//
if(!(genType instanceof ParameterizedType)) {
return Object.class;
}
Type[] params=((ParameterizedType)genType).getActualTypeArguments();
//
if(index>params.length || index<0) {
return Object.class;
}
if(!(params[index] instanceof Class)) {
return Object.class;
}
return (Class) params[index];
}
//获取basedao类似结构的子类传递上来的类型
//返回T类型的字节码
//泛型方法,返回的泛型类型等于定义的泛型类�??
public static <T> Class<T> getSupserGenericType(Class clazz){
return getSuperClassGenericType(clazz,0);
}
}
创建一个自定义列表
-
Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。1
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎