QQZone的review以及当前开发项目的套路

资料来源于:B站尚硅谷JavaWeb教程(全新技术栈,全程实战) ,本人才疏学浅,记录笔记以供日后回顾
视频链接

重点知识

1. http://localhost:8080/pro23/page.do?operate=page&page=login 访问这个URL,执行的过程是什么样的?
   答:
   http://  localhost   :8080   /pro23          /page.do                        ?operate=page&page=login
   协议       ServerIP   port    context root    request.getServletPath()         query string
   1) DispatcherServlet -> urlPattern :  *.do  拦截/page.do
   2) request.getServletPath() ->  /page.do
   3) 解析处理字符串,将/page.do -> page
   4) 拿到page这个字符串,然后去IOC容器(BeanFactory)中寻找id=page的那个bean对象   -> PageController.java
   5) 获取operate的值 -> page    因此得知,应该执行 PageController中的page()方法
   6) PageController中的page方法定义如下:
      public String page(String page){
        return page ;
      }
   7) 在queryString:   ?operate=page&page=login 中 获取请求参数,参数名是page,参数值是login
      因此page方法的参数page值会被赋上"login"
      然后return "login" , return 给 谁??
   8) 因为PageController的page方法是DispatcherServlet通过反射调用的
      method.invoke(....) ;
      因此,字符串"login"返回给DispatcherServlet
   9) DispatcherServlet接收到返回值,然后处理视图
      目前处理视图的方式有两种: 1.带前缀redirect:    2.不带前缀
      当前,返回"login",不带前缀
      那么执行  super.processTemplate("login",request,response);
   10) 此时ViewBaseServlet中的processTemplate方法会执行,效果是:
      在"login"这个字符串前面拼接 "/"  (其实就是配置文件中view-prefix配置的值)
      在"login"这个字符串后面拼接 ".html" (其实就是配置文件中view-suffix配置的值)
      最后进行服务器转发

2. 目前我们进行javaweb项目开发的“套路”是这样的:
   1. 拷贝 myssm包
   2. 新建配置文件applicationContext.xml或者可以不叫这个名字,在web.xml中指定文件名
   3. 在web.xml文件中配置:
      1) 配置前缀和后缀,这样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>
      2) 配置监听器要读取的参数,目的是加载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中的方法中的参数不一定都是通过请求参数获取的
          if("request".equals...) else if("response".equals....) else if("session".equals....){
            直接赋值
          }else{
            此处才是从request的请求参数中获取
            request.getParameter("loginId") .....
          }
      7)  DispatcherServlet中步骤大致分为:
          0. 从application作用域获取IOC容器
          1. 解析servletPath , 在IOC容器中寻找对应的Controller组件
          2. 准备operate指定的方法所要求的参数
          3. 调用operate指定的方法
          4. 接收到执行operate指定的方法的返回值,对返回值进行处理 - 视图处理
      8) 为什么DispatcherServlet能够从application作用域获取到IOC容器?
         ContextLoaderListener在容器启动时会执行初始化任务,而它的操作就是:
         1. 解析IOC的配置文件,创建一个一个的组件,并完成组件之间依赖关系的注入
         2. 将IOC容器保存到application作用域

其他的一些知识点

1. 日期和字符串之间的格式化
    /*
    // 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);
    */
2. thymeleaf中使用#dates这个公共的内置对象
   ${#dates.format(topic.topicDate ,'yyyy-MM-dd HH:mm:ss')}

3. 系统启动时,我们访问的页面是: http://localhost:8080/pro23/page.do?operate=page&page=login
   为什么不是: http://localhost:8080/pro23/login.html  ?
   答: 如果是后者,那么属于直接访问静态页面。那么页面上的thymeleaf表达式(标签)浏览器是不能识别的
       我们访问前者的目的其实就是要执行 ViewBaseServlet中的processTemplete()


4. 修改BaseDAO,让其支持properties文件以及druid数据源连接池
   讲解了两种方式:
   1) 直接自己配置properties,然后读取,然后加载驱动.....
   2) 使用druid连接池技术,那么properties中的key是有要求的

部分代码示例

jdbc.properties文件

该文件放在src目录下

# jdbc.driver=com.mysql.jdbc.Driver
# jdbc.url=jdbc:mysql://localhost:3306/qqzonedb?useUnicode=true&characterEncoding=utf-8&useSSL=false
# jdbc.user=root
# jdbc.pwd=123456
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/qqzonedb2?useUnicode=true&characterEncoding=utf-8&useSSL=false
username=root
password=abc123
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大超时时间
maxWait=3000

ConnUtil.java文件

使用druid连接池读取配置

package com.ypf.myssm.basedao;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class ConnUtil {

    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
    //private static ThreadLocal<Object> threadLocal2 = new ThreadLocal<>();
    //private static ThreadLocal<Object> threadLocal3 = new ThreadLocal<>();

    private  static DataSource source;
    static {
        try {
            //使用数据库连接池读取配置文件
            Properties properties = new Properties();
            InputStream is = ConnUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            properties.load(is);
            source = DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Connection createConn() {
        try {
//
//            DataSource source = DruidDataSourceFactory.createDataSource(properties);
            return source.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception 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);
        }
    }
}

IDEA中,将通用代码打成压缩包

步骤如下图所示:

修改jar包名字,点击创建目录,根据你的需求建立目录结构

根据你的需求,在右侧创建对应的目录结构

选择文件

选择你需要打包的项目的out目录下,对应class文件。全部选择完后,点击应用和确定。


项目下的out目录里就出现了打好的jar包

在项目中新建一个目录,想jar包放入,并添加引用

最后在模块中引入这个目录就可以啦

posted @   飞哥传书  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示