Java學(xué)習(xí)總結(jié) SpringBoot整合Spring MVC
1.SpringMVC概述
MVC(Model–view–controller)是軟件工程中的一種軟件架構(gòu)模式静汤,基于此模式把軟件系統(tǒng)分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)与倡。目的是通過這樣的設(shè)計使程序結(jié)構(gòu)更加簡潔、直觀昆稿,降低問題的復(fù)雜度纺座。其中各個組成部分的職責(zé)為:
視圖(View) - UI設(shè)計人員進行圖形界面設(shè)計,負(fù)責(zé)實現(xiàn)與用戶交互溉潭。
控制器(Controller)- 負(fù)責(zé)獲取請求净响,處理請求,響應(yīng)結(jié)果喳瓣。
模型(Model) - 實現(xiàn)業(yè)務(wù)邏輯馋贤,數(shù)據(jù)邏輯實現(xiàn)。
我們在軟件設(shè)計時畏陕,通常要遵循一定的設(shè)計原則配乓。MVC架構(gòu)模式的設(shè)計中,首先基于單一職責(zé)原則(SRP-Single responsibility principle)讓每個對象各司其職蹭秋,各盡所能扰付。
然后再基于“高內(nèi)聚,低耦合”的設(shè)計思想實現(xiàn)相關(guān)層對象之間的交互仁讨。這樣可以更好提高程序的可維護性和可擴展性羽莺。
JavaEE技術(shù)體系中,MVC設(shè)計思想的實現(xiàn)洞豁,如圖-14所示:
在上圖中盐固,Servlet充當(dāng)MVC中的Controller,負(fù)責(zé)調(diào)用model處理業(yè)務(wù)荒给,負(fù)責(zé)轉(zhuǎn)發(fā)或重定向某個頁面,在頁面(view)上呈現(xiàn)數(shù)據(jù)刁卜。
模塊封裝了對Servlet的技術(shù)的應(yīng)用志电,簡化了程序員對請求和響應(yīng)過程中數(shù)據(jù)的處理。Spring MVC 是Spring 框架中基于MVC設(shè)計思想實現(xiàn)的一個用于處理Web請求的模塊蛔趴。其簡易架構(gòu)分析挑辆,如下圖所示:
DispatcherServlet :前端控制器, 處理請求的入口。
HandlerMapping:映射器對象, 用于管理url與對應(yīng)controller的映射關(guān)系孝情。
Interceptors:攔截器,實現(xiàn)請求響應(yīng)的共性處理鱼蝉。
Controller:后端控制器-handler, 負(fù)責(zé)處理請求的控制邏輯。
ViewResolver:視圖解析器,解析對應(yīng)的視圖關(guān)系(前綴+viewname+后綴)箫荡。
備注:假如希望了解Spring MVC的詳細(xì)處理流程可以基于斷點調(diào)試法進行跟蹤魁亦。
2.初始配置
1. 添加Spring MVC依賴
編輯pom.xml文件,添加web依賴,Thymeleaf依賴羔挡,代碼如下:
Web依賴(提供了Spring MVC核心API洁奈,同時會嵌入一個Tomcat服務(wù)器)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Thymeleaf依賴(提供了一個視圖解析器對象以及數(shù)據(jù)綁定機制)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
其中: Spring Web Starter 提供Spring MVC 依賴支持,并會自動添加一個tomcat依賴,作為嵌入式web服務(wù)器使用.thymeleaf是一個html模板引擎绞灼,提供了與Spring MVC進行整合的API利术,可作為MVC架構(gòu)中Web應(yīng)用的View層。
2. 配置Spring MVC 核心對象
在application.proper視ties文件中添加圖解析器配置(假如沒有配置也會默認(rèn)配置镀赌,在默認(rèn)配置中prefix默認(rèn)值為classpath:/templates/,后綴默認(rèn)為.html)氯哮。
spring.thymeleaf.prefix=classpath:/templates/pages/
spring.thymeleaf.suffix=.html
說明:要基于配置在src/main/resources目錄下創(chuàng)建templates/pages目錄
3.Spring MVC 進行入門實踐
第一步:編寫GoodsController類并將其交給spring管理。這樣的Controller在SpringMVC 規(guī)范中通常稱之為Handler(處理器)商佛,我們在企業(yè)中有時也會將此對象理解為一個后端控制器喉钢。
package com.cy.pj.goods.controller;
@Controller
@RequestMapping("/goods/")
public class GoodsController {
@RequestMapping("doGoodsUI")
public String doGoodsUI() {
return "goods";
}
}
第二步:需要在/templates/pages/目錄下創(chuàng)建goods.html
第三步:啟動服務(wù)器(默認(rèn)項目嵌入的是tomcat),打開瀏覽器進行訪問測試良姆。
http://localhost:8080/goods/doGoodsUI
API應(yīng)用設(shè)計,如圖所示:
課堂練習(xí)1:將數(shù)據(jù)庫中的商品數(shù)據(jù)查詢出來更新到頁面上肠虽。
查詢時序分析:
第一步:定義pojo對象(com.cy.pj.goods.pojo.Goods)
package com.cy.pj.goods.pojo;
import java.util.Date;
/**
* pojo對象,基于此對象封裝從數(shù)據(jù)庫查詢到的數(shù)據(jù)
* 思考:對象靠什么存儲數(shù)據(jù)玛追?屬性
*/
public class Goods {
private Long id;//id bigint primary key auto_increment
private String name;//name varchar(100) not null
private String remark;//remark text
private Date createdTime;//createdTime datetime
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Date getCreatedTime() {
// System.out.println("==getCreatedTime==");
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
@Override
public String toString() {
return "Goods{" +
"id=" + id +
", name='" + name + '\'' +
", remark='" + remark + '\'' +
", createdTime=" + createdTime +
'}';
}
}
第二步:定義GoodsDao接口及方法
package com.cy.pj.goods.dao;
import com.cy.pj.goods.pojo.Goods;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* @Mapper是由Mybatis框架中定義的一個描述數(shù)據(jù)層接口對象的注解(所有的注解起到一個描述性的作用)
* 系統(tǒng)底層啟動mybatis框架會基于@Mapper注解的描述,創(chuàng)建其接口的實現(xiàn)類,并將其實現(xiàn)類對象交給spring管理
*/
@Mapper
public interface GoodsDao {
/**
* 查找所有商品信息
*/
@Select("SELECT id,name,remark,createdTime FROM tb_goods")
List<Goods> findObjects();
}
第三步:定義GoodsService接口及其實現(xiàn)類
GoodsService
package com.cy.pj.goods.service;
import com.cy.pj.goods.pojo.Goods;
import java.util.List;
public interface GoodsService {
List<Goods> findGoods();
}
GoodsServiceImpl
package com.cy.pj.goods.service.impl;
import com.cy.pj.goods.dao.GoodsDao;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 商品業(yè)務(wù)層對象,負(fù)責(zé)業(yè)務(wù)邏輯處理
*/
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsDao goodsDao;
@Override
public List<Goods> findGoods() {
Long start=System.currentTimeMillis();
List<Goods> list=goodsDao.findObjects();
long end=System.currentTimeMillis();
System.out.println("query time:"+(end-start));
return list;
}
}
第四步:定義GoodsController及其url映射
package com.cy.pj.goods.controller;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/goods/")
public class GoodsController {
@Autowired
private GoodsService goodsService;
//http:localhost:8080/goods/doGoodsUI
//此訪問路徑會傳遞到DispatcherServlet對象
//DispatcherServlet對象會基于用戶輸入的url找到對應(yīng)的controller及方法
//DispatcherServlet底層會根據(jù)反射技術(shù)調(diào)用對應(yīng)的控制層方法
@RequestMapping("doGoodsUI")
public String doGoodsUI(Model model) {
//獲取業(yè)務(wù)數(shù)據(jù)
List<Goods> list = goodsService.findGoods();
//將數(shù)據(jù)存儲到作用域?qū)ο? model.addAttribute("list", list);
//將頁面響應(yīng)到客戶端
return "goods";//view name
//將此view返回給前端控制器DispatcherServlet
//前端控制器會調(diào)用視圖解析器對view進行解析,添加前綴和后綴
//templates/pages/goods.html
//最后由DispatcherServlet將頁面響應(yīng)給客戶端
}
}
第五步:定義goods.html,通過Thymeleaf模板將活動數(shù)據(jù)呈現(xiàn)在頁面上
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<thead>
<th>id</th>
<th>name</th>
<th>remark</th>
<th>createdTime</th>
</thead>
<tbody>
<tr th:each="g:${list}" >
<td th:text="${g.id}"></td>
<td th:text="${g.name}"></td>
<td th:text="${g.remark}"></td>
<td th:text="${#dates.format(g.createdTime,'yyyy/MM/dd HH:mm')}"></td>
</tr>
</tbody>
</table>
</body>
</html>
第六步:運行Application啟動服務(wù)器,在網(wǎng)頁中輸入url地址
啟動服務(wù)器:
在網(wǎng)頁中輸入url地址:http://localhost:8080/goods/doGoodsUI
查詢結(jié)果如下:
課堂練習(xí)二:基于ID刪除商品庫中的商品信息
時序分析:
第一步:GoodsDao中定義基于id刪除記錄的方法 deleteById(Integer id);
package com.cy.pj.goods.dao;
import com.cy.pj.goods.pojo.Goods;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* @Mapper是由Mybatis框架中定義的一個描述數(shù)據(jù)層接口對象的注解(所有的注解起到一個描述性的作用)
* 系統(tǒng)底層啟動mybatis框架會基于@Mapper注解的描述,創(chuàng)建其接口的實現(xiàn)類,并將其實現(xiàn)類對象交給spring管理
*/
@Mapper
public interface GoodsDao {
/**
* 基于id刪除數(shù)據(jù)庫中商品信息
* @param id
* @return
*/
@Delete("delete from tb_goods where id=#{id}")
int deleteById(Integer id);
/**
* 查找所有商品信息
* @return
*/
@Select("SELECT id,name,remark,createdTime FROM tb_goods")
List<Goods> findObjects();
}
第二步:GoodsService及實現(xiàn)類中定義deleteById(Integer id)方法用于執(zhí)行記錄刪除
GoodsService
package com.cy.pj.goods.service;
import com.cy.pj.goods.pojo.Goods;
import java.util.List;
public interface GoodsService {
List<Goods> findGoods();
void deleteById(Integer id);
}
GoodsServiceImpl
package com.cy.pj.goods.service.impl;
import com.cy.pj.goods.dao.GoodsDao;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 商品業(yè)務(wù)層對象,負(fù)責(zé)業(yè)務(wù)邏輯處理
*/
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsDao goodsDao;
@Override
public List<Goods> findGoods() {
Long start=System.currentTimeMillis();
List<Goods> list=goodsDao.findObjects();
long end=System.currentTimeMillis();
System.out.println("query time:"+(end-start));
return list;
}
@Override
public void deleteById(Integer id) {
int rows=goodsDao.deleteById(id);
}
}
第三步:ActivityController中定義doDeleteById(Integer id)方法用于處理刪除請求
package com.cy.pj.goods.controller;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/goods/")
public class GoodsController {
@Autowired
private GoodsService goodsService;
//http://localhost:8080/goods/doDeleteById
@RequestMapping("doDeleteById")
public String doDeleteById(Integer id){
//調(diào)用業(yè)務(wù)層對象執(zhí)行刪除操作
goodsService.deleteById(id);
//思考:刪除以后要做什么?
//在當(dāng)前業(yè)務(wù)中我們可以重定向到查詢頁面
return "redirect:doGoodsUI";
}
//http:localhost:8080/goods/doGoodsUI
//此訪問路徑會傳遞到DispatcherServlet對象
//DispatcherServlet對象會基于用戶輸入的url找到對應(yīng)的controller及方法
//DispatcherServlet底層會根據(jù)反射技術(shù)調(diào)用對應(yīng)的控制層方法
@RequestMapping("doGoodsUI")
public String doGoodsUI(Model model) {
//獲取業(yè)務(wù)數(shù)據(jù)
List<Goods> list = goodsService.findGoods();
//將數(shù)據(jù)存儲到作用域?qū)ο? model.addAttribute("list", list);
//將頁面響應(yīng)到客戶端
return "goods";//view name
//將此view返回給前端控制器DispatcherServlet
//前端控制器會調(diào)用視圖解析器對view進行解析,添加前綴和后綴
//templates/pages/goods.html
//最后由DispatcherServlet將頁面響應(yīng)給客戶端
}
}
第四步:定義goods.html,通過Thymeleaf模板將活動數(shù)據(jù)呈現(xiàn)在頁面上
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<thead>
<th>id</th>
<th>name</th>
<th>remark</th>
<th>createdTime</th>
</thead>
<tbody>
<tr th:each="g:${list}" >
<td th:text="${g.id}"></td>
<td th:text="${g.name}"></td>
<td th:text="${g.remark}"></td>
<td th:text="${#dates.format(g.createdTime,'yyyy/MM/dd HH:mm')}"></td>
<td><a th:href="@{/goods/doDeleteById(id=${g.id})}">delete</a></td>
</tr>
</tbody>
</table>
</body>
</html>
第五步:運行Application啟動服務(wù)器,在網(wǎng)頁中輸入url地址
啟動服務(wù)器:
在網(wǎng)頁中輸入url地址:http://localhost:8080/goods/doGoodsUI
點擊delete
課堂練習(xí)三:將頁面用戶輸入的商品信息寫入到數(shù)據(jù)庫
時序分析
第一步:在GoodsDao中定義insert(Goods entity)方法以及SQL映射
package com.cy.pj.goods.dao;
import com.cy.pj.goods.pojo.Goods;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* @Mapper是由Mybatis框架中定義的一個描述數(shù)據(jù)層接口對象的注解(所有的注解起到一個描述性的作用)
* 系統(tǒng)底層啟動mybatis框架會基于@Mapper注解的描述,創(chuàng)建其接口的實現(xiàn)類,并將其實現(xiàn)類對象交給spring管理
*/
@Mapper
public interface GoodsDao {
/**
* 基于id刪除數(shù)據(jù)庫中商品信息
* @param id
* @return
*/
@Delete("delete from tb_goods where id=#{id}")
int deleteById(Integer id);
/**
* 基于id進行批量刪除操作
* @param ids
* @return
*/
//int deleteObjects(@Param("ids")Integer...ids);早期版本需要基于@Param注解
int deleteObjects(Integer...ids);//sql映射中可使用array,ids參數(shù)名來接收方法參數(shù)
/**
* 查找所有商品信息
* @return
*/
@Select("SELECT id,name,remark,createdTime FROM tb_goods")
List<Goods> findObjects();
@Insert("insert into tb_goods (name,remark,createdTime) values(#{name},#{remark},now())")
int insert(Goods entity);
}
第二步:在GoodsService接口及實現(xiàn)類中添加insert(Goods entity)
GoodsService
package com.cy.pj.goods.service;
import com.cy.pj.goods.pojo.Goods;
import java.util.List;
public interface GoodsService {
List<Goods> findGoods();
void deleteById(Integer id);
int insert(Goods entity);
}
GoodsServiceImpl
package com.cy.pj.goods.service.impl;
import com.cy.pj.goods.dao.GoodsDao;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 商品業(yè)務(wù)層對象,負(fù)責(zé)業(yè)務(wù)邏輯處理
*/
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsDao goodsDao;
@Override
public List<Goods> findGoods() {
Long start=System.currentTimeMillis();
List<Goods> list=goodsDao.findObjects();
long end=System.currentTimeMillis();
System.out.println("query time:"+(end-start));
return list;
}
@Override
public void deleteById(Integer id) {
int rows=goodsDao.deleteById(id);
}
@Override
public int insert(Goods entity) {
int rows=goodsDao.insert(entity);
return rows;
}
}
第三步:在GoodsController對象中添加doSaveGoods方法并定義url映射
package com.cy.pj.goods.controller;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/goods/")
public class GoodsController {
@Autowired
private GoodsService goodsService;
//http://localhost:8080/goods/doDeleteById
@RequestMapping("doDeleteById")
public String doDeleteById(Integer id){
//調(diào)用業(yè)務(wù)層對象執(zhí)行刪除操作
goodsService.deleteById(id);
//思考:刪除以后要做什么?
//在當(dāng)前業(yè)務(wù)中我們可以重定向到查詢頁面
return "redirect:doGoodsUI";
}
@RequestMapping("doSaveGoods")
public String doSaveGoods(Goods entity){
goodsService.insert(entity);
return "redirect:doGoodsUI";
}
//http:localhost:8080/goods/doGoodsUI
//此訪問路徑會傳遞到DispatcherServlet對象
//DispatcherServlet對象會基于用戶輸入的url找到對應(yīng)的controller及方法
//DispatcherServlet底層會根據(jù)反射技術(shù)調(diào)用對應(yīng)的控制層方法
@RequestMapping("doGoodsUI")
public String doGoodsUI(Model model) {
//獲取業(yè)務(wù)數(shù)據(jù)
List<Goods> list = goodsService.findGoods();
//將數(shù)據(jù)存儲到作用域?qū)ο? model.addAttribute("list", list);
//將頁面響應(yīng)到客戶端
return "goods";//view name
//將此view返回給前端控制器DispatcherServlet
//前端控制器會調(diào)用視圖解析器對view進行解析,添加前綴和后綴
//templates/pages/goods.html
//最后由DispatcherServlet將頁面響應(yīng)給客戶端
}
}
第四步:在頁面中g(shù)oods.html添加form表單(用戶填寫數(shù)據(jù))并設(shè)置樣式
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/goods/doSaveGoods" method="post">
<ul>
<li>name:
<li><input type="text" name="name">
<li>remark:
<li><textarea rows="5" cols=""50 name="remark"></textarea>
<li><input type="submit" value="save"></li>
</ul>
</form>
<fieldset>
<legend>商品列表</legend>
<table width="50%">
<table>
<thead>
<th>id</th>
<th>name</th>
<th>remark</th>
<th>createdTime</th>
</thead>
<tbody>
<tr th:each="g:${list}" >
<td th:text="${g.id}"></td>
<td th:text="${g.name}"></td>
<td th:text="${g.remark}"></td>
<td th:text="${#dates.format(g.createdTime,'yyyy/MM/dd HH:mm')}"></td>
<td><a th:href="@{/goods/doDeleteById(id=${g.id})}">delete</a></td>
</tr>
</tbody>
</table>
</body>
</html>
第五步:在表單中輸入數(shù)據(jù),然后點擊保存按鈕,將數(shù)據(jù)傳遞到服務(wù)端
最后
有什么不懂的歡迎在下方留言討論税课,也可以選擇私信問我,私信我一般看到之后都會回的痊剖,當(dāng)然特別忙的時候沒看到的話也請見諒韩玩!