第一次试着以规范的MVVC设计模式写了OA部分的功能。写完以后,对MVC这种著名的设计模式有了一些具体的理解和心得体会。
MVC百度百科如是说:
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
将模型(model)-视图(view)-控制器(controller)三层分离,实现层与层之间尽可能低的耦合性,利于框架的维护与扩展。牺牲了性能,换取了系统弹性。所谓系统弹性,就是怎么搞也搞不跨的性能。
在经典的J2EE中:
1.jsp在View层接收用户的操作,如提交表单等。收到请求后,调用controller层的servelt来处理这个request。
2.servelt调用业务逻辑层service中的方法来处理这个请求。
3.javabean则为封装了数据实体的对象,每实例化一个javabean,则可理解为创建了一个和数据库中表里一张数据对应的一个对象。在dao层中通过连接数据库,实现具体的数据访问操作,如连接、增、删、改、查等等。
4.在看过了网上的一些源码和别人写的一些DEMO后,在分包的时候,javabean所在的包名可以叫做 domain(域模型),entity(实体),bean。在过去搞安卓应用开发的时候,我多用entity,在J2EE中,现在看来,更适合于管理数据实体javabean的domain层。
关于MVC模式的项目中分包名的概述。
M:代表model,可以理解为javaBean;
V:代表view,可以理解为jsp;
c:代表controller,可以理解为action;
1.domain:这一层是用来管理javaBean实体对象的;
2.dao:数据访问层,对数据库进行访问;
3.service:业务逻辑层,通过调用dao层来对数据库进行访问;
4.web:数据显示层;
接下来,以最近写的OA系统为例,逐步分析这个最简单的DEMO中体现的MVC设计。
——————————————————————————————————————————————————————————————————————————
首先是工程包结构:
整个工程分为5块
1.controller:控制层,包含servelt,负责接收用户响应以及回复给用户结果视图。
2.dao:数据访问层。在dao层中首先定义了接口(UsersDao),并在其中分出impl包,实现dao中的接口,连接数据库,并实现基本的数据操作。在本OA系统中,即为用户是否可以成功登陆。
3.service业务逻辑层。在OA系统中,业务逻辑较为简单,就是登录。但在一些大型的如电商或是企业管理系统中,业务逻辑可能会比较复杂,如积分会员,获取详情等等。
4.domain域模型层,此层中包含对javabean实体对象的管理,在OA系统中,需要的实体对象只有一个(Users,请无视那个无关的Books)
5.util公用方法层,在OA系统中,我只写了连接数据库的相关操作。获取连接对象,增删改查,执行SQL语句等。还可以补充一个获取系统时间的util。
其他:那个Test层是开发调试过程中,用来测试数据库连接是否正常,增删改查是否成功执行等。
接下来看各层的类定义与实现。
首先是dao层。
UsersDao是一个接口,定义了数据访问中需要实现的方法。
package com.kyy.dao; import com.kyy.domain.Users; public interface UsersDao { public Boolean isLogin(Users user); }
UsersDaoImpl是这个接口的实现。
package com.kyy.dao.impl; import java.sql.SQLException; import com.kyy.dao.UsersDao; import com.kyy.domain.Users; import com.kyy.util.DBHelp; public class UsersDaoImpl implements UsersDao { @Override public Boolean isLogin(Users user) { // TODO Auto-generated method stub boolean ret=false; String sql="select * from users where name='%s' and pwd='%s'"; try { if(DBHelp.dbQuery(String.format(sql, user.getName(),user.getPwd())).next()) { ret=true; } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ret; } }
接着是业务逻辑service层。因为本OA系统中数据访问中的方法 是否能成功登陆与业务逻辑层中的是否能登陆一样,在业务逻辑层的接口实现中,只需要实例化一个Dao对象,并调用Dao层中方法即可。
UsersService.java
package com.kyy.service; import com.kyy.domain.Users; public interface UserService { public boolean isLogin(Users User); }
package com.kyy.service.impl; import com.kyy.dao.UsersDao; import com.kyy.dao.impl.UsersDaoImpl; import com.kyy.domain.Users; import com.kyy.service.UserService; public class UsersServiceImpl implements UserService{ UsersDao dao=new UsersDaoImpl(); @Override public boolean isLogin(Users User) { // TODO Auto-generated method stub return dao.isLogin(User); } }
最后是控制层controller
通过servelt接受用户的action,并转交给业务逻辑service层来处理
UsersAction.java
package com.kyy.controller; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; 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 com.kyy.domain.Users; import com.kyy.service.UserService; import com.kyy.service.impl.UsersServiceImpl; /** * Servlet implementation class MainMall */ public class UsersAction extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public UsersAction() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //response.getWriter().append("Served at: ").append(request.getContextPath()); //this.doPost(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); String name=request.getParameter("name"); String pwd=request.getParameter("pwd"); Users loginuser=new Users(); loginuser.setName(name); loginuser.setPwd(pwd); UserService service=new UsersServiceImpl(); PrintWriter out=response.getWriter(); if(service.isLogin(loginuser)) { //getServletContext().getRequestDispatcher("mainmall.jsp").forward(request, response); out.println("YES!"); }else { //getServletContext().getRequestDispatcher("index.jsp").forward(request, response); out.println("NO!"); } } }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>bookshop</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>UsersAction</servlet-name> <servlet-class>com.kyy.controller.UsersAction</servlet-class> </servlet> <!-- ... --> <servlet-mapping> <servlet-name>UsersAction</servlet-name> <url-pattern>/UsersAction.do</url-pattern> </servlet-mapping> </web-app>
DBHelp.java
package com.kyy.util; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import com.mysql.jdbc.Connection; import com.mysql.jdbc.Statement; public class DBHelp { private static final String DRIVER = "com.mysql.jdbc.Driver"; private static final String URL="jdbc:mysql://xx.xx.xx.xxx:xxxx/xxxxxxxxx"; private static final String PASSWORD="xxxxxxxxxx"; private static final String USER="xxxx"; public static Connection getConnection() { Connection conn = null; try { Class.forName(DRIVER); // 加载数据库驱动 if (null == conn) { conn = (Connection) DriverManager.getConnection(URL, USER, PASSWORD); } } catch (ClassNotFoundException e) { System.out.println("Sorry,can't find the Driver!"); e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return conn; } public static int executeNonQuery(String sql) { int result = 0; Connection conn = null; Statement stmt = null; try { conn = getConnection(); stmt = (Statement) conn.createStatement(); result = stmt.executeUpdate(sql); } catch (SQLException err) { err.printStackTrace(); free(null, stmt, conn); } finally { free(null, stmt, conn); } return result; } public static ResultSet dbQuery(String sql) { Connection conn = null; Statement stmt = null; ResultSet rs=null; try { conn = getConnection(); stmt = (Statement) conn.createStatement(); rs = stmt.executeQuery(sql); } catch (SQLException sqlex) { System.out.println("数据库查询异常:"); sqlex.printStackTrace(); free(null,stmt,conn); } return rs; } public static int dbUpdate(String sql) { Connection conn = null; Statement stmt = null; int rs=0; try { conn = getConnection(); stmt = (Statement) conn.createStatement(); //System.out.println("更新语句..."+sql); rs = stmt.executeUpdate(sql); } catch (SQLException sqlex) { System.out.println("数据库更新异常:"); sqlex.printStackTrace(); free(null,stmt,conn); }finally { free(null,stmt,conn); } return rs; } public static void free(ResultSet rs) { try { if (rs != null) { rs.close(); } } catch (SQLException err) { err.printStackTrace(); } } public static void free(Statement st) { try { if (st != null) { st.close(); } } catch (SQLException err) { err.printStackTrace(); } } public static void free(Connection conn) { try { if (conn != null) { conn.close(); } } catch (SQLException err) { err.printStackTrace(); } } public static void free(ResultSet rs, Statement stmt, Connection conn) { free(rs); free(stmt); free(conn); } }
最后是负责用户界面view的jsp视图
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>bookshop</title> </head> <body> <form action="UsersAction.do" method="post"> <p>用户名: <input type="text" name="name" /></p> <p>密码: <input type="text" name="pwd" /></p> <input type="submit" value="Submit" /> </form> </body> </html>
数据库中的表信息如下
运行结果如下
当输入正确的用户名和密码时
结果如下
当输入错误的用户名和密码时
结果
最后用C#写的HTTP测试工具测试一下
可以看到 Body里的Yes
此外,我并没有重写servelt里的doget方法,所以,直接通过访问网页,执行get请求时无任何返回。
至此,整个OA模块的功能都被打通了。以此文为记,作为从Android移动端转向J2EE WEB开发的新起点。
(要是明年能给宝宝个开发岗的实习就好了~~~~~~)