案例2:qqZone
文章目录
- 一.业务需求分析
- 二.数据库的设计
- 三.代码实现
- 1. `pojo`类的实现
- 1.1设计原则
- 1.2可能的异常
- 2. `dao`类
- 3. `service`类
- 3.1 接口
- 3.2 接口的实现类
- 4. `controller`类
- 4.1`UserController`
- 4.2`TopicController`
- 5.`HTML`的设计
- 4.1可能的异常`
- 4.2`login`登录界面
- 4.3`index`展示界面
- 4.3.1`top`页面信息
- 4.3.2`left`好友列表
- 4.3.3`main`日志显示列表
- 4.3.4`detial`日志详情
- 四.开发套路总结
- 1.拷贝`myssm`包
- 2.新建配置文件`applicationContext.xml`或者其他名字,在`web.xml`中指定文件名
- 3.在`web.xml`文件中配置:
- 4.开发具体的业务模块:
- 5.数据库连接异常
一.业务需求分析
- 用户登录
- 登陆成功,显示主界面。左侧显示好友列表;上端显示欢迎词。如果不是自己空间,显示超链接:返回我主页
- 查看日志详情:
- 日志本身的信息(作者头像,昵称,日志标题,日志内容,日志的日期)
- 回复列表(回复作者的头像,昵称,回复内容,回复日期)
- 主人回复信息
- 删除日志
- 删除特定的回复
- 删除特定主人的回复
- 添加日志、添加回复、添加主人回复
- 点击左侧好友,进入好友的空间
二.数据库的设计
- 抽取实体:用户登录信息、用户详情信息、日志、回帖、主人回帖
- 属性分析
- 实体之间的关系
三.代码实现
1. pojo
类的实现
1.1设计原则
主键应该是没有实际意义的列,不要和业务由关联。因为将来可能涉及两表合并,主键将无法合并。
设计时间类型时:
–年月日时分秒(
java.util.Date
),–年月日(
java.sql.Date
),时分秒(java.sql.TIme
)类与类之间的关系也要建立
public class UserBasic {private Integer id;private String loginId;private String nickName;private String pwd;private String headImg;//类与类之间的关系private UserDetail userDetail; //1:1private List<Topic> topicList; //1:Nprivate List<UserBasic> friendList; //M:Npublic UserBasic() {} }
1.2可能的异常
- 查询好友列表时,查询到的
rsmd.getColumnName
为fid
,而UserBasic
中的属性为id
。可以在sql
语句中使用别名代替,并rsmd.getColumnName
替代 - 数据库连接失败:1.驱动是否导入,2.数据库选择,3.用户名和密码。
- 获取
Topic
列表时调用setValue(entity,columnName,columnValue)
设置UserBasic author
属性,但是数据库中返回的类型是Integer
。
2. dao
类
3. service
类
3.1 接口
3.2 接口的实现类
4. controller
类
4.1UserController
4.2TopicController
需要根据topicId
获取对应的topic
信息
5.HTML
的设计
4.1可能的异常`
页面无法渲染。
原因:没有经过
processTemplate(methodReturnStr,req,resp);
语句的渲染,而是直接跳转到静态页面解决:通过
PageController
控制渲染,调用PageController
中的page
方法跳转到Page
参数对应的页面。iframe th:src="@{/page.do?operate=page&page=frames/left}"
public class PageController {protected String page(String page){return page;} }
点击好友名称时,在
iframe
中刷新整个页面。原因:
target
没有设置解决:超链接后添加
target="_top"
语句,使得新页面在顶层显示。访问动态页面时,一定要经过渲染。案例使用
PageController
渲染return
语句的使用:
4.2login
登录界面
静态页面:可以直接用地址访问。本案例使用
page.do?operate=page&page=login
渲染得到。启动时,访问的页面是:
http:// localhost :8080 /pro23 /page.do ?operate=page&page=login
协议
ServerIP
port
context root
request.getPath
query String
4.3index
展示界面
4.3.1top
页面信息
显示欢迎进入好友页面:
th:text="|欢迎进入${session.friend.nickName}的空间!|"
如果不是在自己空间,显示连接返回自己空间(即将
friend
更新为当前userBasic
)<span th:if="${session.userBasic.id!=session.friend.id}"><a th:href="@{|/user.do?operate=friend&id=${session.userBasic.id}|}" target="_top">返回自己的空间!</a> </span>
4.3.2left
好友列表
- 点击好友时,页面刷新为好友的日志列表。
- 根据id查询好友的
userBasic
信息,覆盖session.friend
- main页面展示friend的
topicList
,而不是userBasic
中的topicList
。方法:给连接添加target="_top"
- 根据id查询好友的
4.3.3main
日志显示列表
日期显示的格式化与解析
在
java
中//解析:看的懂 ---> 看不懂 String dateStr = "2022-04-11 12:58:13"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try{Date date = sdf.parse(dateStr); }catch (ParseException e){e.printStackTrance(); } //格式化:看不懂 ---> 看得懂 Date date = new Date(); String dateStr = sdf.format(date);
在
thymeleaf
中#dates.format(topic.topicDate,'yyyy-MM-dd HH:mm:ss')
4.3.4detial
日志详情
一句里面不能有两个
style
配置
thymeleaf
文件@{}
:表示省略了pro21/
的绝对路径<html lang="en" xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" th:href="@{css/common.css}"><link rel="stylesheet" th:href="@{css/main.css}"> </head>
需要获取主人日志,回复列表(每个回复对应的主人日志)。
日志中的主人回复没有显示
<!--head中--> <script language="JavaScript">function showDelImg(imgId){document.getElementById(imgId).style.display='inline';}function hiddenDelImg(imgId){document.getElementById(imgId).style.display='none';}</script> <!--body中--> <td th:onmouseover="|showDelImg('a${reply.id}')|" th:onmouseout="|hiddenDelImg('a${reply.id}')|"> <a th:unless="${reply.hostReply!=null}" th:id="|a${reply.id}|" th:href="#" style="float: right;display: inline;">主人回复</a> </td>
可以删除的条件
- 在我自己的空间
- 这条评论是我发表的
异常:删除父表时,需要保证没有子表在引用父表
MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`qqzonedb`.`t_host_reply`, CONSTRAINT `FK_host_reply` FOREIGN KEY (`reply`) REFERENCES `t_reply` (`id`))
四.开发套路总结
1.拷贝myssm
包
2.新建配置文件applicationContext.xml
或者其他名字,在web.xml
中指定文件名
3.在web.xml
文件中配置:
配置前缀和后缀,这样
thtmeleaf
引擎就可以根据我们返回的字符串进行拼接,再跳转<context-param><param-name>view-prefix</param-name><param-value>/</param-value> </context-param> <context-param><param-name>view-suffix</param-name><param-value>.html</param-value> </context-param>
配置监听器要读取的参数,目的是加载
IOC
容器的配置文件(applicationContext.xml
)<context-param><param-name>contextConfigLocation</param-name><param-value>applicationContext</param-value> </context-param>
4.开发具体的业务模块:
一个具体的业务模块的纵向结构:
html
页面POJO
类DAO
接口和实现类Service
接口和实现类Controller
控制器组件
如果
html
页面有thymeleaf
表达式,一定不能够直接访问,必须要经过PageController
在
applicationContext.xml
中配置DAO,Service,Controller
,以及三者之间的依赖关系DAO
实现类中,继承BaseDAO
,然后实现具体的接口,注意泛型不能写错,例如:public class UserDAOImpl extends BaseDAO<User> implements UserDAO{}
Service
是业务控制类,需要注意- 业务逻辑封装在Service这一层,不要分散在
Controller
层。也不要出现在DAO
层(需要保证DAO
方法的单精度特性) - 当需要使用其他模块的功能的时候,尽量调用别人的
service
,而不是深入到其他模块的DAO
细节
- 业务逻辑封装在Service这一层,不要分散在
Controller
类的编写规则在
applicationContext.xml
中来配置Controller
<bean id="user" class="com.atlff.qqzone.controllers.UserController">
那么,用户在前端发请求时,对应的
servletPath
就是/User.do
,其中“user”就是此处bean
的id
值在
Controller
中设计的方法名需要和operate
的值一致public String login(String loginId, String pwd, HttpSession session){return "index"; }
此时验登录的表单如下:
<form th:action="@{/user.do}" method="post"><input type="hidden" name="operate" value="login"> </form>
在表单中,组件的
name
属性和Controller
中的方法参数名一致<input type="text" name="loginId">
public String login(String loginId, String pwd, HttpSession session)
另外,
Controller
中的方法不一定都是通过请求参数获取if("request".equals...) else if("resqonse".equals...) else if("session".equals...){//直接赋值 }else{//此处才是从request的请求参数中获取request.getParameter("loginId")... }
DispatcherServlet
中步骤的分类:0.从
application
作用域获取IOC
容器1.解析
servletPath
,在IOC
容器中寻找对应的Controlelr
组件2.准备
operate
指定的方法所要求的参数3.调用
operate
指定的方法4.接收到执行
operate
指定的方法的返回值,对返回值进行处理 ----视图处理为什么
DispatcherServlet
能够从application
作用域获取到IOC
容器?ContextLoaderListener
在容器启动时会执行初始化任务,而他的操作是:1.解析
IOC
的配置文件,创建一个一个的组件,并完成组件之间的依赖注入关系2.将
IOC
容器保存到application
作用域
5.数据库连接异常
数据库连接失败
原因:
druid
没有添加到部署包解决:在项目结构中的
ProjectStructure
中将jar
包添加部署数据库报错连接太多
Data source rejected establishment of connection, message from server:"Too many connections"
原因:
DruidDataSourceFactory.createDataSource(properties);
出现在createConnection
中,导致创建多个连接池.解决:将连接池放置在初始化的代码段,而不是出现在方法中.
数据库连接失败
原因:
druid
没有添加到部署包解决:在项目结构中的
ProjectStructure
中将jar
包添加部署数据库报错连接太多
Data source rejected establishment of connection, message from server:"Too many connections"
原因:
DruidDataSourceFactory.createDataSource(properties);
出现在createConnection
中,导致创建多个连接池.解决:将连接池放置在初始化的代码段,而不是出现在方法中.
案例2:qqZone相关推荐
- 爬虫(11) selenium(下) 行为链 登录qq空间案例
文章目录 第十一章 selenium(下)行为链登录qq空间 1. 行为链 2. selenium操作cookie 2.1 获取cookie 2.2 登录QQ空间 2.3 自己的方法登录QQ空间 2. ...
- python 网络编程之Socket通信案例消息发送与接收
背景 网络编程是python编程中的一项基本技术.本文将实现一个简单的Socket通信案例消息发送与接收 正文 在python中的socket编程的大致流程图如上所示 我们来首先编写客户端的代码: # ...
- 2021年大数据ELK(十七):Elasticsearch SQL 订单统计分析案例
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 订单统计分析案例 一.案例介绍 二.创建索引 三.导入测试数据 四.统计不同支 ...
- 2021年大数据ELK(十六):Elasticsearch SQL(职位查询案例)
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 职位查询案例 一.查询职位索引库中的一条数据 二.将SQL转换为DSL 三.职 ...
- 2021年大数据ELK(四):Lucene的美文搜索案例
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 美文搜索案例 一.需求 二.准备工作 1.创建IDEA项目 2. ...
- ❤️让人心跳加速的陌陌案例,大数据必需学会的基础案例!❤️ 【推荐收藏】
全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 已列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 前言 陌陌案例 一.陌陌案例的需求说明 二.陌陌案例中表设计内容 1. ...
- 2021年大数据Hive(十二):Hive综合案例!!!
全网最详细的大数据Hive文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 前言 Hive综合案例 一.需求描述 二.项目表的字段 三.进 ...
- 2021年大数据Flink(三十八):Table与SQL 案例五 FlinkSQL整合Hive
目录 案例五 FlinkSQL整合Hive 介绍 集成Hive的基本方式 准备工作 1.添加hadoop_classpath 2.下载jar并上传至flink/lib目录 3.修改hive配置 4.启 ...
- 2021年大数据Flink(三十七):Table与SQL 案例四
目录 案例四 需求 代码实现 案例四 需求 从Kafka中消费数据并过滤出状态为success的数据再写入到Kafka {"user_id": "1", &qu ...
最新文章
- 中医研究登上Nature
- LINUX文件、目录权限及相关操作命令
- Struts2学习总结二
- 遍历Windows系统的内核模块(源码)
- ABAP应用服务器的HTTP响应状态码(Status Code)
- IdentityServer4-前后端分离的授权验证(六)
- 远控免杀专题(23)-SharpShooter免杀
- 前端学习(1780):前端调试之快速转存站点的方法
- idea的plugins无法使用marketplace plugins are not loaded
- Java事务管理之Hibernate
- Mac效率工具:Mosaic 1.3.3
- 方法、hadoop源码之JobQueueTaskScheduler-by小雨
- matlab计算涡度的函数_流函数涡量法的二维方腔流数值模拟matlab编程.doc
- 个人微信api接口调用,微信好友收发消息
- select设置默认的option
- html5 斜边,css斜切角 斜边 倒角
- 虚拟机设置BT4上网
- java百万级大数据量导出
- letcode 715
- 国内三大B2C网站首页的信息架构【收集整理,本人非原作者】
热门文章
- linux实现毛玻璃窗口,给Ubuntu 安装透明水晶毛玻璃效果主题[组图]
- 前端用队列实现击鼓传花游戏
- 在动态规划的海洋中遨游(一)
- com.alibaba.fastjson.JSONException: can not cast to JSONObject.
- Tachiyomi 使用指南:一款开源的聚合漫画阅读软件
- 4K激光电视进入万元时代,极米引领新一轮客厅革命
- 学习UI设计怎么样?为什么有人觉得UI设计找工作难?
- Jmeter用户自定义变量
- xboxone硬盘坏的表现_直视问题,教你怎么正确判断自己的移动硬盘出了什么故障...
- U盘怎么调整分区大小?u盘分区工具推荐