# CloudNote **Repository Path**: hmfdev/CloudNote ## Basic Information - **Project Name**: CloudNote - **Description**: 互联网在线云日记系统实战-云R记 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 20 - **Forks**: 5 - **Created**: 2021-07-08 - **Last Updated**: 2024-09-13 ## Categories & Tags **Categories**: blog **Tags**: jsp, Servlet, Bootstrap ## README # CloudNote #### 介绍 云R记软件就是用于记录日常生活点滴。一款跨平台的简单快速的个人记事备忘工具,并且能够实现PC、移动设备和云端之间的信息同步,简洁高效。将会议记录、日程安排、生活备忘,奇思妙想、快乐趣事以及任何突发灵感都可快速记录到系统中。 #### 软件架构 本系统采用B/S架构,使用 BootStrap + JSP + Servlet + MySQL + Tomcat 开发,使用 Maven 构建,采用 JUnit 单元测试、Log4j搭建日志 #### 项目图片展示(具体展示图片在 PICTURE.md 文件中) ##### 登录页 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0820/105414_501f55bd_5474516.png "login1.png") ##### 首页 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0820/105428_df189c27_5474516.png "mainPage.png") #### 提交日志细节记录 1. 【1.本地初始化】: 1)新建一个Maven的webapp项目 2)check out 版本库中新建的repository项目到本地,加入check out 下来的内容到新建的webapp项目中,整合后,做本地初始化提交 2. 【2.开发环境搭建,添加所需依赖,测试程序启动是否成功】: 1)更改pom.xml文件,如,修改为1.8,并删除不需要的东西 2)在pom.xml添加所需的依赖 3)引入了tomcat的插件,然后就不需要额外配置tomcat服务器了,只需要配置运行时的参数 tomcat7:run 就可以运行了,在这个依赖中修改端口号和项目访问站点名 4)配置maven的启动命令是 tomcat7:run,当然也可以直接在右边的maven中,找到tomcat插件的命令,双击运行启动项目 3. 【3.1)添加代码分层:web(控制层)、service(业务逻辑层)、dao(数据库操作层)、po(实体层)、util(各种工具类) 2)添加数据库配置文件:db.properties 3)编写数据库连接工具类 DBUtil】: 1)web、service、dao、po、util 2)编写了数据库连接工具类DBUtil,包含了获取数据库连接和关闭连接的方法 4. 【3.1)单元测试的编写 2)修改pom.xml日志依赖 3)添加log4j配置文件】: 1)单元的测试数据库连接是否成功 2)这里添加的是log4j的日志依赖 5. 【5.在webapp目录下新建static目录,添加需要的静态资源】 1)包括bootstrap前端框架、echarts报表、图片、sweetalert弹出框、ueditor富文本框等的一些静态资源 6. 【6.实现登录页前端校验、添加一个隐藏域标志,用来用来不用写这么多servlet、更新read.me】 1)html页面转jsp页面,并修改资源路径 2)添加登录表单,修改表单属性 3)登录表单前端校验,其他js文件的引入,JQuery的简单操作(获取属性值、设置html内容、提交表单等) 7. 【7.用户登录模块实现思路,写在了txt文件中、login.jsp页面增加了少许内容】 1)txt文件中有详细的实现思路,我们在写代码的过程中也可以大概写个实现流程,按照流程写代码即可 8. 【8.登录页面后台代码的实现、更新read.me】 1)更新read.me说明 2)使用lombok时,需要在IDEA中安装lombok插件,还需要添加lombok依赖 3)新建测试类,编写测试方法时,要将注解 @Test 加在测试的方法上面 4)在<%@ page %>指令中可以通过设置 isELIgnored 属性来确定是否支持el表达式 5)在登录页通过el表达式,直接取设置好的提示信息,如:${resultInfo.msg} 6)登录数据回显,即登录不成功时,不要把用户输入的登录信息清空了 7)点击取消按钮,清空输入数据的处理,使用JQuery即可 8)到这里记住密码时,存在 cookie 里的值还是明文,还需要处理 9. 【9.抽取BaseDao类】 1)更新操作(添加、修改、删除) 2)查询操作(查询一个字段、查询集合(这里要用到反射,这里要好好理解一下)、查询某个对象) 3)修改原先的登录查询,改为使用BaseDao类来进行查询 4)测试使用BaseDao类的更新操作方法,是否能成功添加数据 10. 【10.修改云记主页面index.jsp,实现动态的获取右侧的内容,通过后台实现】 1)index.jsp中,动态包含其他页面<jsp:include> 通过后台去设置 2)通过一个新的IndexServlet控制器,可以额外的设置其他的内容,如:设置请求域参数,然后请求转发到最终的页面 11. 【11.通过过滤器Filter,解决字符乱码问题】 1)通过重写底层代码来实现,使用了内部类 2)注意导包时,不要导错了 12. 【12.非法访问拦截LoginAccessFilter】 1)指定页面、静态资源、指定行为、登录状态都需要放行 2)项目根目录下新建database目录,加入数据库脚本文件 3)测试时,不要忘了清除一下网页缓存 13. 【13.用户免登录,即记住密码,自动登录】 1)在请求地址中拼接请求参数后,使用请求转发并不能在目标userServlet中获取到请求地址中携带的拼接参数,我就改为了使用重定向response.sendRedirect(url),改为后就可行了 2)主要的内容是获取并操作Cookie,然后拼接请求参数,跳转页面 14. 【14.用户退出操作】 1)用户退出后需要清除session和cookie,然后重定向到登录页面 2)webapp->项目思路 文件夹里有详细的实现说明过程 15. 【15.进入个人中心】 1)出现el表达式不能识别的情况,在<%@page %>指令中添加属性isELIgnored="false",不忽略el表达式 2)设置顶部菜单选中时高亮 16. 【16.请求加载头像】 1)通过image标签的src属性请求加载头像(即获取图像也是一次请求),--这里设置非常的微妙--,就像是请一个页面一样,不过这里请求返回的是图像 2)根据不同图片的后缀,设置不同的响应的类型 17. 【17.修改昵称时,验证昵称的唯一性(前端实现)】 1)前端使用文本框的失焦事件blur和聚焦事件focus来判断,并使用jquery的ajax发送请求获取数据验证 18. 【18.验证昵称的唯一性(后端实现)】 1)验证时需要把自己排除掉 19. 【19.修改用户信息(前端思路实现)和(后端代码实现)】 1)文件上次表单:表单类型 enctype="multipart/form-data" 2)这里需要注意input标签为type=submit时,onclick点击事件的写法方式不同 3)文件上传,需要在提交到的servlet中添加注解 @MultipartConfig 4)如果service层需要用到request对象,那么可以在servlet层中传过来 5)上传文件的操作较复杂,通过字符串的截取subString()来获取需要的内容 20. 【20.查询类型列表(后端代码实现)】 1)使用ajax请求,要用流的方式响应返回 2)注意这里actionName用户行为请求参数的使用 21. 【21.修复个人中心,点击修改按钮成功后,刷新页面出现空白页的情况】 1)因为修改成功后,地址是 (http://localhost:8080/note/user),因为地址要为(http://localhost:8080/note/user?actionName=userCenter)才不会出现问题,所有要保证表单提交的地址为:action="user?actionName=userCenter",所有就有了这次的修改 2)主要通过设置一个标志来判断 3)这里要注意,请求转发之后,地址是不会改变的,即还是原来的请求地址 22. 【22.查询类型列表(前端代码实现)】 1)使用JSTL的<c:if>做判断,<c:foreach>做遍历操作 2)IDEA中保存了我们本地修改文件的记录,只需要右击相应文件,选择Local History->Show History即可查看 3)别忘了在jsp页面中的<%@page %>指令添加属性 isELIgnored="false",这样才能使用EL表达式 23. 【23.类别管理-删除类型(后端思路分析)和(后端代码实现)】 1)通过ajax响应数据,并把数据转为json格式,方便解析 2)封装转换成json的工具类 3)这里多做了一层的判断,即在删除之前判断是否有子记录,如果有,则不删除 24. 【24.类别管理-删除类型(前端思路分析)和(前端代码实现)】 1)该模块后端较为简单,复杂的在于前端js,因为会涉及到ajax请求和DOM操作 2)修改引入sweetalert2.min.js显示提示框的错误路径问题 3)类别删除逻辑完成,但左侧同步删除的云记类别还未实现逻辑 4)通过<tr id="tr_${item.typeId}">这样的标识来确定每一个类别行,方便操作指定行,如删除等 25. 【25.类别管理-添加或修改类型(打开添加或修改类型的模态框)】 1)使用的是BootStrap的模态框,在菜鸟教程或官网找到想要的样式直接copy过来即可 2)给修改和添加类别按钮,添加onclick点击事件,打开模态框,并设置模态框的标题等内容 3)这里通过JQuery操作DOM元素,来获取表格中格子的内容,设置到模态框中,这个还是重要的 26. 【26.类别管理-添加或修改类型(发送AJAX请求)】 1)这里发送AJAX请求是使用JQuery封装好的,直接使用就很方便 27. 【27.类别管理-添加或修改类型(后端思路分析)】 28. 【28.类别管理-添加或修改类型(后端代码实现)】 1)尽管前端已经做了判空的操作,但后台还是要对相关数据进行判空操作 2)注意返回主键时,预编译的写法:preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 然后通过 resultSet = preparedStatement.getGeneratedKeys(); 获取主键的结果集 29. 【29.类别管理-添加或修改类型(修改类型的DOM操作)】 1)修复模态框提示信息不消失的情况 2)通过JQuery操作DOM来实现 3)通过给左侧类型分组导航栏的列表项要显示的值加上一个标签,方便我们操作他显示数据 30. 【30.类别管理-添加或修改类型(添加类型的DOM操作)】 1)添加类型个更新table时需要拼接tr行记录,然后追加到table中,就显示完成了,这是一个要点 2)拼接tr行记录的时候,注意新增第一条记录的情况,这里的拼接内容不同 3)左侧类型分组导航栏的列表项,也同样是通过拼接html页面代码,然后通过JQuery来追加显示 31. 【31.进入发布云记页面代码实现(1)】 1)Note实体类中,发布时间的类型是Date 2)把需要的html页面添加进来并转为jsp页面 3)发布云记右侧页面,获取类型列表展示下拉框数据完成 4)把所需要的servlet、service、dao层的文件创建完成,待完成代码 32. 【32.进入发布云记页面代码实现(2)】 1)修复发布云记右侧页面类型列表显示 33. 【33.加载富文本编辑器】 1)设置首页发布云记导航选项高亮 2)将下载好的富文本编辑器的相关jar包依赖加入到pom.xml文件中,在WEB-INF目录下,新建lib目录,将json.jar与ueditor-1.1.2.jar的jar包拷贝进去 3)然后配置富文本编辑器ueditor的ueditor.config.js文件,设置项目的路径的ueditor,具体配置看思路分析 4)第一次运行加载富文本编辑器时,加载不出来,清空一下浏览器缓存就好了 34. 【34.发布云记(前端代码实现)】 1)在<input>隐藏域中设置用户的行为actionName 2)前端参数的非空判断 35. 【35.发布云记(后端代码实现)】 1)后端代码也需要对参数进行判空的处理 2)云记保存失败时,需要设置回显,即失败后不清空输入的内容 3)JSTL的<c:if>等标签可以直接放进到html标签的属性设置区那里 4)这里也存在保存失败,再次请求转发到该页面时,由于请求地址还是提交后的地址 http://localhost:8080/note/note 不会改变,所以重新刷新就出出现空白页面了,我们在下个提交里修复 36. 【36.发布云记失败时,刷新页面出现空白页的修复】 1)修复完成,这使用的修复方法和修复个人中心出现的问题一样,都要保持他们请求转发前后的地址不变, 37. 【37.Page分页工具类】 1)封装分页的工具类Page 38. 【38.分页查询云记列表(后端代码实现)】 1)这块内容主要是查询操作,需要好好的理解才行 39. 【39.分页查询云记列表(前端代码实现)】 1)这里分页查询语句不要忘了使用limit查询指定位置的数据 40. 【40.主页日期分组与云记类别分组】 1)主页头像的加载和昵称、签名的显示 2)sql语句查询是使用到了一个日期格式函数DATE_FORMAT(pubTime, '%Y年%m月'),就是这里的sql查询有点难度 3)实现主页云记日期分组展示内容 4)实现主页云记类别分组展示内容 41. 【41.多条件查询-标题查询】 1)使用concat()方法来拼接sql条件查询语句,还要注意sql语句的空格问题和limit语句要放在sql语句最后 2)实现了标题搜索查询,但云记列表查询出来后,点击页码,就又变为了所有的查询,这个问题在下面44提交中修复 42. 【42.多条件查询-日期查询】 1)这里同样使用了sql日期格式化函数date_format()来匹配查询 43. 【43.多条件查询-类型查询】 1)与上面日期查询,所使用的方法类似 44. 【44.多条件查询-分页查询】 1)修复41提交中说到的问题 2)上面设置回显的目的就是为了解决这里提到的问题 3)解决该问题的主要方式就是通过在请求地址中拼接所需要的请求参数 45. 【45.查询云记详情(后端代码实现)】 46. 【46.查询云记详情(前端代码实现)】 1)这里有个问题,就是你查询的时候,最好使用select + 具体字段名,尽量不要使用select * 来做查询,第一是会影响查询的速度,第二是当你使用反射来获取实体类的字段时,如果少于数据库中的字段,BaseDao就会出问题了 2)所以查询字段select语句,你要什么字段就查什么字段,不要再使用select * 来做查询了,而要使用 select column_name1,column_name2 from table_name 来做查询 47. 【47.删除云记(前端代码实现)】 1)弹出提示框swal()询问是否删除 2)使用ajax请求后台 3)删除成功后,使用window.location.href = "index";跳转到首页 48. 【48.删除云记(后端代码实现)】 1)ajax请求要以流的方式响应数据回来 49. 【49.修改云记】 1)这部分的细节比较多,改的东西也比较多,基本上是在原有的代码上添加修改内容 2)在js的函数中跳转到页面使用 window.location.href = "note?actionName=view¬eId=" + noteId;方法跳转 3)修复了云记列表乱序的情况使用order by pubTime desc 排序解决 4)使用JSTL核心标签库来做各种的显示判断 50. 【50.进入数据报表页面】 1)设置选中导航高亮,包含的页面值,用户的行为actionName,新建页面report/info.jsp等 51. 【51.echarts插件集成到数据报表页面中】 1)把加载柱状图的内容放到了一个方法里,方便传数据进去显示 52. 【52.加载通过月份查询云记数量的柱状图】 1)js中可以使用 console.log(result); // 打印查看效果 2)这里的数据查询,用到了之前显示日期分类和云记数量的方法 53. 【53.集成百度地图API】 1)突然发现百度地图API很好玩,很牛掰 2)添加了一些基本的控件,百度地图的demo里还有好多其他的控件,可以自己玩一玩 54. 【54.发布云记时获取用户当前位置的经纬度】 1)要点是获取到发布时的经纬度,这里是通过集成了百度地图API后来获取 2)这里引用百度地图API文件与上一个不同,这里使用的是v2.0版本 3)之前的发布云记是没有经纬度的,现在这里处理,就是在发布云记的时候把经纬度也保存在数据库中 55. 【55.百度地图显示用户地区分布的点标记(前端代码实现)】 1)使用ajax请求后台获取经纬度数据,回传到前台去展示坐标点标记 56. 【56.百度地图显示用户地区分布的点标记(后端代码实现)】 1)通过连表查询到经纬度lon,lat 57. 【57.添加展示项目图片的PICTURE.md】 58. 【58.修复【Issues01】富文本编辑器ueditor加载失败问题】 1)由于.gitignore文件配置了忽略所有的*.jar包文件,所以导致没有提交到仓库,因此,clone下来的也就没有相应的jar包 2)通过命令 (git add -f json.jar 和 git add -f ueditor-1.1.2.jar) 加上参数 -f 强制把 (json.jar 和 ueditor-1.1.2.jar 包) 添加到git中,这样就能够提交到仓库了 3)其实这里就是涉及到.gitignore配置文件如何配置忽略的问题,以及定制化忽略文件 #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)