版本

  1. MySQL: 8.02
  2. Tomcat :9.0.64
  3. JDK:11
  4. Maven:3.014 (Thymeleaf)
  5. idea:2021.032

MySQL8.0设置

  • 保存在jdbc.properties即可
1
2
3
4
public static final String DRIVER = "com.mysql.cj.jdbc.Driver" ;
public static final String URL ="jdbc:mysql://localhost:3306/*****?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&useSSL=false";
public static final String USER = "root";
public static final String PWD = "*********" ;

Edit水果信息执行顺序

点击名称,
img
, 然后把fid发送给EditServlet

image-20220710194328833,EditServlet 内通过fid查找数据并保存(setAttribute ),然后EditServlet 跳转到 edit.html , 通过thymeleaf 获取 对象并填入 数据

image-20220710194308175

,修改好之后 点击 修改(实际是一个form表单) 提交表单,
img
,将数据发送给updateServlet, updateServlet内完成 数据库的更新 ,然后跳转到index(经过thymeleaf渲染的界面,而不是直接index.html) , 修改操作完成



requests传参⚠️parameters

image-20220707212212581

注意添加 -parameters,否则请求发过来的参数就会是arg0 ,arg1,arg2 ,arg3s…………, 无法获得具体的名称(导致参数全部为null , 无法加载页面,

原因:

private String index(String oper , String keyword , Integer pageNo , HttpServletRequest request )

  • FruitController index()方法在执行时 ,参数全部为空, 无法通过null的 request对象获取session,也就无法保存(setAttribute)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    private String index(String oper , String keyword , Integer pageNo , HttpServletRequest request ) {
    HttpSession session = request.getSession() ;
    if(pageNo==null){
    pageNo = 1;
    }
    if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
    pageNo = 1 ;
    if(StringUtil.isEmpty(keyword)){
    keyword = "" ;
    }
    session.setAttribute("keyword",keyword);
    }else{
    Object keywordObj = session.getAttribute("keyword");
    if(keywordObj!=null){
    keyword = (String)keywordObj ;
    }else{
    keyword = "" ;
    }
    }
    // 重新更新当前页的值
    session.setAttribute("pageNo",pageNo);
    List<Fruit> fruitList = fruitService.getFruitList(keyword , pageNo);
    session.setAttribute("fruitList",fruitList);

    //总记录条数
    int pageCount = fruitService.getPageCount(keyword);
    session.setAttribute("pageCount",pageCount);

    return "index" ;
    }

完成这个操作后,获得到了具体的实参名称

image-20220707212507505

可以正确加载页面!!!!

qqzone项目增加添加日志功能

—ByMyself

thymeleaf ||

thymeleaf 表达式里面的 被 | | 包裹住的内容表示里面是一个普通字符串

被${ }包裹住的是表达式,

比如:

@{|/addTopic.do?operate=addTopic&userBasicId=${session.userBasic.id}|}

@{|/updateTopic.do?operate=updateTopic&userBasicId=${session.userBasic.id}|}

由于这是一个字符串 ,所以不用 再用’ 包裹operate 的值

发送请求时 就是http://localhost:8080/pro22/addTopic.do?operate=addTopic&userBasicId=1

