SpringMVC 简介
背景分析
在大型软件系统设计时,业务一般会相对复杂,假如所有业务实现的代码都纠缠在一起,会出现逻辑不清晰、可读性差,维护困难,改动一处就牵一发而动全身等问题。为了更好解决这个问题就有了我们现在常说的分层架构设计。
MVC是什么
MVC是一种软件架构设计思想,基于MVC架构将我们的应用软件进行分层设计和实现,例如可以分为视图层(View),控制层(Controller),模型层(Model),通过这样的分层设计让我们程序具备更好的灵活性和可可扩展性.因为这样可以将一个复杂应用程序进行简化,实现各司其职,各尽所能.比较适合一个大型应用的开发.
SpringMVC 概述
Spring MVC是MVC设计思想在Spring框架中的一种实现,基于这样的思想spring框架设计了一些相关对象,用于更好的基于MVC架构处理请求和响应,其简易架构如图所示:
其中:
1)DispatcherServlet是客户端所有请求处理的入口,负责请求转发。
2)RequestMapping负责存储请求url到后端handler对象之间的映射。
3)Handler 用于处理DispatcherServlet对象转发过来的请求数据。
4)ViewResolver负责处理所有Handler对象响应结果中的view。
基于Spring,MyBatis,SpringBoot,Thymeleaf技术实现商品模块的增删改查操作
第一步:创建springboot项目10-springboot-goods
第二步:添加依赖
第三步:配置文件初始化
#server
server.port=1314
#spring datasource
spring.datasource.url=jdbc:mysql:///dbgoods?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=1234
#spring mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml
#spring thymeleaf
spring.thymeleaf.prefix=classpath:/templates/pages/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
#spring logging
#logging.file.path=d:/logs/
logging.level.com.cy=debug
management.endpoints.web.exposure.include=*
项目API架构设计
其API架构设计,如图所示:
商品CRUD业务实现
业务时序分析
查询所有商品信息,其业务时序分析,如图所示:
第一步:定义Goods对象,封装查询到的对象
package com.cy.pj.goods.pojo;
import java.util.Date;
/**
* 用来封装商品
*/
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() {
return createdTime;
}
@Override
public String toString() {
return "Goods{" +
"id=" + id +
", name='" + name + ''' +
", remark='" + remark + ''' +
", createdTime=" + createdTime +
'}';
}
}
第二步:Dao接口方法及映射定义
package com.cy.pj.goods.dao;
import java.util.List;
import org.apache.ibatis.annotations.*;
import com.cy.pj.goods.pojo.Goods;
/**
* 商品数据逻辑对象,负责商品模块的数据访问逻辑的实现
*/
@Mapper
public interface GoodsDao {
@Update("update tb_goods set name=#{name},remark=#{remark} where id=#{id}")
int updateGoods(Goods entity);
@Select("select * from tb_goods where id=#{id}")
Goods findById(Integer id);
@Insert("insert into tb_goods(name,remark,createdTime) values(#{name},#{remark},now())")
int insertGoods(Goods entity);
/**
* 基于id进行删除
* @param id
* @return
*/
@Delete("delete from tb_goods where id=#{id}")
int deleteById(Integer id);
/**
* 查询所有的商品信息
* @return 所有的商品
* mybatis框架中定义sql映射有两种方式:
* 1,注解方式(实现简单的sql映射)
* 2,使用XML方式(实现复杂的sql映射)
*/
@Select("select * from tb_goods")
List<Goods> findGoods();
}
第三步:Service接口方法定义及实现
GoodsService接口
package com.cy.pj.goods.service;
import com.cy.pj.goods.pojo.Goods;
import java.util.List;
/**
* 用来定义商品业务逻辑操作的接口
*/
public interface GoodsService {
int updateGoods(Goods entity);
Goods findById(Integer id);
int saveGoods(Goods entity);
int deleteById(Integer id);
List<Goods> findGoods();
}
GoodsService接口实现类GoodsServiceImpl定义及方法实现
package com.cy.pj.goods.service;
import com.cy.pj.goods.dao.GoodsDao;
import com.cy.pj.goods.pojo.Goods;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class GoodsServiceImpl implements GoodsService {
private static final Logger log=LoggerFactory.getLogger(GoodsServiceImpl.class);
@Autowired
private GoodsDao goodsDao;
@Override
public int updateGoods(Goods entity) {//对于update操作,参数entity中需要有一个id值
return goodsDao.updateGoods(entity);
}
@Override
public Goods findById(Integer id) {
return goodsDao.findById(id);//将来还可以将查询到的结果在业务逻辑层存储到cache
}
@Override
public int saveGoods(Goods entity) {
return goodsDao.insertGoods(entity);
}
@Override
public int deleteById(Integer id) {
int rows=goodsDao.deleteById(id);
return rows;
}
@Override
public List<Goods> findGoods() {
long t1=System.currentTimeMillis();
List<Goods> list=goodsDao.findGoods();
long t2=System.currentTimeMillis();
log.info("findGoods time-> {}", t2-t1);//{}为占位符好
return list;
}
}
第四步:Controller对象方法定义及实现
定义GoodsController类,
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.*;
import java.util.List;
@Controller
@RequestMapping("/goods/")
public class GoodsController {
@Autowired
private GoodsService goodsService;
@PostMapping("doUpdateGoods")
public String doUpdateGoods(Goods entity){//用pojo对象接收客户端参数
goodsService.updateGoods(entity);
return "redirect:/goods/doGoodsUI";
}
@RequestMapping("doFindById/{id}")
public String doFindById(@PathVariable Integer id,Model model){
Goods goods=goodsService.findById(id);
model.addAttribute("g", goods);
return "goods-update";
}
@RequestMapping("doSaveGoods")
public String doSaveGoods(Goods entity){//用pojo对象接收客户端参数
goodsService.saveGoods(entity);
return "redirect:/goods/doGoodsUI";
}
/**
* 返回商品添加页面
* @return
*/
@RequestMapping("doGoodsAddUI")
public String doGoodsAddUI(){
return "goods-add";
}
@RequestMapping("doDeleteById/{id}")//rest风格(软件架构编码风格)url
public String doDeleteById(@PathVariable Integer id){//@PathVariable 描述参数时表示参数的值来自url
goodsService.deleteById(id);
return "redirect:/goods/doGoodsUI";//redirect 表示重定向(客户端再次向服务端发请求)
}
// @RequestMapping("doDeleteById")
// public String doDeleteById(Integer id){
// goodsService.deleteById(id);
// return "redirect:/goods/doGoodsUI";//redirct 表示重定向(客户端再次向服务端发请求)
// }
@RequestMapping("doGoodsUI")
public String doGoodsUI(Model model){
List<Goods> goodsList=goodsService.findGoods();
model.addAttribute("goodsList", goodsList);
return "goods";//Viewname
//返回值会交给DispatcherServ
// let进行处理
//DispatcherServlet会调用ViewResolver进行视图解析(view+model)
//最后DispatcherServlet将解析结果响应到页面上
}
}
第五步:Goods商品列表页面设计及实现
在templates/pages目录中添加goods.html页面,并在body中添加html元素,在运行内部使用thymeleaf标签属性获取数据,代码如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table width="50%">
<a th:href="@{/goods/doGoodsAddUI}">添加商品</a>
<thead> <th>id</th>
<th>name</th>
<th>remark</th>
<th>createdTime</th>
<th colspan="2">operation</th>
</thead> <tbody> <tr th:each="g:${goodsList}">
<td th:text="${g.id}">1</td>
<td th:text="${g.name}">MySQL</td>
<td th:text="${g.remark}">DBMS</td>
<td th:text="${#dates.format(g.createdTime, 'yyyy/MM/dd HH:mm')}">2020/07/03</td>
<td><a th:href="@{/goods/doDeleteById/{id}(id=${g.id})}">delete</a></td>
<td><a th:href="@{/goods/doFindById/{id}(id=${g.id})}">update</a></td>
</tr> </tbody></table>
</body>
</html>
goods-adds.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--
ul li :后代选择器,ul 里所有的 li 元素,包括 ol 里的 li ; ul>li :子代选择器,下一级的DOM节点,不包括 ol 里的 li 。
ul>ol>li :子代选择器必须一代接一代。-->
<style>
ul>li{
list-style-type: none;
}
</style>
</head>
<body>
<div>
<h1>the goods add pages</h1>
<form th:action="@{/goods/doSaveGoods}" method="post">
<ul> <li>name</li>
<li><input type="text" name="name"></li>
<li>remark</li>
<li><textarea rows="3" cols="50" name="remark"></textarea></li>
<li><input type="submit" value="Save Goods"></li>
</ul> </form>
</div>
</body>
</html>
goods-update.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--
ul li :后代选择器,ul 里所有的 li 元素,包括 ol 里的 li ; ul>li :子代选择器,下一级的DOM节点,不包括 ol 里的 li 。
ul>ol>li :子代选择器必须一代接一代。-->
<style>
ul>li{
list-style-type: none;
}
</style>
</head>
<body>
<div>
<h1>the goods update pages</h1>
<form th:action="@{/goods/doUpdateGoods}" method="post">
<ul> <li><input type="hidden" name="id" th:value="${g.id}"></li>
<li>name</li>
<li><input type="text" name="name" th:value="${g.name}"></li>
<li>remark</li>
<li><textarea rows="3" cols="50" name="remark" th:text="${g.remark}"></textarea></li>
<li><input type="submit" value="Update Goods"></li>
</ul> </form>
</div>
</body>
</html>
thymeleaf 是一种模板引擎,此引擎以html为模板,可以添加自定义标签属性,可以将服务端model中数据填充在页面上,然后实现与用于交互。其官网为thymeleaf.org
Goods页面上数据呈现分析:
第六步:启动服务器进行测试
http://localhost:1314/goods/doGoodsUI
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。