三层架构模式有别于之前所体到的MVC模式,主要的区别在于C(控制器)进行的M(模型)和V(视图)转交数据操作改变为视图面向服务端操作,服务端数据请求Dao资源包操作,Dao进行访问数据库。实现具体的小应用请点击详情页。
小Demo具体实现了页面对数据库中信息的增删改查操作,运用三层架构进行设计,优化封装了数据层面的冗余信息,这里跟着代码进一步了解简单的实现过程。
首先在webContent的WEB-INF中创建用于登录的index.jsp文件,在body中写入:
<table border="1px">
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>地址</th>
</tr>
<%
//获取request中的数据
List<Student> students = (List<Student>)request.getAttribute("students")
for(Student student:students){
%>
<tr>
<td><a href="QueryStudentBySnoServlet?sno=<%=student.getSno() %>"><%=student.getSno() %></a> </td>
<td><%=student.getSname() %></td>
<td><%=student.getSage() %></td>
<td> <a href="DeleteStudentServlet?sno=<%=student.getSno() %> ">删除</a> </td>
</tr>
<%
}
%>
</table>
字段主要实现了显示信息为:学号,姓名,年龄,地址的页面框体。
再者,由于我们操作的对象是人物,我们可以建立一个基于人物的java文件,我主要写的是Student对象,对数据封装实现其中的set和get方法以及有无实参的构造函数,以待调用:
public class Student {
private int sno;
private String sname;
private int sage;
private String saddress;
public Student() {
}
public Student( String sname, int sage, String saddress) {
this.sname = sname;
this.sage = sage;
this.saddress = saddress;
}
public Student(int sno, String sname, int sage, String saddress) {
this.sno = sno;
this.sname = sname;
this.sage = sage;
this.saddress = saddress;
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getSage() {
return sage;
}
public void setSage(int sage) {
this.sage = sage;
}
public String getSaddress() {
return saddress;
}
public void setSaddress(String saddress) {
this.saddress = saddress;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getSno()+"-"+this.getSname()+"-"+this.getSage()+"-"+this.getSaddress();
}
}
其中的同toString方法主要是对toString的重写操作,便于直接输出我们想要的结果。
有人对象也有了页面的显示信息,我们下一步要做的就是连接数据库实现Dao包的对数据的增删改查操作,由于我们是对Demo的三层架构操作,我们应当独一的实现各类操作,然后再在需要的时候调用其中的一个乃至几个操作进行数据操作的封装,类似于我们要增加一个人,就要去先判断这个人是否存在,如果存在则不需要加入,如果不存在就再调用增函数实现数据的增加,然后加入数据库。由此可见,如果我们不进行底层的每一步的封装,那么在操作具体实现的时候就会产生更多的代码冗余。我们再创建具体的包,包名记为Servlet,具体先实现的代码为:
首先是实现数据库的基本操作:
//数据访问层是原子性的增删改查
public class StudentDao {
public String URL = "jdbc:mysql://localhost:3306/db_stu";
public String USERNAME = "root";
public String PASSWORD = "xxxx";
//判断学生存在与否
public boolean isExist(int sno) {
return queryStudentBySno(sno)==null?false:true;
}
//增加学生
public boolean addStudent(Student student) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL,USERNAME,PASSWORD);
String sql = "insert into student(sno,sname,sage,saddress) values(?,?,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, student.getSno());
pstmt.setString(2, student.getSname());
pstmt.setInt(3, student.getSage());
pstmt.setString(4, student.getSaddress());
int count = pstmt.executeUpdate(sql);
if(count > 0) {
return true;
}else {
return false;
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
try {
if(pstmt!=null) pstmt.close();
if(conn!=null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//删除一个学生
public boolean deleteStudentBySno(int Sno) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL,USERNAME,PASSWORD);
String sql = "delete from student where sno=?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, Sno);
int count = pstmt.executeUpdate(sql);
if(count > 0) {
return true;
}else {
return false;
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
try {
if(pstmt!=null) pstmt.close();
if(conn!=null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//改学生信息,根据Sno改成student的信息
public boolean updateStudentBySno(int Sno,Student student) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL,USERNAME,PASSWORD);
String sql = "update student set sname=?,sage=?,saddress=? where sno=?";
pstmt = conn.prepareStatement(sql);
//修改后的样子
pstmt.setString(1, student.getSname());
pstmt.setInt(2, student.getSage());
pstmt.setString(3, student.getSaddress());
pstmt.setInt(4, Sno);//修改的人
int count = pstmt.executeUpdate(sql);
if(count > 0) {
return true;
}else {
return false;
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
try {
if(pstmt!=null) pstmt.close();
if(conn!=null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//查询全部学生
public List<Student> queryAllStudent() {
List<Student> students = new ArrayList<>();
Student student = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL,USERNAME,PASSWORD);
String sql = "selecrt * from student";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()) {
int no = rs.getInt("sno");
String name = rs.getString("sname");
int age = rs.getInt("sage");
String address = rs.getString("saddress");
student = new Student(no,name, age, address);
students.add(student);
}
return students;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}finally {
try {
if(rs!=null) rs.close();
if(pstmt!=null) pstmt.close();
if(conn!=null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//根据学号查学生
public Student queryStudentBySno(int Sno) {
Student student = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL,USERNAME,PASSWORD);
String sql = "selecrt * from student where sno=?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, Sno);
rs = pstmt.executeQuery();
if(rs.next()) {
int no = rs.getInt("sno");
String name = rs.getString("sname");
int age = rs.getInt("sage");
String address = rs.getString("saddress");
student = new Student(no,name, age, address);
}
return student;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}finally {
try {
if(rs!=null) rs.close();
if(pstmt!=null) pstmt.close();
if(conn!=null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
因此我们要实现具体的操作,也就是业务逻辑性的增删改查,对Dao的组装,我们将这以操作创建名为service包中,里面的具体操作是根据我们的:
public class StudentService {
StudentDao studentDao = new StudentDao();
//根据学号查一个人
public Student queryStudentBySno(int sno) {
return studentDao.queryStudentBySno(sno);
}
//查询全部学生
public List<Student> queryAllStudents() {
return studentDao.queryAllStudent();
}
public boolean deleteStudentBySno(int sno) {
if(studentDao.isExist(sno)) {
return studentDao.deleteStudentBySno(sno);
}else {
return false;
}
}
public boolean updateStudentBySno(int sno,Student student) {
if(studentDao.isExist(sno)) {
return studentDao.updateStudentBySno(sno, student);
}else {
return false;
}
}
public boolean addStudent(Student student) {
//不存在就添加
if(!studentDao.isExist(student.getSno())) {
studentDao.addStudent(student);
return true;
}else {
System.out.println("此人已经存在");
return false;
}
}
}
再者,根据我们以及实现的代码的进行对页面数据的操作:
首先是增加数据的servlet封装:
public class AddStudentServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
int no = Integer.parseInt(request.getParameter("sno"));
String name = request.getParameter("sname");
int age = Integer.parseInt(request.getParameter("sage"));
String address = request.getParameter("saddress");
Student student = new Student(no,name,age,address);
//数据的拼接
StudentService studentService = new StudentService();
boolean result = studentService.addStudent(student);
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
if(result) {
out.println("增加成功!");
}else {
out.println("增减失败!");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
再者是删除数据的封装:
public class DeleteStudentServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//删除的功能
request.setCharacterEncoding("utf-8");
//接收前端传来的学号
int no = Integer.parseInt(request.getParameter("sno"));
StudentService service = new StudentService();
boolean result = service.deleteStudentBySno(no);
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("utf-8");
if(result) {
//response.getWriter().println("删除成功!");
response.sendRedirect("QueryAllStudentServlrt");
}else {
response.getWriter().println("删除失败!");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
更新数据的封装:
public class UpdateStudentServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//获取待修改人的学号
int no = Integer.parseInt(request.getParameter("sno"));
//获取修改的内容
String name = request.getParameter("sname");
int age = Integer.parseInt(request.getParameter("sage"));
String address = request.getParameter("saddress");
//将修改后的内容封装到JavaBean中
Student student = new Student(name, age, address);
StudentService service = new StudentService();
boolean result = service.updateStudentBySno(no, student);
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
if(result) {
out.println("修改成功!");
}else {
out.println("修改失败!");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
根据学号查询学生信息:
public class QueryStudentBySnoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
int no = Integer.parseInt(request.getParameter("sno"));
StudentService service = new StudentService();
Student student = service.queryStudentBySno(no);
System.out.println(student);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
查询所有信息:
public class QueryAllStudentServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
StudentService service = new StudentService();
List<Student> students = service.queryAllStudents();
System.out.println(students);
request.setAttribute("students", students);
//通过请求转发方式跳转
request.getRequestDispatcher("index.jsp").forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
由于Dao包中有着大量冗余的代码,例如我们申请数据库,或者关闭数据库的一些操作,现在这些都可以进行封装成一个类专门调用。我们把这个封装的数据库操作记为Util包,代码实现如下:
//通用的数据操作方法
public class DBUtil {
private static final String URL = "jdbc:mysql://localhost:3306/db_stu";
private static final String USERNAME = "root";
private static final String PASSWORD = "xxxx";
public static PreparedStatement pstmt = null ;
public static Connection connection = null ;
public static ResultSet rs = null ;
//通用的增删改
public static boolean executeUpdate(String sql,Object[] params) {//{"zs",1}
try {
Object[] obs = { name,age ,...,x} ;
String sql = "delete from xxx where Name = ? or id = ? " ;
pstmt.setInt(1,sno );
setXxx()方法的个数 依赖于 ?的个数, 而?的个数 又和 数组params的个数一致
setXxx()方法的个数 ->数组params的个数一致
pstmt = createPreParedStatement(sql,params);
int count = pstmt.executeUpdate() ;
if(count>0)
return true ;
else
return false ;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false ;
} catch (SQLException e) {
e.printStackTrace();
return false ;
}catch (Exception e) {
e.printStackTrace();
return false ;
}
finally {
closeAll(null,pstmt,connection);
}
}
//Statement
public static void closeAll(ResultSet rs,Statement stmt,Connection connection)
{
try {
if(rs!=null)rs.close();
if(pstmt!=null)pstmt.close();
if(connection!=null)connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws ClassNotFoundException, SQLException {
Class.forName("jdbc:mysql://localhost:3306/db_stu") ;
return DriverManager.getConnection( URL,USERNAME,PASSWORD ) ;
}
public static PreparedStatement createPreParedStatement(String sql,Object[] params) throws ClassNotFoundException, SQLException {
pstmt = getConnection() .prepareStatement( sql) ;
if(params!=null ) {
for(int i=0;i<params.length;i++) {
pstmt.setObject(i+1, params[i]);
}
}
return pstmt;
}
//通用的查 :通用 表示 适合与 任何查询
public static ResultSet executeQuery( String sql ,Object[] params) {//select xxx from xx where name=? or id=?
Student student = null;
List<Student> students = new ArrayList<>();
try {
// String sql = "select * from student" ;//select enmae ,job from xxxx where...id>3
pstmt = createPreParedStatement(sql,params);
rs = pstmt.executeQuery() ;
return rs ;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null ;
} catch (SQLException e) {
e.printStackTrace();
return null ;
}catch (Exception e) {
e.printStackTrace();
return null ;
}
// finally {
// try {
// if(rs!=null)rs.close();
// if(pstmt!=null)pstmt.close();
// if(connection!=null)connection.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
}
}
鉴于此我们简单的实现了对数据的操作,这是再学习Servlet和JSP中跟着实践写的代码,教程源于lanqiao,通过自己的理解和些许天的学习,在Web上有了丝丝见解,而且基本能够读懂相应的代码。也许这就是学习的乐趣所在吧,能够自己见证自己的成长,确实挺好。