後端開發基礎-SpringMVC框架學習-008——基礎概念
阿新 • • 發佈:2018-12-13
系統分層(瞭解)
為什麼要分層
為了方便系統的維護,方便系統的 效能調優,方便測試,方便分工協作。
如何分層
表示層:資料的展現和使用者操作介面。 業務層:業務邏輯的處理。 持久層:資料訪問邏輯。 . 表示層呼叫業務層,業務層呼叫持久層。 . 下一層為上一層提供某種服務。 . 上一層通過介面呼叫下一層提供的服務。
表單中文引數值的亂碼問題
step1. 確保表單按照post方式提交。 step2. 配置spring提供的 CharacterEncodingFilter過濾器。 step3. 確保頁面編碼與過濾器配置的編碼一致。
練習: 完成資費列表。http://ip:port/springcase-netctoss/cost.do
案例演示:
工程案例目錄結構
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.study</groupId> <artifactId>springcase-netctoss</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc14</artifactId> <version>10.2.0.4.0</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>3.2.8.RELEASE</version> </dependency> </dependencies> </project>
匯入Tomcat類庫
web.xml
<?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_2_5.xsd" version="2.5"> <display-name>springcase-netctoss</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> <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:app.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
app.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="com.dk.oss"/>
<!-- 配置mvc註解掃描 -->
<mvc:annotation-driven/>
<!--
配置檢視解析器:
負責將檢視名解析成真正的檢視物件(比如jsp)。
-->
<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="jdbc" location="classpath:db.properties" />
<!-- 配置DataSource -->
<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="#{jdbc.driverclass}" />
<property name="url" value="#{jdbc.url}" />
<property name="username" value="#{jdbc.user}" />
<property name="password" value="#{jdbc.password}" />
<property name="maxActive" value="#{jdbc.maxActive}" />
</bean>
</beans>
db.properties
driverclass=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:orcl
user=learn
password=learn
maxActive=1
initSize=1
LoginController.java
package com.dk.oss.controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.dk.oss.entity.Admin;
import com.dk.oss.service.AdminService;
import com.dk.oss.service.AppException;
@Controller
public class LoginController {
@Resource(name="adminService")
private AdminService adminService;
@RequestMapping("/toLogin.do")
public String toLogin(){
return "login";
}
@RequestMapping("/login.do")
public String checkLogin(HttpServletRequest request){
//讀取請求引數值
String adminCode = request.getParameter("adminCode");
String pwd = request.getParameter("pwd");
System.out.println("adminCode:"+adminCode+" pwd:"+pwd);
//呼叫業務層模組來進行登入處理。
try{
Admin admin= adminService.checkLogin(adminCode, pwd);
System.out.println(admin);//Integer.valueOf("a");
}catch(Exception e){
if(e instanceof AppException){
//應用異常,需要明確提示使用者。
request.setAttribute("errorMsg", e.getMessage());
System.out.println("自定義異常。。。");
//轉發到登入頁面。
return "login";
}else{
//系統異常,提示使用者稍後重試。
System.out.println("系統異常。。。"+e.getMessage());
return "error";
}
}
//登入成功,重定向到首頁。
return "redirect:index.do";
}
@RequestMapping("/index.do")
public String toIndex(){
return "index";
}
}
AdminService.java
package com.dk.oss.service;
import com.dk.oss.entity.Admin;
/**
* 業務層介面
*
* @author Cher_du
*
*/
public interface AdminService {
//用於登入處理
public Admin checkLogin(String code,String pwd);
}
AdminServiceImpl.java
package com.dk.oss.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.dk.oss.dao.AdminDAO;
import com.dk.oss.entity.Admin;
/**
* 業務層實現
* @author Cher_du
*
*/
@Service("adminService")
public class AdminServiceImpl implements AdminService{
@Resource(name="adminDAO")
private AdminDAO adminDAO;
public Admin checkLogin(String code, String pwd) {
//呼叫AdminDAO訪問資料庫
Admin admin = adminDAO.findByCode(code);
if(admin == null){
//賬戶不存在,需要提示使用者。
//丟擲一個應用異常(使用者在使用系統
//的過程當中,做了一些錯誤的操作,比如
//輸出入錯誤的賬戶或密碼)。
throw new AppException("賬戶錯誤");
}
if(!admin.getPassword().equals(pwd)){
//密碼錯誤,需要提示使用者。
throw new AppException("密碼錯誤");
}
//登入成功
return admin;
}
}
AppException.java
package com.dk.oss.service;
/**
* 應用異常類。
* @author Cher_du
*
*/
public class AppException extends RuntimeException {
public AppException() {
}
public AppException(String message) {
super(message);
}
}
AdminDAO.java
package com.dk.oss.dao;
import com.dk.oss.entity.Admin;
/**
* DAO介面
* 注:
* 任何介面,都不要涉及任何具體的實現。
* @author Cher_du
*
*/
public interface AdminDAO {
public Admin findByCode(String code);
}
AdminDAOJdbcImpl.java
package com.dk.oss.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 com.dk.oss.entity.Admin;
/**
* DAO實現類
* @author Cher_du
* @Resource預設按照名稱方式進行bean匹配,@Autowired預設按照型別方式進行bean匹配
*/
@Repository("adminDAO")
public class AdminDAOJdbcImpl implements AdminDAO{
//注入datasource。
@Resource(name="ds")
private DataSource ds;
public Admin findByCode(String code) {
Admin admin = null;
Connection conn = null;
PreparedStatement prep = null;
ResultSet rst = null;
try {
conn = ds.getConnection();
String sql = "SELECT * FROM admin_info "
+"WHERE admin_code=?";
prep = conn.prepareStatement(sql);
prep.setString(1, code);
rst = prep.executeQuery();
if(rst.next()){
admin = new Admin();
admin.setAdminId(rst.getInt("admin_id"));
admin.setAdminCode(rst.getString("admin_code"));
admin.setPassword(rst.getString("password"));
admin.setName(rst.getString("name"));
admin.setTelephone(rst.getString("telephone"));
admin.setEmail(rst.getString("email"));
admin.setEnrolldate(rst.getTimestamp("enrolldate"));
}
} catch (SQLException e) {
//記日誌(保留現場)
e.printStackTrace();
/*
* 異常能否恢復,如果不能夠恢復
* (發生了系統異常,比如資料庫服務
* 暫停,網路中斷),則提示使用者稍後
* 重試。如果能夠恢復,則立即恢復。
*/
throw new RuntimeException(e);
}finally{
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return admin;
}
}
Admin.java
package com.dk.oss.entity;
import java.sql.Timestamp;
/**
* 實體類
* 注:
* 與要操作的表保持一致。
* @author Cher_du
*
*/
public class Admin {
private Integer adminId;
private String adminCode;
private String password;
private String name;
private String telephone;
private String email;
private Timestamp 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;
}
}
***為了使編寫的每一層程式碼沒有問題,需要對其進行單元測試,儘可能減少開發失誤。
TestCase.java
package test;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.dk.oss.dao.AdminDAO;
import com.dk.oss.dao.CostDAO;
import com.dk.oss.entity.Admin;
import com.dk.oss.entity.Cost;
import com.dk.oss.service.AdminService;
public class TestCase {
@Test
//測試DataSource
public void test1() throws SQLException{
ApplicationContext ac =
new ClassPathXmlApplicationContext(
"app.xml");
System.out.println(ac);
DataSource ds= ac.getBean("ds", DataSource.class);
System.out.println(ds.getConnection());
}
@Test
//測試DAO
public void test2(){
ApplicationContext ac =
new ClassPathXmlApplicationContext(
"app.xml");
AdminDAO adminDAO = ac.getBean("adminDAO", AdminDAO.class);
Admin admin= adminDAO.findByCode("caocao");
System.out.println(admin.getPassword());
}
@Test
//測試AdminService
public void test3(){
ApplicationContext ac = new ClassPathXmlApplicationContext("app.xml");
AdminService adminService = ac.getBean("adminService", AdminService.class);
Admin admin = adminService.checkLogin("caocao", "123");
System.out.println(admin.getTelephone());
}
@Test
//測試CostDAO
public void test4(){
ApplicationContext ac = new ClassPathXmlApplicationContext("app.xml");
CostDAO dao = ac.getBean("costDAO", CostDAO.class);
List<Cost> costs = dao.findAll();
System.out.println(costs);
}
}
頁面執行結果對應如下
錄入賬戶與密碼的不同情況:
正確:
錯誤:
對應練習 資費Cost部分參考程式碼:
Cost.java
package com.dk.oss.entity;
import java.sql.Timestamp;
/**
* 實體類
* @author Cher_du
*
*/
public class Cost {
private Integer costId;
private String name;
//基本時長
private Integer baseDuration;
//基本費用
private Double baseCost;
//單位費用
private Double unitCost;
//狀態:0-啟用;1-禁用;
private String status;
//描述
private String descr;
//建立時間
private Timestamp creatime;
//開通時間
private Timestamp startime;
//資費型別:1-包月;2-套餐;3-計時;
private String costType;
@Override
public String toString() {
return "Cost [costId=" + costId + ", name=" + name + ", baseDuration=" + baseDuration + ", baseCost=" + baseCost
+ ", unitCost=" + unitCost + ", status=" + status + ", descr=" + descr + ", creatime=" + creatime
+ ", startime=" + startime + ", costType=" + costType + "]";
}
public Integer getCostId() {
return costId;
}
public void setCostId(Integer costId) {
this.costId = costId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getBaseDuration() {
return baseDuration;
}
public void setBaseDuration(Integer baseDuration) {
this.baseDuration = baseDuration;
}
public Double getBaseCost() {
return baseCost;
}
public void setBaseCost(Double baseCost) {
this.baseCost = baseCost;
}
public Double getUnitCost() {
return unitCost;
}
public void setUnitCost(Double unitCost) {
this.unitCost = unitCost;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDescr() {
return descr;
}
public void setDescr(String descr) {
this.descr = descr;
}
public Timestamp getCreatime() {
return creatime;
}
public void setCreatime(Timestamp creatime) {
this.creatime = creatime;
}
public Timestamp getStartime() {
return startime;
}
public void setStartime(Timestamp startime) {
this.startime = startime;
}
public String getCostType() {
return costType;
}
public void setCostType(String costType) {
this.costType = costType;
}
}
CostDAO.java
package com.dk.oss.dao;
import java.util.List;
import com.dk.oss.entity.Cost;
/**
* DAO介面
* @author Cher_du
*
*/
public interface CostDAO {
public List<Cost> findAll();
}
CostDAOJdbcImpl.java
package com.dk.oss.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.stereotype.Repository;
import com.dk.oss.entity.Cost;
/**
* DAO實現類
* @author Cher_du
*
*/
@Repository("costDAO")
public class CostDAOJdbcImpl implements CostDAO{
//注入DataSource
@Resource(name="ds")
private DataSource ds;
//查詢出所有資費資訊
public List<Cost> findAll() {
List<Cost> costs = new ArrayList<Cost>();
Connection conn = null;
PreparedStatement prep = null;
ResultSet rst = null;
try {
conn = ds.getConnection();
String sql = "SELECT * FROM cost "
+"ORDER BY cost_id";
prep = conn.prepareStatement(sql);
rst = prep.executeQuery();
while(rst.next()){
Cost c = createCost(rst);
costs.add(c);
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return costs;
}
//將結果集中的記錄轉換成一個物件
private Cost createCost(ResultSet rst) throws SQLException {
Cost c = new Cost();
c.setCostId(rst.getInt("cost_id"));
c.setName(rst.getString("name"));
c.setBaseDuration(rst.getInt("base_duration"));
c.setBaseCost(rst.getDouble("base_cost"));
c.setUnitCost(rst.getDouble("unit_cost"));
c.setStatus(rst.getString("status"));
c.setDescr(rst.getString("descr"));
c.setCreatime(rst.getTimestamp("creatime"));
c.setStartime(rst.getTimestamp("startime"));
c.setCostType(rst.getString("cost_type"));
return c;
}
}