在之前已经写过了jdbc的工具类,不过最近学习了新的方法,所以在这里重新写一遍,为后面的javaEE做铺垫;
首先我们要了解javaEE项目中,文件构成,新建一个javaEE项目,在项目中,有一个web文件夹,在web文件夹下有WEB-INF文件夹,我们的web.xml文件放在这个文件夹下,同时我们要新建两个文件夹,一个是classes文件夹,一个lib文件夹;
classes文件夹:我们做出来的程序,都是先编译成class文件,然后再jvm中运行class文件,所以运行时,并不需要java‘文件,因此要把编译好的class文件放在classes文件夹下,然后直接将web文件夹放在tomcat的webapps文件夹下就可以运行了。
这里写一下怎样将class文件放入classes文件夹:
我们先建四个包:
然后以建一个student表:
我们一这个表为基础,来模拟一次业务;
首先在entity中创建student表的实例化对象类Student:
package com.zs.entity;
/**
* 创建实例化是对象类Student
* 生成get和set方法,
* 空参及带参构造方法
* tostring方法*/
public class Student {
// 1定义成员变量
private int id;
private String sname;
private int age; public Student() {
super();
} public Student(int id, String sname, int age) {
this.id = id;
this.sname = sname;
this.age = age;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getSname() {
return sname;
} public void setSname(String sname) {
this.sname = sname;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Student{" +
"id=" + id +
", sname='" + sname + '\'' +
", age=" + age +
'}';
}
}
然后我们在util包创建jdbc的工具类:
package com.zs.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*; /**
* 1.导jar包,需要用到druid-1.0.9.jar,
* mysql-connector-java-5.1.45-bin.jar,
* servlet-api.jar
* 需要用到阿里的连接池,所以需要配置文件,配置文件放在src文件夹下,配置文件的内容之前有介绍
*/ public class DBUtils {
private static DataSource ds;
// 1.创建静态代码块读druid.properites配置文件,创建链接池
static {
Properties p = new Properties();
InputStream in = DBUtils.class.getClassLoader().getResourceAsStream("druid.properties");
try {
p.load(in);
ds = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
} // 2.创建获得连接对象的静态方法
public static Connection getConnection() throws SQLException {
return ds.getConnection();
} // 3.创建增删改的方法,并返回布尔类型,使用可变参数来传递占位符的值
public static boolean executeUpdate(String sql,Object... args){
Connection conn = null;
PreparedStatement ps = null;
try {
conn= getConnection();
ps = conn.prepareStatement(sql);
// 通过for循环来给占位符赋值
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
// 执行sql语句
int i = ps.executeUpdate();
return i>0;
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(conn,ps);
}
return false;
} // 创建查询的方法,并返回list集合
public static List<Map<String, Object>> executeQuery(String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn=getConnection();
ps = conn.prepareStatement(sql);
// 遍历可变数组传递占位符值
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
rs = ps.executeQuery();
List<Map<String,Object>> list=new ArrayList<>();
while (rs.next()) {
Map<String, Object> map = new LinkedHashMap<>();
/**这里可能会有问题,为什么是String,Object类型,因为我们通过rs.next只能获得一行结果,这一行结果,我们如果直接存入集合中的的化就是一个一个的值
* 我们无法识别哪儿个值是那儿一列的,所以用想到用map集合来装结果,key为列名,所以用String,因为一行中有多种数据类型,所以用obj来保存,用linkedHashMap
* 是因为map集合出来的结果是无序的,所以用linkedHashMap是有序的*/
// rs.getMetaData().getColumnCount();方法获得当前结果集的列数
for (int i = 0; i <rs.getMetaData().getColumnCount(); i++) {
// 通过列的索引获得列名,i+1是因为没有第0列,从第一列开始
String key = rs.getMetaData().getColumnLabel(i + 1);
// 通过键名来获得值
Object value = rs.getObject(key);
map.put(key, value);
}
list.add(map);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(conn,ps,rs);
}
return null;
}
// 创建关闭流的方法
private static void close(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 重载
private static void close(Connection conn, PreparedStatement ps) {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(conn);
}
}
}
// 重载
private static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(conn,ps);
}
}
}
}
然后我们写dao层的类:
package com.zs.dao; import com.zs.entity.Student; import java.util.List;
import java.util.Map; /**我们首先在dao层下面创建接口,因为我们需要一个多态的特征,所以在接口中写抽象方法,方便后期的修改和维护
* 为什么要用多态,为了程序解耦,接触程序的耦合性,在创建后期修改时,如果我们要修改某一个方法,那就看可能会导致其他的方法不能运行,
* 程序之间的联系就是耦合性,就像藕断丝连,越是复杂的程序,之间的联系就越多,而多态就是为了解耦*/
public interface IStudentDAO {
/**
* 在这里我们传递的参数为Student 对象
* 为什么要用student对象?
* 因为在实际开发中,我们的表中的数据可能有很多列,我们不能把所有的列都当参数来传递,那样太麻烦了,而且不方便后期的修改和维护和,
* 比如说,我们突然要删除一列,那么我们就要找到所有于该方法有关的方法,删除参数列表中相应的参数,这样太麻烦了,传递对象,我们通过get方法来获得参数*/
boolean add(Student s);
boolean upd(Student s);
boolean del(int id);
List<Map<String,Object>> getStudentById(int id);
List<Map<String,Object>> getAllStudent(); }
package com.zs.dao.impl;
/**
* 在创建完接口后,我们在dao层的下面新建一个impl文件夹,用来存放接口的实现类*/
import com.zs.dao.IStudentDAO;
import com.zs.entity.Student;
import com.zs.util.DBUtils; import java.util.List;
import java.util.Map; public class StudentImpl implements IStudentDAO {
@Override
public boolean add(Student s) {
String sql="insert into student(sname,age) value (?,?)";
// 通过get方法来传递占位符的值
return DBUtils.executeUpdate(sql, s.getSname(), s.getAge());
} @Override
public boolean upd(Student s) {
String sql = "update student set sname=? ,age=? where id=?";
return DBUtils.executeUpdate(sql, s.getSname(), s.getAge(), s.getId());
} @Override
public boolean del(int id) {
String sql = "delete from student where id=?";
return DBUtils.executeUpdate(sql, id);
} @Override
public List<Map<String, Object>> getStudentById(int id) {
String sql = "select * from student where id=?";
return DBUtils.executeQuery(sql, id);
} @Override
public List<Map<String, Object>> getAllStudent() {
String sql = "select * from student";
return DBUtils.executeQuery(sql);
}
}
然后我们在servlet包中建测试类来测试工具类:
package com.zs.servlet; import com.zs.dao.IStudentDAO;
import com.zs.dao.impl.StudentImpl;
import com.zs.entity.Student;
import com.zs.util.DBUtils;
import org.junit.Test; import java.util.List;
import java.util.Map; public class StudentServlet {
IStudentDAO is=new StudentImpl();
@Test
public void add(){
Student stu = new Student(1, "张三", 20);
// 这里这个 1 可能会有疑问,可以看一下dao层,我们插入语句中并没有用导id;写1是为了使用带参构造
boolean b = is.add(stu);
if (b) {
System.out.println("插入成功");
} else {
System.out.println("插入失败");
}
}
@Test
public void upd(){
Student stu = new Student(1, "张三", 20);
boolean b = is.upd(stu);
if (b) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
}
@Test
public void del(){
boolean b = is.del(1);
if (b) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
}
@Test
public void sel(){
List<Map<String, Object>> list = is.getStudentById(2);
if (list.size() > 0) {
System.out.println(list);
} else {
System.out.println("该学生不存在");
}
}
@Test
public void selAll(){
List<Map<String, Object>> list = is.getAllStudent();
System.out.println(list);
}
}
上面完成后,我们下面写一个页面,完成简单的表单验证,点击提交后,数据提交到后台,然后后台调用dao层,数据对比:
首先创建一个login表:
然后我们在dao层中创建ilogin接口:
package com.zs.dao; public interface ILoginDAO {
boolean login(String username, String password);
}
然后在impl文件夹中创建实现类:
package com.zs.dao.impl; import com.zs.dao.ILoginDAO;
import com.zs.util.DBUtils; import java.util.List;
import java.util.Map; public class LoginImpl implements ILoginDAO { @Override
public boolean login(String username, String password) {
String sql = "select * from login where sname=? and pwd=?";
List<Map<String, Object>> list = DBUtils.executeQuery(sql, username, password);
return list.size()>0;
}
}
然后我们写一个简单的html页面,html页面放在web文件夹下;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录界面</title>
</head>
<body>
<form action="/zs/login" method="post">
<input type="text" name="username" placeholder="请输入用户名"><br>
<input type="password" name="password" placeholder="请输入密码"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
下面写登陆的后台Servlet:
package com.zs.servlet; import com.zs.dao.ILoginDAO;
import com.zs.dao.impl.LoginImpl; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet(name = "LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 将请求的数据转为utf-8的格式,没有这句话的话,会出现登录中文用户名失败
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
ILoginDAO lo=new LoginImpl();
boolean b = lo.login(username, password);
if (b) {
System.out.println("登录成功");
// 成功跳转页面方法与下面一样,这里没有写可以跳转的页面
} else {
System.out.println("登陆失败");
// 失败返回登录页面
response.sendRedirect("Login.html");
}
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
配置tomcat的方法再之前写过,然后直接启动tomcat就好了