(尚硅谷)JavaWeb新版教程09-QQZone项目总结
目录
- 1、日期和字符串之间的转化
- 1.1 JDK 8 之前的 Date 日期的格式转换
- 1.2 JDK 8之后 LocalDateTime 新日期的格式转换
- 1.3 Thymeleaf 中将 Date 日期转换为字符串
- 1.4 Thymeleaf 中将 LocalDateTime 日期转换为字符串
- 2、系统启动时访问页面
- 3、访问某 URL 执行的过程
- 3.1 前置知识
- 3.2 组件路径和查询字符串执行过程
- 4、目前 javaweb 项目开发的“套路”
- 4.1 详细步骤
- 4. 开发具体的业务模块:
- 5、使用 druid 数据库连接池
- 6、Idea 打包 jar 包
1、日期和字符串之间的转化
1.1 JDK 8 之前的 Date 日期的格式转换
Date 和 String 之间的转换 API:
// String -> java.util.Date
String dateStr1 = "2021-12-30 12:59:59";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {Date date1 = sdf.parse(dateStr1);
} catch (ParseException e) {e.printStackTrace();
}// Date -> String
Date date2 = new Date();
String dateStr2 = sdf.format(date2);
1.2 JDK 8之后 LocalDateTime 新日期的格式转换
只要你使用的是 MySQL 8.0 之后版本的数据库,里面的时间格式已经改成了 LocalDateTime,之前项目中涉及到的日期均需要改成 LocalDateTime 类型的。
参考文献:java8 — 新日期时间API篇,包括之前的所有相关的 LocalDateTime 内容都可以参考这篇文章。
LocalDateTime 和 String 之间的格式转换:
//java.time.LocalDateTime -> String
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateStr = formatter.format(date);
System.out.println(dateStr);System.out.println("-----------------------------------");
//String -> java.time.LocalDateTime
String datetime = "2020-01-13 21:27:30";
LocalDateTime ldt = LocalDateTime.parse(datetime, formatter);
System.out.println(ldt);
1.3 Thymeleaf 中将 Date 日期转换为字符串
thymeleaf中使用#dates这个公共的内置对象:
th:text="${#dates.format(topic.topicDate ,'yyyy-MM-dd HH:mm:ss')}"
1.4 Thymeleaf 中将 LocalDateTime 日期转换为字符串
但是,查找相关资料,将 LocalDateTime 日期转换为字符串均需要进行 maven 配置,所以这里暂时先不对日期格式进行转化。
th:text="${#temporals.format(localDateTime, 'dd-MM-yyyy HH:mm:ss')}"
参考文献:用thymeleaf将LocalDateTime类型的日期格式化为yyyy-MM-dd hh:mm:ss
2、系统启动时访问页面
- 系统启动时,我们访问的页面是:
http://localhost:8080/pro23/page.do?operate=page&page=login
- 为什么不是:
http://localhost:8080/pro23/login.html
- 答: 如果是后者,那么属于直接访问静态页面。那么页面上的 thymeleaf 表达式浏览器是不能识别的;我们访问前者的目的其实就是要执行
ViewBaseServlet
中的processTemplete()
,也就是说,我们要经过 PageController 去访问后端进行视图渲染的组件,而不能直接访问静态页面。
3、访问某 URL 执行的过程
http://localhost:8080/pro23/page.do?operate=page&page=login
访问这个URL,执行的过程是什么样的?
3.1 前置知识
ServerIP(服务器端的 IP 地址):怎么保证访问你的服务器,不是访问别人的服务器嘞,要把域名地址解析成一个 IP 地址,每一台服务器都在网络上有唯一的 IP 地址。
URL 地址各个部分对应的含义如下面表格所示:
URL 地址 | http:// | localhost | :8080 | /pro23 | /page.do | ?operate=page&page=login |
---|---|---|---|---|---|---|
各部分含义 | 协议 | ServerIP | port | context root(根目录) | request.getServletPath() | query string |
3.2 组件路径和查询字符串执行过程
- DispatcherServlet 组件的 URL 映射表 urlPattern 为
*.do
拦截/page.do
; - 中央控制器中的
request.getServletPath()
得到/page.do
这个字符串; - 中央控制器解析处理字符串,将
/page.do
转化成page
; - 拿到 page 这个字符串,然后去 IOC 容器(
BeanFactory
)中寻找id=page
的那个 bean 对象,然后我们就可以找到PageController.java
这个 class 类; - 获取
operate
的值,这里是page
方法,因此得知,应该执行PageController
中的page()
方法; - PageController 中的 page 方法定义如下:
public String page(String page){return page ;
}
- 在 queryString:
?operate=page&page=login
中获取请求参数,参数名是page
,参数值是login
,因此 page 方法传入的形参 page 值会被赋上"login"
,然后return "login"
, return 给 谁?? - 因为 PageController 的 page 方法是 DispatcherServlet 通过反射调用的
method.invoke(....) ;
,因此,字符串 “login” 返回给中央控制器DispatcherServlet
; - DispatcherServlet 接收到返回值,然后处理视图:
目前处理视图的方式有两种: 1. 带前缀redirect: 2. 不带前缀
当前,返回 “login”,不带前缀
那么直接执行视图渲染操作:super.processTemplate("login",request,response);
- 此时 ViewBaseServlet 中的 processTemplate 方法会执行,会帮助我们设置前缀、设置后缀、封装成 templateEngine 引擎,然后这个引擎帮我们工作,执行 process 方法 ,效果是:
在 “login” 这个字符串前面拼接"/"
(其实就是配置文件中 view-prefixe 配置的值)
在"login"这个字符串后面拼接".html"
(其实就是配置文件中 view-suffix 配置的值) - 最后进行服务器转发,属于内部转发。
4、目前 javaweb 项目开发的“套路”
4.1 详细步骤
- 导入
myssm.jar
包,这里也可以选择直接复制粘贴整个 myssm 文件夹到下一个项目,后面会对 myssm 中封装好的 DispatcherServlet 进行修改; - 新建配置文件
applicationContext.xml
或者可以不叫这个名字,在 web.xml 中指定文件名 - 在
web.xml
文件中配置:
- 配置前缀和后缀,这样 thymeleaf 引擎就可以根据我们返回的字符串进行拼接,再跳转
<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.xml</param-value>
</context-param>
4. 开发具体的业务模块:
(1)一个具体的业务模块纵向上由几个部分组成
- html 页面
- POJO 类
- DAO 接口和实现类
- Service 接口和实现类
- Controller 控制器组件
(2)如果 html 页面有 thymeleaf 表达式,一定不能够直接访问,必须要经过 PageController
(3)在 applicationContext.xml 中配置 DAO、Service、Controller,以及三者之间的依赖关系
(4)DAO 实现类中 , 继承 BaseDAO,然后实现具体的接口, 需要注意, BaseDAO 后面的泛型不能写错。
例如:
public class UserDAOImpl extends BaseDAO<User> implements UserDAO{}
(5)Service 是业务控制类,这一层我们只需要记住一点:
- 业务逻辑我们都封装在 service 这一层,不要分散在 Controller 层,也不要出现在 DAO 层(我们需要保证 DAO 方法的单精度特性)
- 当某一个业务功能需要使用其他模块的业务功能时,尽量的调用别人的 service,而不是深入到其他模块的 DAO 细节
(6)Controller 类的编写规则
- 在 applicationContext.xml 中配置
Controller <bean id="user" class="com.atguigu.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"><inut type="hidden" name="operate" value="login"/>
</form>
- 在表单中,组件的 name 属性和 Controller 中方法的参数名一致
<input type="text" name="loginId" />
public String login(String loginId , String pwd , HttpSession session){
- 另外,需要注意的是: Controller 中的方法中的参数不一定都是通过请求参数获取的,要除去浏览器发送请求自带的的参数,比如请求、响应、session 等
if("request".equals...) else if("response".equals....) else if("session".equals....){直接赋值
}else{此处才是从request的请求参数中获取request.getParameter("loginId") .....
}
(7)DispatcherServlet中步骤大致分为:
- 初始化方法中:从 application 作用域获取 IOC 容器
- 解析 servletPath , 在 IOC 容器中寻找对应的 Controller 组件
- 准备 operate 指定的方法所要求的参数
- 调用 operate 指定的方法
- 接收到执行 operate 指定的方法的返回值,对返回值进行处理 - 视图处理
(8)为什么 DispatcherServlet 能够从 application 作用域获取到 IOC 容器?
ContextLoaderListener
在容器启动时会执行初始化任务,而它的操作就是:
- 解析 IOC 的配置文件,创建一个一个的组件,并完成组件之间依赖关系的注入;
- 将 IOC 容器保存到 application 作用域。
5、使用 druid 数据库连接池
修改 BaseDAO,让其支持 propertie s文件以及 druid 数据源连接池,这里老师讲了两种方式,也不太清晰,具体的可以看我之前的 JDBC 中有关讲解:(尚硅谷)JDBC总复习
- 新建一个 jdbc.properties 配置文件放置在 src 文件夹下:
配置文件的内容,这里的每一对配置中的 key 是固定格式的,不可以修改:
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/qqzonedb?useUnicode=true&characterEncoding=utf-8&useSSL=false
username=root
password=abc123# 初始化时建立物理连接的个数
initialSize=5
# 最大连接池数量
maxActive=10
# 最大等待时间
maxWait=3000
- 将 ConnUtil 获取连接的文件修改为:
public class ConnUtil {private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();/*** 使用Druid数据库连接池技术*/private static DataSource source;static{try {Properties pros = new Properties();InputStream is = ConnUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");pros.load(is);source = DruidDataSourceFactory.createDataSource(pros);} catch (Exception e) {e.printStackTrace();}}private static Connection createConn(){try {// //1.加载驱动
// Class.forName(DRIVER);
// //2.通过驱动管理器获取连接对象
// return DriverManager.getConnection(URL,USER,PWD);return source.getConnection();} catch (SQLException e) {e.printStackTrace();}return null ;}public static Connection getConn(){Connection conn = threadLocal.get();if(conn==null){conn =createConn();threadLocal.set(conn);}return threadLocal.get() ;}public static void closeConn() throws SQLException {Connection conn = threadLocal.get();if(conn==null){return ;}if(!conn.isClosed()){conn.close();//threadLocal.set(null);threadLocal.remove();}}
}
注意:
- 这里的这个
private static DataSource source;
要放置在createConn()
方法外面,而不是像老师那样放置在方法内部,这样才能保证初始加载我们只创建了一个数据库连接池,而不是每次连接都创建一个数据库连接池(这样会更慢)。 - 这边需要将康师傅讲的 将
ClassLoader.getSystemClassLoader().getResourceAsStream()
变成ConnUtil.class.getClassLoader().getResourceAsStream();
,否则就会报 500 错误,读取不到流文件,具体原因呢还不清楚为什么获取系统类加载器不可以,之后看完反射回来再说。
6、Idea 打包 jar 包
具体打包方法看 尚硅谷丨2022版JavaWeb教程(全新技术栈,全程实战),P68 18.00开始讲解如何打包的。
注意:
- 但是这里不建议删除,不建议打包,因为后面还要对这个 myssm 包内的文件进行修改,毕竟手写的不如人家框架里面封装好的考虑的全面,直接复制粘贴到下一个项目就可以了。
(尚硅谷)JavaWeb新版教程09-QQZone项目总结相关推荐
- 尚硅谷Nginx新版升级教程,带你轻松掌握高并发系统架构
摘要:桃李春风一杯酒,江湖夜雨十年灯. "你说有没有一种可能, "你喜欢我,又不好意思说出口, "其实你可以直接说出来的, "我会让你知道什么叫心想事成.&qu ...
- 尚硅谷最新版JavaScript基础全套教程完整版(p79-p90)
尚硅谷最新版JavaScript基础全套教程完整版(140集实战教学,JS从入门到精通) 一.函数的方法 1.call()和 apply()方法 -这两个方法都是函数对象方法,需要通过函数对象来调用 ...
- 04 frameset-iframe【尚硅谷JavaWeb教程】
04 frameset-iframe[尚硅谷JavaWeb教程] JAVAWEB的学习笔记 学习视频来自:https://www.bilibili.com/video/BV1AS4y177xJ/?vd ...
- 06 CSS-盒子模型【尚硅谷JavaWeb教程】
06 CSS-盒子模型[尚硅谷JavaWeb教程] JAVAWEB的学习笔记 学习视频来自:https://www.bilibili.com/video/BV1AS4y177xJ/?vd_source ...
- JavaScript(基础、高级)笔记汇总表【尚硅谷JavaScript全套教程完整版】
目 录 前言 JavaScript(基础+高级)配套资料下载 JavaScript 基础 学习地址 学习笔记 day 05(P001-P006)[2016.11.22] day 06(P007-P ...
- 尚硅谷JavaScript高级教程(javascript实战进阶)学习笔记
前言 这个是我学习过程中的笔记,分享给大家,希望对大家有用. 学习内容是尚硅谷JavaScript高级教程(javascript实战进阶),这里是视频链接. 我在前面有两篇对于web前端HTML和CS ...
- 尚硅谷Redis6基础教程-秒杀案例中库存遗留问题
尚硅谷redis6基础教程中视频24-27的秒杀案例,使用Redis乐观锁解决了超卖问题,但是也产生了库存遗留问题.引入Lua脚本,解决了超卖和库存遗留.Lua脚本为什么解决了库存遗留问题???
- 尚硅谷Docker实战教程-笔记02【安装docker、镜像加速器配置】
尚硅谷大数据技术-教程-学习路线-笔记汇总表[课程资料下载] 视频地址:尚硅谷Docker实战教程(docker教程天花板)_哔哩哔哩_bilibili 尚硅谷Docker实战教程-笔记01[理念简介 ...
- Vue数据代理+事件处理+事件修饰符的作用+计算属性的使用,尚硅谷Vue系列教程学习笔记(2)
尚硅谷Vue系列教程学习笔记(2) 参考课程:<尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通> 参考链接:https://www.bilibili.com/video/ ...
最新文章
- java反射机制知识_Java反射机制讲解,程序员必须掌握的知识点
- nokia android 8,疑似诺基亚8再曝光:预装Android 8.0系统
- html旋转代码_用CSS实现一个抽奖转盘(附详细代码+思路)
- 01_基于应用拆分的技术架构
- 64位java_一文详解 Java 的八大基本类型!
- linux 验证邮箱账号,linux邮件服务器的身份验证(sasl)
- 统计mysql里每条SQL语句执行的时间
- System V 共享内存 和 系列函数
- 40.服务器搭建准备
- matlab界面语言修改
- 计算机机房需求调查表,机房建设需求调查表机房建设需求调查表.doc
- u盘遭受蠕虫 特洛伊木马攻击文件隐藏的解决办法
- [裴礼文数学分析中的典型问题与方法习题参考解答]5.1.13
- 使用hexo+github搭建免费个人博客详细教程
- itunes备份电脑C盘内存不够怎么办?
- imitate wechat - 1
- DGZX1564 - 水塔水位
- 百利天恒更新招股书:上半年收入约3亿元,持续加大研发投入
- excel数据分析--仪表板制作
- guid和mbr格式的区别;32位和64位操作系统的区别。