主要增加了

  1. addTopic.html

    • <a th:href="@{|/addTopic.do?operate=addTopic&userBasicId=${session.userBasic.id}|}" class="right8" target="_blank" >发表新日志</a>
    • a标签向后端传值
  2. addTopic 方法 :

    • TopicController

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public String addTopic(Integer userBasicId,HttpSession session){ 
      // 跳转到 addTopic.html 填入内容
      UserBasic userBasic = userBasicDAO.getUserBasicById(userBasicId);
      session.setAttribute("userBasic",userBasic);
      return "frames/addTopic";
      }
      public String updateTopic(String title, String content,Integer Id,HttpSession session)
      {
      // 通过 DispacherServlet 接收来自addTopic.html的数据 ,并保存到数据库
      UserBasic author=(UserBasic)session.getAttribute("userBasic");
      Topic topic=new Topic(content,new Date(),title,Id,author);
      topicDAO.addTopic(topic);
      return "redirect:user.do?operate=login&loginId="+author.getLoginId()+"&pwd="+author.getPwd();
      /* return "index"; 直接返回index 就不会登录,无法显示个人信息(账号, 以及日志等)*/
      }
    • TopicDAOImpl

      1
      2
      3
      4
      5
      6
      7
      8
      9
      @Override
      public void addTopic(Topic topic) {
      executeUpdate("insert into t_reply values(?,?,?,?,?)",
      topic.getId(),
      topic.getTitle(),
      topic.getContent(),
      topic.getTopicDate(),
      topic.getAuthor().getId()) ;
      }
  3. 大概执行顺序

    1. 在main.html点击发表新日志

      <a th:href="@{/addTopic.do}" class="right8" >发表新日志2</a>

    2. DispacherServlet接收/addTopic.do请求, 从请求中获取operate(此处是 addTopic) ,调用TopicController(通过beanFactory获取)addTopic方法,

    3. DispacherServle接收addTopic方法的返回值(String returnStr = method.invoke(controllerBeanObj,parameterValues)😉,然后通过thymeleaf模板引擎加载前端页面

    4. 在addTopic.html填入数据后,点击提交,将表单(

      <form th:action="@{|/updateTopic.do?operate=updateTopic&userBasicId=${session.userBasic.id}|}">>)

      发送到DicpacherServlet,beanFactory从application.xml读取到请求对应的controller(这里就是TopicController),然后找到operate对应的方法(这里就是updateTopic方法),将数据保存到数据库,返回登录页面

      1
      return "redirect:user.do?operate=login&loginId="+author.getLoginId()+"&pwd="+author.getPwd();
      • 这里仍然是DispacherServle接收addTopic方法的返回值,然后thymeleaf模板引擎加载前端页面
    5. 添加日志操作完成

main.html

1
<a th:href="@{|/addTopic.do?operate=addTopic&userBasicId=${session.userBasic.id}|}" class="right8" target="_blank" >发表新日志</a>

addTopic.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link th:src="@{../css/addTopic.css}">
<script language="JavaScript">
/*此处写入js 代码*/
</script>
<meta charset="UTF-8">
<title>发表新日志</title>
</head>
<!--<div th:text="用户 |${session.userBasic.nickName}| 发表新日志">欢迎进入空间</div>-->

<body>

<form th:action="@{|/updateTopic.do?operate=updateTopic&userBasicId=${session.userBasic.id}|}">
<!-- "@{|/addTopic.do?operate=addTopic&userBasicId=${session.userBasic.id}|}"-->
<!--这一行 表明 要访问TopicController
<input type="hidden" name="operate" value="updateTopic"> ;这一行 表明 要调用 addTopic 方法 -->
<!-- <input type="hidden" name="userBasicId" th:value="${session.userBasic.id}"/>
将这两行 集成到 form 里面 -->

标题<input id="div_add_reply" type="text" name="title" th:value="Test" /> <br/>
日志id<input type="text" name="Id" th:value="12"/> <br/>
主要内容<input type="text" name="content" th:value="主要内容"/> <br/>
<input type="submit" value="添加日志"/> <br/>
<!-- <input type="button" value="删除" th:if="${session.userBasic.id==session.friend.id}" th:onclick="|delTopic(${topic.id})|"/>-->

</form>
</body>
</html>

遇到的问题:

  1. addTopic方法的return "frames/detail";的frames 没有写s
  2. 执行的顺序应该是main.html 点击添加,发送请求, 然后执行addTopic 跳转到addTopic.html,在addTopic.html修改完成后,提交form表单,发送请求到TopicController的updateTopic,在uodateTopic内将数据保存到数据库
    • 第一次写的时候直接在addTopic方法里保存到数据库,但那是明显不可行的
  3. TopicDAOImpl 的addTopic 方法需要插入的表写错了,导致日期格式不正确
    • insert into t_topic 写成了 insert into t_reply

qqzone bug1

setValue方法在给 topicprivate Date topicDate ; 赋值时 出现异常:

  • Can not set java.util.Date field com.atguigu.qqzone.pojo.Topic.topicDate to java.time.LocalDateTime

  • 无法将LocalDateTime类型数据赋值给Date类型变量

原因 :应该属于mysql8.0驱动的bug,具体原因未知

正常情况下从表中查出datetime类型如下
在这里插入图片描述
出现bug时类型为LocalDateTime,值为2017-07-15T00:16:40.0,与pojo属性类型不匹配
在这里插入图片描述

采用的解决方法是在属性赋值前(setValue)进行类型检查,如果是LocalDateTime类型就转换成java.util.Date类型

  • 正确的代码已经在上面改过了
  • 注意 :propertyValue=(Date)propertyValue; 直接转换会==报错==
    • class java.time.LocalDateTime cannot be cast to class java.util.Date (java.time.LocalDateTime and java.util.Date are in module java.base of loader 'bootstrap')
1
2
3
4
5
if (propertyValue.getClass().toString().equals("class java.time.LocalDateTime"))
//实际测试使用 if(propertyValue instanceof LocalDateTime) 也可以
{
propertyValue = Timestamp.valueOf((LocalDateTime) propertyValue);
}

==bug==解除,可以正常加载页面

遇到的问题

总结:java的properties文件赋值不要写分号,会一起读取进去

==背景==:在将登录MySQL需要用到的数据封装到jdbc.properties时,

  • 通过静态代码块,加载类时自动执行(读取jdbc.properties中的数据)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static  String DRIVER ;
public static String URL;
public static String USER ;
public static String PWD ;

static {
InputStream is = ConnUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties=new Properties();
try {
properties.load(is);
DRIVER= properties.getProperty("jdbc.DRIVER");
URL= properties.getProperty("jdbc.URL");
USER= properties.getProperty("jdbc.USER");
PWD= properties.getProperty("jdbc.PWD");
} catch (IOException e) {
e.printStackTrace();
}
}

==异常==:出现加载驱动错误

  • java.sql.SQLException: No suitable driver found for "jdbc:mysql://localhost:3306/qqzonedb2?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&useSSL=false";

==原因==:java的properties文件不能写分号

  • properties在load()时会将分号一起读取进去

    exception

    image-20220710124815097

    • 因为jdbc.properties配置文件中的jdbc.DRIVER后面带了一个分号,所以通过load获取的Driver也有一个分号(上面的debug图片)

    • 注意上面的异常最后也是带了一个分号

删去分号,问题解决

Controller 内 DAOImpl or Service 对象不需要初始化的原因

在application注册

1
2
<bean id="user" class="com.atguigu.book.controller.UserController">
<property name="userService" ref="userService"/>

下面的property , 就是给UserController 内的 userService 初始化 ,直接UserService userService ;就行,不需要再new UserService();