源码结构
1.pojo层
package com.crm.pojo;
import java.io.Serializable;
//登录的userbean
public class User implements Serializable {
private Integer id;
private String username;
private String password;
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
public User(Integer id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public User() {
super();
}
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2.utils层
package com.crm.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;
/**
*
* @author Administrator
* @ClassName: JdbcUtil
* @Description: 使用c3p0连接数据库的工具类
* @version V1.0
* @date 2019年10月25日
*
*/
//使用连接池,采用的c3p0连接池
public class JdbcUtil {
//com.mchange.v2.c3p0.ComboPooledDataSource.ComboPooledDataSource()
// 使用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();
}
// 关闭c3p0连接池
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;
}
}
// 关闭执行的sql
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("根本就没有要关闭的连接!!!");
}
}
}
}
package com.crm.utils;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
/**
*
* @author Administrator
* @ClassName: MyQueryRunner
* @Description:批量数据crud操作
* @version V1.0
* @date 2019年10月25日
*
*/
public class MyQueryRunner extends QueryRunner {
@Override
public int[] batch(Connection conn, String sql, Object[][] params) throws SQLException {
// zhen真正起效果的是super.batch
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;
}
}
package com.crm.utils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
*
* @author Administrator
* @ClassName: ReflectUtil
* @Description: 反射的工具类
* @version V1.0
* @date 2019年10月25日
*
*/
public class ReflectUtil {
// 获取的一个泛型类类型
// 返回直接继承的父类的泛型参数类型
public static Class getSuperClassGenericType(Class clazz, int index) {
// 返回当前类的父类的Type
Type genType = clazz.getGenericSuperclass();
// 验证这个类型是否是参数化类型
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
// getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。
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);
}
}
3.factory层
package com.crm.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.crm.annotaion.MyTransaction;
import com.crm.base.Dao;
import com.crm.common.ConnectionContext;
import com.crm.utils.JdbcUtil;
public class DaoFactory {
// 根据传进来的dao进行数据库的连接以及crud操作
// private Object target;
// 针对反射做出的处理
private DaoFactory() {
throw new RuntimeException("不可以做反射哦");
}
// daoFactory本身对自己进行实例化
private DaoFactory(int init) {
}
// new 出自己 让外部可以访问
private static DaoFactory instance = new DaoFactory(1);
// 使用懒加载对传进来的值进行非空判断
public static DaoFactory getInstance() {
// 如果里面的值为空,重新创建一个DaoFactory
// 对DaoFactory进行枷锁 每次只允许一个对象去new它
if (instance == null) {
synchronized (DaoFactory.class) {
if (instance == null) {
instance = new DaoFactory();
}
}
}
return instance;
}
// 加载配置文件 产生一个dao userDao--userDaoImpl
public Dao getDaoName(String daoName) {
// 使用properties读取配置文件
Properties prop = new Properties();
// ClassLoader 把class文件加载到jvm中
InputStream in = DaoFactory.class.getClassLoader()//
.getResourceAsStream("dao.properties");
// InputStream in=new FileInputStream("dao.properties");
try {
// 加载读取配置文件
prop.load(in);
// 读取文件内容//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) {
// 使用jdk动态代理
// 生成一个代理的实例newProxyInstance
// 通过当前的target取得所属的class 和所对应代理对象的规范 UserDaoImpl
return Proxy.newProxyInstance(target.getClass().//
getClassLoader(), target.getClass().//
// 通过调用InvocationHandler下的invoke方法处理代理的实例
getInterfaces(),
new InvocationHandler() {
// 调用方法的代理实例
// proxy==UserDaoImpl/method==UserDaoImpl下面的方法/Object[] args==查询的参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
// 若方法上有事务注解,则执行开启事务注解
MyTransaction ann = method.getDeclaredAnnotation(MyTransaction.class);
Connection conn = null;
// 判断方法上的注解是不为空,
// conn.rollback conn.commit 事务回滚,提交事务
if (ann != null) {
String value = ann.value();
if (value.equals("oprnTransaction")) {
try {
// 开启一个连接
conn = JdbcUtil.getConnection();
// 开启事务
conn.setAutoCommit(false);
// 绑定数据库的连接对象
ConnectionContext.getInstancee().bind(conn);
// 调用相应的增删改查方法
result = method.invoke(target, args);
// 提交数据更新数据库
conn.commit();
} catch (Exception e) {
// 发生错误 ,数据回滚
conn.rollback();
throw new RuntimeException(e + "sql执行出问题,执行数据回滚");
} finally {
// 资源释放
ConnectionContext.getInstancee().remove();
// 将连接放回连接池
JdbcUtil.close(conn, null, null);
return result;
}
}
}
// 不需要开启事物的
try {
// 开启连接
conn = JdbcUtil.getConnection();
// connection绑定上下文连接
ConnectionContext.getInstancee().bind(conn);
result = method.invoke(target, args);// crud语句
} catch (Exception e) {
throw new RuntimeException(e + "sql执行出问题,执行数据回滚");
} finally {
ConnectionContext.getInstancee().remove();
JdbcUtil.close(conn, null, null);
return result;
}
}
});
}
}
4.dao层
package com.crm.dao;
import java.util.List;
import java.util.Map;
import com.crm.annotaion.MyTransaction;
import com.crm.base.Dao;
public interface UserDao<User> extends Dao<User> {
@MyTransaction
public void addUser(User user);
public void queryTest();
public User query4Login(String username);
public List<User> pageQueryData(Map<String, Object> map);
public void insert(User user);
public Boolean existUser(String username);
}
5.dao实现类
package com.crm.dao.impl;
import java.util.List;
import java.util.Map;
import com.crm.base.BaseDao;
import com.crm.dao.UserDao;
import com.crm.pojo.User;
public class UserDaoImpl extends BaseDao<User> implements UserDao<User> {
@Override
public void addUser(User user) {
// TODO Auto-generated method stub
}
@Override
public void queryTest() {
// TODO Auto-generated method stub
}
@Override
public User query4Login(String username) {
String sql = "select * from mes_user1 where username=?";
Object[] params = new Object[] { username };
User user = queryForBean(sql, params);
return user;
}
@Override
public List<User> pageQueryData(Map<String, Object> map) {
// TODO Auto-generated method stub
return null;
}
@Override
public void insert(User user) {
// TODO Auto-generated method stub
}
@Override
public Boolean existUser(String username) {
// TODO Auto-generated method stub
return null;
}
}
6.controller层
package com.crm.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.crm.base.BaseServlet;
public class DispatcherServlet extends BaseServlet {
/**
* 对页面进行分发
*/
private static final long serialVersionUID = 1L;
public String loginPage(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
return contactStr("login", "f");
}
public String mainPage(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
return contactStr("main", "r");
}
}
package com.crm.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.crm.base.BaseServlet;
import com.crm.common.CommonUtils;
import com.crm.common.JsonData;
import com.crm.dao.UserDao;
import com.crm.factory.DaoFactory;
import com.crm.pojo.User;
public class UserServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
// @Resource
// private UserDao userDao;
// getInstance 调用对象的实例,层级调用。
private UserDao userDao = (UserDao) DaoFactory.getInstance().getDaoName(“userDao”);
public JsonData loginAjax(HttpServletRequest request, HttpServletResponse response) {
// 准备一个json对象对页面传过来的json'数据进行校验
JsonData result = new JsonData();
User user = CommonUtils.toBean(request.getParameterMap(), User.class);
User dbUser = userDao.query4Login(user.getUsername());
System.out.println(dbUser);
if (dbUser != null && user.getPassword().equals(dbUser.getPassword())) {
HttpSession session = request.getSession();
session.setAttribute("loginUser", dbUser);
result.setSuccess(true);
} else {
result.setSuccess(false);
}
return result;
}
}
7.common层
package com.crm.common;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
public class CommonUtils {
//map转bean
public static <T> T toBean(Map map, Class<T> clazz) {
T bean = null;
try {
bean = clazz.newInstance();
BeanUtils.populate(bean, map);
return bean;
} catch (Exception e) {
// TODO Auto-generated catch block
throw new RuntimeException("封装bean出了问题", e);
}
}
}
package com.crm.common;
import java.sql.Connection;
public class ConnectionContext {
// 连接上下文的工具类,提供全局使用,保证线程变量安全
// 恶汉单例模式
private ConnectionContext() {
}
// ConnectionContext保护每次链接的唯一性
private static ConnectionContext instance = new ConnectionContext();
public static ConnectionContext getInstancee() {
return instance;
}
// 准备本地线程变量
// ThreadLocal保证线程安全 解决可以解决线程并发问题
// 在这里保证这个本地线程链接的安全性
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();
}
}
package com.crm.common;
//json数据
public class JsonData {
private boolean success = false;// 验证状态
private Object result;// 验证结果;true/false
private String message;// 消息
public JsonData() {
super();
}
public JsonData(boolean success, Object result, String message) {
super();
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;
}
@Override
public String toString() {
return "JosnData [success=" + success + ", result=" + result + ", message=" + message + "]";
}
}
8.base层
package com.crm.base;
import java.sql.Connection;
import java.util.List;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.crm.common.ConnectionContext;
import com.crm.utils.MyQueryRunner;
import com.crm.utils.ReflectUtil;
public class BaseDao<T> implements Dao<T> {
private Class<T> clazz;
protected MyQueryRunner queryRunner = new MyQueryRunner();
public BaseDao() {
this.clazz = ReflectUtil.getSupserGenericType(getClass());// 使用�?个reflect工具类,返回T的类�?
}
// 添加
@Override
public int add(String sql, Object... args) {
// TODO Auto-generated method stub
return update(sql, args);
}
// 跟新
@Override
public int update(String sql, Object... args) {
Connection conn = null;
try {
conn = ConnectionContext.getInstancee().get();
return queryRunner.update(conn, sql, args);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("查询列表出现问题!!");
}
}
// 删除
@Override
public int delete(String sql, Object... args) {
// TODO Auto-generated method stub
return update(sql, args);
}
@Override
public T queryForBean(String sql, Object... args) {
Connection conn = null;
try {
// 获取连接
// getinstance获取这个类 的实例对象
// 这句代码只是获取一个conn链接
conn = ConnectionContext.getInstancee().get();
return queryRunner.query(conn, sql, args, new BeanHandler<T>(clazz));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("查询出现问题!!");
}
}
// 查询及多条数据
@Override
public List<T> queryForList(String sql, Object... args) {
Connection conn = null;
try {
conn = ConnectionContext.getInstancee().get();
// BeanListHandler将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
return queryRunner.query(conn, sql, args, new BeanListHandler<T>(clazz));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("查询列表出现问题!!");
}
}
}
package com.crm.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.crm.common.JsonData;
import com.google.gson.Gson;
public class BaseServlet extends HttpServlet {
// 设置前缀
private static String preRFix = "r:/WEB-INF/jsp/";
private static String preFFix = "f:/WEB-INF/jsp/";
// 设置后缀
private static String afterFix = ".html";
// 前缀加后缀的得到具体的路径
public static String contactStr(String str, String pre) {
if (pre.equals(preRFix)) {
return preRFix + str + afterFix;
} else {
return preFFix + str + afterFix;
}
}
// 处理servlet的请求及方法
@Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String methodName = req.getParameter("method");
Method method = null;
try {
method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
} catch (Exception e) {
throw new RuntimeException("您调用的方法:" + methodName + "不存在", e);
}
try {
// 处理json数据
Object resultObj = method.invoke(this, req, resp);
if (resultObj != null && resultObj instanceof JsonData) {
JsonData jsondata = (JsonData) resultObj;
Gson gson = new Gson();
String objstr = gson.toJson(jsondata, JsonData.class);
resp.getWriter().print(objstr);
return;
}
// string对象数据
String result = (String) resultObj;
if (result != null && !result.trim().isEmpty()) {
int index = result.indexOf(":");
if (index == -1) {
req.getRequestDispatcher(result).forward(req, resp);
} else {
String start = result.substring(0, index);
String path = result.substring(index + 1);
// 使用s转发 重定向
if (start.equals("f")) {
req.getRequestDispatcher(path).forward(req, resp);
} else if (start.equals("r")) {
resp.sendRedirect(req.getContextPath() + path);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package com.crm.base;
import java.util.List;
import com.crm.annotaion.MyTransaction;
/**
*
* @author Administrator
* @ClassName: Dao 规范
* @Description: TODO
* @version V1.0
* @date 2019年10月31日
*
* @param <T>
*/
public interface Dao<T> {
@MyTransaction
int add(String sql, Object... args);
@MyTransaction
int update(String sql, Object... args);
@MyTransaction
int delete(String sql, Object... args);
T queryForBean(String sql, Object... args);
List<T> queryForList(String sql, Object... args);
}
9.annotaion层
package com.crm.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 "oprnTransaction";
}
10.连接池配置
<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config>
<default-config>
<property name="jdbcUrl">
<![CDATA[
jdbc:mysql://localhost:3306/mes?useUnicode=true&characterEncoding=UTF-8&useServerPrepStmts=true&prepStmtCacheSqlLimit=256&cachePrepStmts=true&prepStmtCacheSize=256&rewriteBatchedStatements=true
]]>
</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 链接用完了自动增量3个 -->
<property name="acquireIncrement">3</property>
<!-- 初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。 -->
<property name="initialPoolSize">10</property>
<!-- 最小取值 -->
<property name="minPoolSize">2</property>
<!-- 最大取值 -->
<property name="maxPoolSize">10</property>
</default-config>
</c3p0-config>
11.外部资源文件
userDao=com.crm.dao.impl.UserDaoImpl``
12.登录界面
<title>Signin Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/login_css.css">
<script src="/ui/login.js"></script>
<div class="container">
<form class="form-signin" method="POST">
<h2 class="form-signin-heading">小黑黑</h2>
<!-- <label for="inputUser" class="sr-only">User</label> -->
<input type="text" id="inputUser" class="form-control" placeholder="Username" >
<!-- <label for="inputPassword" class="sr-only">Password</label> -->
<input type="password" id="inputPassword" class="form-control" placeholder="Password" >
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> 记住密码
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" id="btn_1" type="button">登录</button>
</form>
</div>
<script src="/layer/layer.js"></script>
13.验证的js
$(function (){
$("#btn_1").click(function(){
var username=$("#inputUser").val();
var password=$("#inputPassword").val();
if(username==""){
layer.msg("用户的账号不能为空",{time:1000,icon:5,shift:6},function(){
});
return;
}
if(password==""){
layer.msg("用户的密码不能为空",{time:1000,icon:5,shift:6},function(){
});
return;
}
var loadingIndex=null;
$.ajax({
type:"POST",
dataType:"json",
url:"UserServlet?method=loginAjax",
data:{
"username":username,
"password":password
},
// 等待效果
beforeSend:function(){
loadingIndex:layer.msg(“处理中”,{icon:16});
},
success:function(result){
layer.close(loadingIndex);//关闭等待效果
if(result.success){
window.location.href="/DispatcherServlet?method=mainPage";
}else {
layer.msg("账号或者密码错误",{time:2000,icon:5,shift:6},function(){
});
}
}
});
});
});