1. 系统分层 (扩展)
(1)为什么要分层?(了解)
为了系统好维护,系统的设计应该要做到“高内聚,低耦合”。
“高内聚”:指的是类的职责要单一,这样,一个类就可以会拆分成多个类(比如AccountService拆分成了AccountService和AccountDAO),这样,就形成了分层的概念。
“低耦合”:指的是类与类之间不要直接依赖。(AccountService要调用AccountDAO,应该使用依赖注入)。
(2)如何分层?
表示层:数据展现和操作界面,以及请求分发。
业务层:封装了业务逻辑。
持久层: 封装了数据访问逻辑。
注:
表示层调用业务层,业务层调用持久层。
上一层通过接口来调用下一层提供的服务(这样,下一层的
实现发生了改变,不影响上一层)。
案例:
/netctoss-spring/src/main/java/cn/tedu/netctoss/controller/LoginController.java
package cn.tedu.netctoss.controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import cn.tedu.netctoss.entity.Admin;
import cn.tedu.netctoss.service.ApplicationException;
import cn.tedu.netctoss.service.LoginService;
@Controller
public class LoginController {
@Resource(name="loginService")
private LoginService loginService;
@RequestMapping("/toLogin.do")
public String toLogin(){
System.out.println("toLogin()");
return "login";
}
@RequestMapping("/login.do")
public String login(
HttpServletRequest request){
System.out.println("login()");
//读取帐号,密码
String adminCode =
request.getParameter(
"adminCode");
System.out.println("adminCode:"
+ adminCode);
String pwd =
request.getParameter("pwd");
//调用业务层提供的服务
try{
Admin admin =
loginService.checkLogin(
adminCode, pwd);
}catch(Exception e){
e.printStackTrace();
if(e instanceof ApplicationException){
//应用异常,明确提示用户
/*
* getMessage方法继承自
* RuntimeException,作用是
* 获得异常的描述信息。
*/
request.setAttribute(
"login_failed",
e.getMessage());
return "login";
}
//系统异常,提示用户稍后重试
return "error";
}
return "redirect:toIndex.do";
}
@RequestMapping("/toIndex.do")
public String toIndex(){
System.out.println("toIndex()");
return "index";
}
}
/netctoss-spring/src/main/java/cn/tedu/netctoss/dao
AdminDAO.java
package cn.tedu.netctoss.dao;
import cn.tedu.netctoss.entity.Admin;
/**
* 持久层接口
*/
public interface AdminDAO {
public Admin findByAdminCode(
String adminCode);
}
AdminDAOJdbcImpl.java
package cn.tedu.netctoss.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.stereotype.Repository;
import cn.tedu.netctoss.entity.Admin;
/**
* 持久层实现
*/
@Repository("adminDAO")
public class AdminDAOJdbcImpl implements
AdminDAO{
@Resource(name="ds")
private DataSource ds;
public Admin findByAdminCode(
String adminCode) {
Admin admin = null;
Connection conn = null;
try {
conn = ds.getConnection();
String sql =
"select * from admin_info_lhh "
+ "where admin_code=?";
PreparedStatement ps =
conn.prepareStatement(
sql);
ps.setString(1, adminCode);
ResultSet rs = ps.executeQuery();
if(rs.next()){
admin = new Admin();
admin.setAdminId(rs.getInt("admin_id"));
admin.setAdminCode(rs.getString("admin_code"));
admin.setPassword(rs.getString("password"));
admin.setName(rs.getString("name"));
admin.setTelephone(rs.getString("telephone"));
admin.setEmail(rs.getString("email"));
admin.setEnrolldate(rs.getTimestamp("enrolldate"));
}
} catch (SQLException e) {
//step1. 记日志(保留现场)
e.printStackTrace();
/*
* step2.看异常能否恢复,如果
* 不能够恢复(比如数据库服务
* 暂停,网络中断,这样的异常
* 一般我们称之为系统异常),
* 则提示用户稍后重试。如果能够
* 恢复,则立即恢复。
*
*/
throw new RuntimeException(e);
}finally{
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
return admin;
}
}
/netctoss-spring/src/main/java/cn/tedu/netctoss/entity/Admin.java
package cn.tedu.netctoss.entity;
import java.io.Serializable;
import java.sql.Timestamp;
public class Admin implements Serializable{
private Integer adminId;
private String adminCode;
private String password;
private String name;
private String telephone;
private String email;
private Timestamp enrolldate;
@Override
public String toString() {
return "Admin [adminId=" + adminId + ", adminCode=" + adminCode + ", password=" + password + ", name=" + name
+ ", telephone=" + telephone + ", email=" + email + ", enrolldate=" + enrolldate + "]";
}
public Integer getAdminId() {
return adminId;
}
public void setAdminId(Integer adminId) {
this.adminId = adminId;
}
public String getAdminCode() {
return adminCode;
}
public void setAdminCode(String adminCode) {
this.adminCode = adminCode;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Timestamp getEnrolldate() {
return enrolldate;
}
public void setEnrolldate(Timestamp enrolldate) {
this.enrolldate = enrolldate;
}
}
/netctoss-spring/src/main/java/cn/tedu/netctoss/service
ApplicationException.java
package cn.tedu.netctoss.service;
/**
* 应用异常类
*
*/
public class ApplicationException
extends RuntimeException {
public ApplicationException() {
}
public ApplicationException(
String message) {
super(message);
}
}
LoginService.java
package cn.tedu.netctoss.service;
import cn.tedu.netctoss.entity.Admin;
/**
* 业务层接口
*
*/
public interface LoginService {
public Admin checkLogin(String adminCode,
String pwd);
}
LoginServiceImpl.java
package cn.tedu.netctoss.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import cn.tedu.netctoss.dao.AdminDAO;
import cn.tedu.netctoss.entity.Admin;
/**
* 业务层实现
*
*/
@Service("loginService")
public class LoginServiceImpl implements
LoginService{
@Resource(name="adminDAO")
private AdminDAO aDAO;
public Admin checkLogin(
String adminCode, String pwd) {
Admin admin =
aDAO.findByAdminCode(adminCode);
if(admin == null){
//帐号不存在,抛一个应用异常。
//注:应用异常,指的是因为用户
//不正确的操作引起的异常,比如
//帐号、密码填写错误。需要明确
//提示用户采取正确的操作。
throw new ApplicationException(
"帐号错误");
}
if(!admin.getPassword().equals(pwd)){
//密码错误
throw new ApplicationException(
"密码错误");
}
//登录成功
return admin;
}
}
/netctoss-spring/src/main/resources
db.properties
# db connection parameters
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
user=
pwd=
# datasource parameters
initsize=1
maxsize=2
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<!-- 配置组件扫描 -->
<context:component-scan base-package="cn.tedu.netctoss" />
<!-- 配置MVC注解扫描 -->
<mvc:annotation-driven />
<!-- 配置视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 读取db.properties文件 -->
<util:properties id="db"
location="classpath:db.properties" />
<!-- 配置连接池 -->
<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="#{db.driver}" />
<property name="url" value="#{db.url}" />
<property name="username" value="#{db.user}" />
<property name="password" value="#{db.pwd}" />
</bean>
</beans>