1、系统为什么要分层?
希望专人肝专事,各司其职。职能分工要明确。这样可以让代码耦合性降低,拓展力增强,组件的可复用性增强。
2、软件的架构中,有一个非常著名的架构模式:MVC架构吗模式
M(Model:数据/业务) V(view:视图/展示) C(controller:控制器)
C(是核心,是控制器,是司令官)
M(处理业务/处理数据的一个秘书)
V(负责页面展示的秘书)
MVC:一个司令官调度两个秘书去做一件事
3、javaEE设计模式之DAO模式
什么是DAO模式?
Data Access Object(数据访问对象)
b.DAO实际上的一种设计模式,属于javaEE的设计模式之一(不是23种设计模式)
c.DAO只是负责数据库表的CRUD,没有任何业务逻辑在里面
d.没有任何业务逻辑,只负责表中数据增删改查的对象,称DAO对象
e.为什么什么这里起名叫AccountDao呢?
这里因为这个DAO是专门处理act这张表的
如果处理user这张表的话,可以叫做:UserDao
如果处理student这张表的话,可以叫做StudentDao
f.一般情况下:一张表对应一个DAO对象
g.DAO中的方法名很固定了,一般都是
insert
deleteByXXX
Update
selectByXXX
selectAll
例:
public class AccountDao {
/**
* 插入账户信息
* @param act 账户信息
* @retuen 1_表示插入成功
*/
public int insert(Account act){
Connection conn=null;
PreparedStatement ps=null;
int count=0;
try {
conn= DBUtil.getConnection();
String sql="insert into mvc(username,money) values (?,?,?)";
ps=conn.prepareStatement(sql);
ps.setString(1,act.getName());
ps.setInt(2,act.getMomay());
count=ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(conn,ps,null);
}
return count;
}
/**
* 根据主键删除
* @param id 主键
* @returm 1-表示删除成功
*/
public int deleteById(int id){
Connection conn=null;
PreparedStatement ps=null;
int count=0;
try {
conn=DBUtil.getConnection();
String sql="delete from mvc where id = ?";
ps=conn.prepareStatement(sql);
ps.setInt(1,id);
count=ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(conn,ps,null);
}
return count;
}
/**
*更新账户
* @param art
* @returm 1-修改成功
*/
public int update(Account art){
Connection conn=null;
PreparedStatement ps=null;
int count=0;
try {
conn=DBUtil.getConnection();
String sql="update mvc set money = ?,name = ? where id = ? ";
ps=conn.prepareStatement(sql);
ps.setInt(1,art.getMomay());
ps.setString(2,art.getName());
ps.setInt(3,art.getId());
count=ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(conn,ps,null);
}
return count;
}
/**
* 根据账号差账户
* @param name name
* @returm Account
*/
public Account selectByName(String name){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
Account account = null;
try {
conn=DBUtil.getConnection();
String sql="select id,name,money from mvc where name like ?";
ps=conn.prepareStatement(sql);
ps.setString(1,name);
rs= ps.executeQuery();
if(rs.next()){
account=new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMomay(rs.getInt("money"));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(conn,ps,rs);
}
return account;
}
/**
* 所有数据
*
*/
public List<Account> selectAll(){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
List<Account> list= new ArrayList<>();
try {
conn=DBUtil.getConnection();
String sql="select id,name,money from mvc ";
ps=conn.prepareStatement(sql);
rs= ps.executeQuery();
while (rs.next()){
int id=rs.getInt("id");
String name=rs.getString("name");
int money=rs.getInt("money");
Account account=new Account();
account.setId(id);
account.setName(name);
account.setMomay(money);
list.add(account);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(conn,ps,rs);
}
return list;
}
}
4、pojo bean domain的概念
账户实体类,一般一张表一个
pojo对象
有人也会把这种专门封装数据的对象称为bean,即:JavaBean
也有人沉稳给领域模型对象
public class Account {
//一般这种属性不建议设计为基本数据类型,建议使用包装类,防止赋空值时出错
private Integer id;
private String name;
private Integer momay;
public Account() {
}
public Account(int id, String name, Integer momay) {
this.id = id;
this.name = name;
this.momay = momay;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getMomay() {
return momay;
}
public void setMomay(Integer momay) {
this.momay = momay;
}
}
5、service翻译为业务
AccountService:专门处理Account业务的一个类在该类中应该编写纯业务代码,(只专注业务,不写别的,不和其他代码混合在一起)
只希望专注业务,能将业务实现,少量bug
业务名一般是:XXXService,XXXBiz
public class AccountService {
AccountDao accountDao=new AccountDao();
/**
* 完成转账逻辑
* @param fromName 转出账户
* @param toName 转入账户
* @param money 金额
*/
public void transfer(String fromName,String toName,int money) throws MoneyNotEnoughException, AppException {
Connection conn= null;
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
Account fromAct=accountDao.selectByName(fromName);
if(fromAct.getMomay()<money){
throw new MoneyNotEnoughException("对不起,余额不足");
}
Account toAct =accountDao.selectByName(toName);
fromAct.setMomay(fromAct.getMomay()-money);
toAct.setMomay(toAct.getMomay()+money);
int count=accountDao.update(fromAct);
count+= accountDao.update(toAct);
if(count!=2){
throw new AppException("对不起服务器异常");
}
conn.commit();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
6、三层架构
7、ThreadLocadl
本质就是一个Map集合<Thread,Object>
key | Value |
t1 | conn |
t2 | conn |
public class DBUtil {
private static ResourceBundle bundle= ResourceBundle.getBundle("resource.Jdbc");
private static String driver=bundle.getString("driver");
private static String url=bundle.getString("url");
private static String user=bundle.getString("user");
private static String password=bundle.getString("password");
//不让创建对象,因为工具类中的方法都是静态的,不要创建对象
//为了防止创建对象,故将构造方法私有化
private DBUtil(){}
//静态代码块
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private static ThreadLocal<Connection> local =new ThreadLocal<>();
/**
* 这里没有使用数据库连接池,直接创建对象
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
Connection conn=local.get();
if(conn==null) {
conn = DriverManager.getConnection(url, user, password);
local.set(conn);
}
return conn;
}
//关闭接口
/**
* 关闭资源
* @param conn
* @param ps
* @param rs
*/
public static void close(Connection conn, Statement ps, ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (ps!=null){
try {
ps.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if(conn!=null){
try {
conn.close();
local.remove();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
8、servlet
充当司令官只调度系统
@WebServlet("/Account")
public class AccountServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fromname =request.getParameter("fromname");
String toname=request.getParameter("toname");
int money = Integer.parseInt(request.getParameter("money"));
AccountService accountService=new AccountService();
try {
accountService.transfer(fromname,toname,money);
response.sendRedirect(request.getContextPath()+"/success.jsp");
} catch (AppException e) {
response.sendRedirect(request.getContextPath()+"/error.jsp");
} catch (MoneyNotEnoughException e) {
response.sendRedirect(request.getContextPath()+"/moneynotenough.jsp");
}
}
}
前端代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
<title>$Title$</title>
</head>
<body>
<form action="Account" method="post">
转账账户:<input type="text" name="fromname"><br>
被转账账户:<input type="text" name="toname"><br>
金额:<input type="text" name="money"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
项目缺陷:
在service层控制了事物,service方法种事物控制代码看着有点别扭,可以用动态处理机制
目前虽然目前接口编程了,但是并没有完全解决对象和对象间的依赖,可以用Spring的Ioc解决