(尚硅谷)JavaWeb新版教程09-QQZone项目总结


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、系统启动时访问页面

  1. 系统启动时,我们访问的页面是: http://localhost:8080/pro23/page.do?operate=page&page=login
  2. 为什么不是: http://localhost:8080/pro23/login.html
  3. 答: 如果是后者,那么属于直接访问静态页面。那么页面上的 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
各部分含义协议ServerIPportcontext root(根目录)request.getServletPath()query string

3.2 组件路径和查询字符串执行过程

  1. DispatcherServlet 组件的 URL 映射表 urlPattern 为 *.do 拦截 /page.do
  2. 中央控制器中的 request.getServletPath() 得到 /page.do 这个字符串;
  3. 中央控制器解析处理字符串,将 /page.do 转化成 page
  4. 拿到 page 这个字符串,然后去 IOC 容器(BeanFactory)中寻找 id=page 的那个 bean 对象,然后我们就可以找到 PageController.java 这个 class 类;
  5. 获取 operate 的值,这里是 page 方法,因此得知,应该执行 PageController 中的 page() 方法;
  6. PageController 中的 page 方法定义如下:
public String page(String page){
return page ;
}
  1. 在 queryString: ?operate=page&page=login 中获取请求参数,参数名是 page,参数值是 login,因此 page 方法传入的形参 page 值会被赋上 "login" ,然后 return "login" , return 给 谁??
  2. 因为 PageController 的 page 方法是 DispatcherServlet 通过反射调用的
    method.invoke(....) ;,因此,字符串 “login” 返回给中央控制器 DispatcherServlet
  3. DispatcherServlet 接收到返回值,然后处理视图:
    目前处理视图的方式有两种: 1. 带前缀redirect: 2. 不带前缀
    当前,返回 “login”,不带前缀
    那么直接执行视图渲染操作:super.processTemplate("login",request,response);
  4. 此时 ViewBaseServlet 中的 processTemplate 方法会执行,会帮助我们设置前缀、设置后缀、封装成 templateEngine 引擎,然后这个引擎帮我们工作,执行 process 方法 ,效果是:
    在 “login” 这个字符串前面拼接 "/" (其实就是配置文件中 view-prefixe 配置的值)
    在"login"这个字符串后面拼接 ".html" (其实就是配置文件中 view-suffix 配置的值)
  5. 最后进行服务器转发,属于内部转发。

4、目前 javaweb 项目开发的“套路”

4.1 详细步骤

  1. 导入 myssm.jar 包,这里也可以选择直接复制粘贴整个 myssm 文件夹到下一个项目,后面会对 myssm 中封装好的 DispatcherServlet 进行修改;
  2. 新建配置文件 applicationContext.xml 或者可以不叫这个名字,在 web.xml 中指定文件名
  3. 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 类的编写规则

  1. 在 applicationContext.xml 中配置 Controller <bean id="user" class="com.atguigu.qqzone.controllers.UserController>
    那么,用户在前端发请求时,对应的 servletpath 就是 /user.do ,其中的 “user” 就是对应此处的 bean 的 id
  2. 在 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>
  1. 在表单中,组件的 name 属性和 Controller 中方法的参数名一致
<input type="text" name="loginId" />
public String login(String loginId , String pwd , HttpSession session){
  1. 另外,需要注意的是: Controller 中的方法中的参数不一定都是通过请求参数获取的,要除去浏览器发送请求自带的的参数,比如请求、响应、session 等
if("request".equals...) else if("response".equals....) else if("session".equals....){
	直接赋值
}else{
	此处才是从request的请求参数中获取
	request.getParameter("loginId") .....
}

(7)DispatcherServlet中步骤大致分为:

  1. 初始化方法中:从 application 作用域获取 IOC 容器
  2. 解析 servletPath , 在 IOC 容器中寻找对应的 Controller 组件
  3. 准备 operate 指定的方法所要求的参数
  4. 调用 operate 指定的方法
  5. 接收到执行 operate 指定的方法的返回值,对返回值进行处理 - 视图处理

(8)为什么 DispatcherServlet 能够从 application 作用域获取到 IOC 容器?
ContextLoaderListener 在容器启动时会执行初始化任务,而它的操作就是:

  1. 解析 IOC 的配置文件,创建一个一个的组件,并完成组件之间依赖关系的注入;
  2. 将 IOC 容器保存到 application 作用域。

5、使用 druid 数据库连接池

修改 BaseDAO,让其支持 propertie s文件以及 druid 数据源连接池,这里老师讲了两种方式,也不太清晰,具体的可以看我之前的 JDBC 中有关讲解:(尚硅谷)JDBC总复习

  1. 新建一个 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
  1. 将 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();
        }
    }
}

注意:

  1. 这里的这个 private static DataSource source; 要放置在 createConn() 方法外面,而不是像老师那样放置在方法内部,这样才能保证初始加载我们只创建了一个数据库连接池,而不是每次连接都创建一个数据库连接池(这样会更慢)。
  2. 这边需要将康师傅讲的 将ClassLoader.getSystemClassLoader().getResourceAsStream() 变成 ConnUtil.class.getClassLoader().getResourceAsStream();,否则就会报 500 错误,读取不到流文件,具体原因呢还不清楚为什么获取系统类加载器不可以,之后看完反射回来再说。
    在这里插入图片描述

6、Idea 打包 jar 包

具体打包方法看 尚硅谷丨2022版JavaWeb教程(全新技术栈,全程实战),P68 18.00开始讲解如何打包的。

注意:

  1. 但是这里不建议删除,不建议打包,因为后面还要对这个 myssm 包内的文件进行修改,毕竟手写的不如人家框架里面封装好的考虑的全面,直接复制粘贴到下一个项目就可以了。
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值