1、spring运行结果出错,但不报错怎么调试?
从Controller -> Service -> dao
因为网址输入的是 : http://localhost:8080/mvc/loginInfo ,它会跳转到 login页面 ,而login页面 action="/mvc/login" 又跳转到Controller层login方法,所以先去Controller层
(1)Controller层 : 在login方法下输入 System.out.println(username + "---" + password); // 调错第一步 ,查看前端数据有没有成功接收到
(2)Service层 : 在loginYZ方法下输入 System.out.println("执行验证成功"); // 调错第二步 ,查看有没有进入到验证方法
(3)dao层 : 在loginMysql方法下输入 System.out.println("验证查询数据库"); // 调错第三步 ,查看有没有进入数据库中查询数据
(4) 如果以上都没有出错,那么结果很可能就出在数据库本身了,去数据库中看看。
将dao层的sql语句复制到数据库中验证一下。
2、demo02MVC02 是在 demo02MVC 的登录基础上改进的,所以 demo02MVC02的 Controller的所有方法注解的标识都需要改变,不能和 demo02MVC一样 ;
而且 demo02MVC02各个层的类名也需要改变,不然 Application检测不出来,会报错。
3、为了更简化代码,再分出第5块区域 : util
负责存放连接数据库的操作。
4、 模拟Linux断电 : 右击右下角的网络 -> 打开"网络和Internet"设置 -> 更改适配器选项 -> 右击 VMware Network Adapter VMnet8 -> 禁用
此时Navicat等工具都连接不上位于Linux系统中安装的Mysql了。
Java项目连接Mysql只会连接一次,conn只会有一个。
当Linux不小心断电了,重启Linux后项目不会重新连接Mysql,这时运行就会报错。除非重启一下项目才会再次连接Mysql。
原因 : 连接Mysql的代码放在了static中,只会走一次。
解决方法 : 采用连接池。
5、连接池 : 获取连接
先下载第三方连接工具:
(1)DBCP 下载 : 在maven仓库网址: https://mvnrepository.com 搜索框搜索 DBCP -> 点击 Commons DBCP -> 点击 1.4 -> 复制Maven 框下面的依赖代码 -> 粘贴在pom.xml文件下 <dependencies> xxx </dependencies> 的xxx位置
-> 代码报红 -> 点击右上角Maven 刷新下载。
(2)c3p0 下载 : 在maven仓库网址: https://mvnrepository.com 搜索框搜索 c3p0 -> 点击 C3P0 -> 点击 0.9.5.5 -> 复制Maven 框下面的依赖代码 -> 粘贴在pom.xml文件下 <dependencies> xxx </dependencies> 的xxx位置
-> 代码报红 -> 点击右上角Maven 刷新下载。
步骤 :
(1)创建连接池
BasicDataSource basicDataSource = new BasicDataSource();
(2)指定连接属性
(3)设置池的初始化大小
basicDataSource.setInitialSize(2);
(4)获取连接
当设置了连接池后,每次访问数据库都会重新获取连接,这样就解决了当Linux不小心断电了,重启Linux后项目不会重新连接Mysql,这时运行就会报错的问题。
当Linux断电重启后,不需要重新启动项目就可以再次访问数据库。
可选步骤:
(5)设置最大连接数
basicDataSource.setMaxActive(5);
(6)设置连接超时时间
basicDataSource.setMaxIdle(5);
使用连接池需要注意的问题:
设置了最大连接数后,当已有五个用户连接,第六个用户连接会等待(网页一直在转圈),连接不上?
原因 :
前五个用户获取连接池连接后,没有将连接放回连接池。
解决方法 :
在持久层 dao 中设置close : conn.close();
每次用户使用完连接池连接后,将连接关闭放回连接池,让下一个人使用。
6、缓存
设置了主键的步骤 : 项目 demo04Cache
(1) 创建数据库表 students ,并向表中伪造 1000*1000 条数据 ,将id设为主键。
(2) 运行Application ,输入 localhost:8080/students/selectById?id=1500100003972 (1500100003972是在添加的数据中随便找到的一条) ,按住 F12。
(3) 会发现第一次响应时间有2.1s ;再刷新一下,变快了很多,只有20ms 。继续刷新,都保持在20ms左右 ,当第六次刷新时会卡住 -- 需要在dao层加上 conn.close();
第一次为什么那么长时间?
因为第一次且只有第一次需要创建连接池,这需要花费很长时间。当创建了连接池之后,其他用户就可以直接去连接池获取连接,所以时间会很短。
加主键的好处?
因为id加了主键,而查询也是按id查询的,所以第二次、第三次... ,响应时间基本都在20ms左右。
将id的主键去掉之后重新运行,会发现每次刷新的响应时间变为在780ms左右,明显增加了响应时间。
>>>> 缓存的作用 == 主键的作用 <<<<<
缓存应该在 service 和 dao 之间,写在service中。
设置缓存,取消主键的步骤 :
(1) 先将数据库中表id的主键去掉。
(2) 去service层 : 加入添加缓存操作 :
1) 以 HashMap 模拟缓存 ,加上static : static HashMap<String, String> cache = new HashMap<>();
2) 先查询缓存, 缓存中存在就直接取出
3) 如果不存在, 再执行 selectById() 查询数据库 ,并将查询到的数据插入到缓存中
(3) 此时运行的响应时间和加了主键基本一样了。 第一次响应时间长,然后接下来就会很短。
但是又出了新的问题 : --- 隐私性
无论是哪个用户,当项目在运行时,只要在网页上输入localhost:8080/students/selectById?id=1500100003972 都可以访问到我的数据库中存储的内容。
解决方法 : API
7、API 面向接口开发
格式 : localhost:8080/students/selectById?id=1500100003972&key=xxxxxx
专业下载API数据接口的网址 : https://www.juhe.cn/apiservice?f=head?f=head
使用加key的方法解决上面出现的隐私性问题 : 项目 demo04Cache
(1) 在项目 demo04Cache 的源码上, 先在Controller层将key作为参数加入
(2) 再去Service层验证key
API项目的创建 : 项目 demo05API
不仅有查询功能,也有delete功能。
(1) 分别在Controller层、Service层和到层 添加查询和删除两个功能。
(2) 若数据库从Mysql 变为 Hive ,那么只需要保证dao层 Hive中的查询和删除方法名和Mysql中的一样 。
总结 :
方法名统一 --> 接口
(3) 在dao层创建一个接口,用于做方法名的统一,MysqlDao 和 HiveDao 都继承这个接口。
//private APIStudentsDao dao1 = new APIStudentsDao();
private HiveStudentsDao dao2 = new HiveStudentsDao();
(4) 在Service层使用接口多态 ,保证对象名一样。 (用dao层接口多态dao层实现类)
//APIStudentsDaoImpl dao = new APIStudentsDao();
APIStudentsDaoImpl dao = new HiveStudentsDao();
面向接口开发(完整的API) : 项目 demo06API
(1) 在Controller层创建正常类
(2) 在Service层创建接口 APIService ,再创建一个包impl存放接口的实现类 APIServiceImpl
(3) 在Dao层创建一个接口 APIDao , 再创建一个包impl存放接口的实现类 APIDapImpl
(4) Dao层写完 ,Service层实现类 接口多态 调用 : APIDao dao = new APIDaoImpl();
当dao层发生改变 ,只需要替换这里的实现类名
APIDao dao = new APIDao02Impl();
(5) 接着Controller层正常类 接口多态 调用 : APIService Service = new APIServiceImpl();