查询时序分析:如图-17所示
图-17
删除时序分析:如图-18所示:
图-18
Dao 层删除代码之前已经完成,所以我们现在需要将 Service 层,实现类和 Controller 层的代码完成即可,还需修改 Goods.html 页面:
- Service:
package com.cy.pj.goods.service;
import java.util.List;
import com.cy.pj.goods.pojo.Goods;
public interface GoodsService {
List<Goods> findGoods();
int deleteById(Integer id);
}
- 实现类:
@Override
public int deleteById(Integer id) {
if(id==null || id<1) throw new IllegalArgumentException("id值无效");
int rows = goodsDao.deleteById(id);
if(rows == 0) throw new NoSuchElementException("记录可能已经不存在");
return rows;
}
- Controller 层:
@RequestMapping("doDeleteById")
public String doDeleteById(Integer id){
goodsService.deleteById(id);
return "redirect:doGoodsUI";//重定向,doGoodsUI是访问路径
}
- Goods.html 页面
<thead>
<tr>
<th>Name</th>
<th>Remark</th>
<th>CreatedTime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<!--th:each,th:text,${} 由 Thymeleaf 引擎进行定义 -->
<tr th:each="g: ${goods}">
<td th:text="${g.name}"></td><!-- 中间默认值可以为空 -->
<td th:text="${g.remark}"></td>
<td th:text="${#dates.format(g.createdTime, 'yyyy/MM/dd HH:mm:ss')}"></td>
<td><a th:href="@{/goods/doDeleteById(id=${g.id})}">delete</a></td>
</tr>
</tbody>
添加时序分析:如图-19所示:
图-19
- Dao 层:
@Insert("insert into tb_goods (name,remark,createdTime) values (#{name},#{remark},now())")
int insertGoods(Goods entity);
- Service 层:
int saveGoods(Goods entity);
- 实现类:
@Override
public int saveGoods(Goods entity) {
//...可能会有其他业务,日志,id 校验等等
int rows=goodsDao.insertGoods(entity);
//...可能会有其他业务
return rows;
}
- Controller 层:
@RequestMapping("doSaveGoods")
public String doSaveGoods(Goods entity) {//提交的参数要和对象中的参数名一致
goodsService.saveGoods(entity);
return "redirect:doGoodsUI";
}
- Goods.html 网页:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
ul li {
list-style-type: none;
margin: 5px
}
</style>
</head>
<body>
<h1>This is Goods Page</h1>
<div>
<fieldset>
<legend>商品添加</legend>
<form action="doSaveGoods" method="post">
<ul>
<li>商品名称:
<li><input type="text" name="name">
<li>商品备注:
<li><textarea rows="5" cols="30" name="remark"></textarea>
<li><input type="submit" value="save">
</ul>
</form>
</fieldset>
<fieldset>
<legend>商品列表</legend>
<table>
<thead>
<tr>
<th>Name</th>
<th>Remark</th>
<th>CreatedTime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<!-- th:each th:text ${} 由thymeleaf引擎定义的 -->
<tr th:each="g: ${goods}">
<td th:text="${g.name}"></td>
<td th:text="${g.remark}"></td>
<td
th:text="${#dates.format(g.CreatedTime, 'yyyy/MM/dd HH:mm:ss')}"></td>
<td><a th:href="@{/goods/doDeleteById(id=${g.id})}">delete</a></td>
</tr>
</tbody>
</table>
</fieldset>
</div>
</body>
</html>
4.Spring Boot小节总结(自学)
1.重难点分析
掌握基于Spring boot 实现HikariCP连接池整合与测试应用的过程
掌握基于Spring boot 实现MyBatis框架资源的整合与测试。
掌握基于Spring boot 实现Spring MVC资源的整合与测试。
掌握Mybatis框架中的核心API以及应用关系
掌握Spring MVC 中的核心API对象以及这些对象之间的调用关系。
了解基于连接池获取数据库连接的基本过程。
了解HiKariCP连接池常用API以及设计原理。
了解thymeleaf模板引擎的基本应用过程(基于官方文档可以查询实用)。
2.FAQ分析
Java中连接池对象的标准API是什么?(DataSource)
Java中基于DataSource接口定义的连接池有哪些?(DBCP,C3P0,DRUID,HiKariCP,…)
Java中标准JDBC API中哪个对象负责与数据库建立连接?(Driver)
Java 中连接池中的连接也是通过Driver对象获取的吗?
SpringBoot 内置的连接池配置是什么?(HiKariCP)
SpringBoot 连接数据库的配置没有问题,数据库连不上?(服务,驱动)
SpringBoot 整合MyBatis时,为什么需要添加mybatis版本?
@Mapper注解的作用什么?(描述数据层接口,是由mybatis框架定义的规范)
@Mapper 描述数据层接口时,底层会为接口做点什么?(创建实现类,创建实现类对象,并将对象存储到spring容器-bean池。)
框架底层基于@Mapper描述的接口创建实现类对象,其内部做什么?
SpringBoot 整合mybatis时候是否可以同时存在注解和xml的映射?
SpringBoot 整合mybatis时如何实现SQL日志的输出?
Spring MVC 核心组件对象有哪些?(DispatcherServlet,HandlerMapping,…)
Spring MVC 核心组件中DispatcherServlet的作用什么?
Spring MVC 应用中请求参数的映射过程?(直接量,pojo对象)
Spring MVC 应用的请求转发和重定向?(服务端跳转,客户端跳转)
Thymeleaf 是什么,应用场景,官网的地址?(thymeleaf.org)
Thymeleaf 模板引擎中的标签属性如何使用?(查询官方docs文档)
3.BUG分析
- 数据库版本及url配置问题,如图-20所示:
图-20
问题分析:在url中追加时区配置(serverTimezone=GMT%2B8)
-
数据库服务连接不上,如图-21所示:
图-21
问题分析:检查数据库服务是否启动,连接数据库的用户名,密码是否正确. -
数据库版本或url配置问题,如图-22所示:
图-22
问题分析:检查数据的服务是否已启动,连接数据的url配置是否正确,数据库版本与驱动是否匹配. -
访问的数据库不存在,如图-23所示:
图-23
问题分析:检查url配置的数据库是否存在. -
指定命名空间下的元素ID已经存在。
Caused by: java.lang.IllegalArgumentException:
Mapped Statements collection already contains value for
com.cy.pj.goods.dao.GoodsDao.deleteObject. please check file
[D:\WORKSPSTS\CGB-SBOOT-01\target\classes\mapper\ GoodsMapper.xml]
and com/cy/pj/goods/dao/GoodsDao.java (best guess)
问题分析:可能是GoodsDao接口或映射文件对应的映射元素有重复。
- MyBatis 绑定异常,如图-24所示:
图-24
问题分析:
检查接口类全名与映射文件中的命名空间是否不一致。
检查接口方法名与映射文件中的元素是否不一致。
查接口方法参数与映射文件可接收的参数不匹配。
检查接口对应的映射文件路径是否配置不正确(mapper-locations)。
- MyBatis 参数绑定异常,如图-25所示:
图-25
问题分析:检查调用的dao方法参数与对应的SQL参数是否有映射关系.(SQL中的使用的ids参数可能没有使用@Param注解进行描述)
- 运行时的SQL语法问题,图-26所示
图-26
问题分析:
认真分析操作中提示的SQL语法问题,以及出现的大概位置。
检测业务执行时传入的参数数据是否正常。
- 无限递归调用导致的栈内存溢出,如图-27所示:
图-27
问题分析:基于错误检查自己写的类,哪里出现了循环递归调用。
- JVM端口号被占用,如图-28所示:
图-28
其解决方案为:
关闭已启动的tomcat,重新启动。
杀进程(windows)
查找进程id:netstat -ano|findstr “8080”
基于进程id杀进程:taskkill /f /pid 进程id
- URL响应资源不存在,如图-29所示:
图-29
问题分析:检查tomcat启动是否OK,检查url对应的服务端资源是否匹配(客户端
url与controller定义url),检查controller的包结构(所在包应在主启动类所在包的同包或子包中)。
- 视图解析失败,如图-30所示:
图-30
问题分析:检查视图解析器的配置是否有问题。
1.Spring Boot 综合应用实践
1.1业务需求分析及设计
从数据库查询所有活动(Activity)信息,然后呈现在页面上(基于thymeleaf,标签应用参考官网thymeleaf.org)。对于软件开发人员在需求分析时通常会有这样的过程:
第一:需求调研 (与软件使用人之间的一个沟通,了解其业务)
第二:需求分析 (对需求调研内容的总结和细化)
第三:原型设计 (是对需求分析结果的更好呈现)
第四:需求评审 (签字确认,确认边界,确定业务模块)
1.2系统架构分析及设计
如何理解架构设计?(所有的架构设计必须以业务前提,脱离业务谈架构就是耍流氓)
第一:架构模式?(CS/BS)
第二:单体架构,分布式架构,微服务架构?
第三:部署架构?(web服务器一台,数据库服务器一台,…)
第四:系统整体分层架构?(基础设施,操作系统,中间件,应用软件,接入层)
第五:软件应用的分层架构?(表示层,请求处理层,业务层,数据层)
1.3业务代码分析及设计
第一步骤:原型设计(省略)
第二步骤:数据库及表设计并初始化。
第三步骤:应用架构设计(MVC)
第四步骤:业务设计,API设计,时序设计?
第五步骤:POJO对象,数据层对象,业务层对象,控制层对象,表示层。
- 创建项目:
-
添加依赖:
-
添加配置:
#tomcat web server
server.port=80
#spring datasource
spring.datasource.url=jdbc:mysql:///dbactivity?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
#mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml
mybatis.configuration.default-statement-timeout=60
mybatis.configuration.map-underscore-to-camel-case=true
#spring thymeleaf
spring.thymeleaf.prefix=classpath:/templates/pages/
#logging
logging.level.com.cy=debug