【javaweb笔记1】自用

javaweb笔记

  • 一、tomcat 安装
  • 1. 官网下载
    • 2.安装
    • 3.卸载
    • 4.启动
      • 5.控制台中文乱码
      • 6.闪退
        • 7.IDEA使用tomcat的maven插件
        • 7.IDEA不使用插件配置
        • maven 创建java web项目
        • 8.导入servlet依赖
        • 9.tomcat防止post方式乱码
        • 10.IDEA自动导包
        • 11.servlet 线程问题
  • 三、Servlet
    • 1.生命周期
    • 2.HTTP 协议
    • 3、Session
      • 1.快速理解
      • 2、保存作用域
      • 3、一些API
      • 4、 重定向和转发的区别
    • 4、路径问题
    • 5、servlet作用域
      • 1、request response
      • 2、session
      • 3、application
  • 四、mybatis
    • 1、依赖部分
      • 1、日志系统
      • 2、jdbc
      • 3、test junit
    • 2、配置部分
      • 1、mapper 包扫描
      • 2、类型别名
      • 3、sqlSession 工具类
      • 4、返回集写法
      • 5、名称空间
  • 五、thymeleaf
    • 1、依赖
    • 2、部分标签
    • 3、ViewBaseServle
    • 4、获取作用域参数
      • 1、session
  • 六、管理水果系统
    • 1、主页
      • 1、不用相对路径并设置根路径
      • 2、设置全局字体颜色
      • 4、直接写属性名,就是设置所有属性
      • 5、直接写属性名,就是设置所有属性
      • 6、表格边框要这么写
      • 7、表格边粗细不一
      • 8、添加图片
      • 9、合并单元格
      • 10、选中某一种类型
    • 2、编辑和修改特定库存信息
      • 1、渲染覆盖
      • 2、路径问题
      • 3、height设置不生效问题
      • 4、取消body边距无效
      • 5、get 可以发送序号过去 ?id=1
      • 6、thymeleaf 拼接属性变换
      • 7、非空判断最好写在一个工具类里面
        • 1、String 判断非空
      • 8、编辑页面里的一些问题
        • 1、我没写name,这个很重要,我编辑好了,要修改的,所以要有name去提交
        • 2、我不知道thymeleaf那个绑定变量怎么写
          • 1、原来是直接写的
          • 2、也可以这样写
      • 9、servlet映射无效
      • 10、bigDecimal 和 String 转换
      • 11、我吐了,真的,那个session 提交和关闭别忘了好不好
      • 12、更新数据后,网页数据没有变
    • 3、添加和删除数据
      • 1、display: inline-block; 无效
      • 2、display: inline-block; 无效
      • 3、取消超链接下划线
      • 4、删除
      • 5、引入js
      • 6、删除delete语句
      • 7、忘了写@WebServlet("/delete")
    • 4、分页查询
      • 1、写了分页查询没有指定返回集
      • 2、调整摁钮大小
      • 3、调整字体粗细
      • 4、我要传一个page页码过去,而不是总数
      • 5、计算页数的公式
      • 6、判断是否是摁钮不可用
    • 5、根据关键字查询
      • 1、模糊查询
      • 2、提交查询关键字
      • 3、查询库存总记录数也要考虑keyWord
      • 4、走下面需要从session中获取关键字,req里面的session没了
    • 6、总结
      • 1、记得更新session里面的数据
  • 七、MVC各个层的设计
    • 连接进来
      • Character Encoding Filter
      • Open Session InView Filter
        • ThreadLocal(难点)
      • DispatcherServlet 这里没懂的比较多,需要多敲代码
      • IOC Container
        • 用标签来指定依赖
    • 一、servlet优化1
      • 1、总体思想
      • 2、function方法怎么改
      • 3、还可以隐藏的发过去
      • 4、之前的重定向,要统一改成现在的总servlet,会通过初始值 指定到主页
      • 5、如果这里面的值都没有就说明是被手动输入了,抛出个错误
      • 6、浏览器? &
      • 7、我以为闹鬼了,点击编辑功能,他直接把数据删了,原来是把数据变成空了,然后不显示
    • servlet优化2 dispatcherServlet引入
      • 1、通过方法名 用反射实现
      • 2、默认的index
      • 3、反射的对象获取
      • 4、对象才有getClass方法,this也是对象
    • 二、servlet优化2.1 dispatcherServlet引入
      • 步骤
      • 1、setAccessible 访问private 需要这个属性
    • 2、中央控制器的概念
        • 1、实现步骤
          • 1、xml声明的固定写法
          • java操作节点的一些文档
          • 2、反射调用方法 变量居然是method
          • 3、反射调用方法 记得用这个getDeclaredMethod
          • 4、这么搞他的搜索功能是坏的,我不知道他后面是怎么解决的,之后再说吧
        • 2、我应该先敲一遍代码,然后看看老师那里翻了错误,我也跟着改
          • 1、根据请求的url获取servletPath,解析出一个名字
          • 2、解析加载配置文件,读取bean 扔到配置文件里面 (这是我几天前写的,我现在就看不懂了)
          • 3、调用controller里面的方法
      • 3、卧槽,困扰我那么久的问题终于要解决了
        • 1、因为FruitController 不是一个servlet方法了,所以不会去调用init方法
        • 2、不能自动调用,那我就自己调用
        • 3、不写构造里了,写在Init里
        • ServletContext就是最大的那个作用域
        • 4、因为我要把那个参数传进去
        • 5、还是没用的原因
        • 6、这么改
    • 三、servlet优化3 提取视图资源处理通用代码 与 统一获取参数
      • 1、重定向和转发也可以提取出来
        • 1、解决转发冗余
        • 2、search 无效 我有点NB了
        • 2、解决那个需要view的
      • 2、每一个方法都有req.getParameter这个方法,代码冗余
        • 1、解决那个需要view的
        • 2、统一抽取到父类里面 就是DispatcherServlet里面![在这里插入图片描述](https://img-blog.csdnimg.cn/942ca87f46fa438faddd1c7eca00c528.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcXFfNDI3NjU0OTM=,size_12,color_FFFFFF,t_70,g_se,x_16#pic_center)
        • 3、思考过程
          • 1、获取当前方法的参数,返回参数数组
          • 2、这里有个错误,因为之前把方法参数改了,不是每个方法都有req,resp的
          • 3、解决方法是获取所有方法,然后循环
          • 4、从JDK8 开始可以获取反射的名称
          • 5、把参数存到数组里面
          • 6、直接把实参数组传到反射里面了,这能行吗
          • 7、程序逻辑bug
          • 8、点下一页的时候报了这个错误
          • 9、这样这个controller里面只需要考虑怎么进行业务的操作,怎么获取参数,怎么跳转都不用考虑了
        • 4、我自己写的时候遇到的问题
          • 1、语言等级
          • 2、我不知道怎么找参数的名字
          • 3、我改了可以获取到参数名字,但是无效
          • 4、草拟吗啊,我为什么 -parameters这个不好使,在maven上配置也不好使
          • 5、如果以后还有问题,来看看这个文章
          • 6、索引越界,越来是j和i写错了。。。
          • 7、声明数组放循环里了,结果导致空指针
          • 8、那个变量数组还没循环存完呢,我就去反射方法了
          • 9、报空指针,添加了非空判断,但是好像没有解决
          • 10、报类型转换异常
          • 11、为什么invoke 能传进去个object数组,因为 下面这个,想想那些List=Arrlist之类的
      • 5、我把本地项目删了,从git上拉取了一下,出现了错误
  • Git
      • 6、弄了一上午git出错,怎么都不能删除当前分支,但是不知道怎么弄的突然好了,用了下面这个链接以及这个链接的方法
    • 四、servlet4 api
      • 1、servlet-api
      • 2、配置文件配置方法
      • 3、注解配置方法
      • 4、获取配置参数方法
      • 5、405报错
      • 6、配置上下文参数
      • 7、读取方法
    • 五、业务层
    • 六、IOC
      • 一、核心思想
        • 1、添加配置文件里
        • 2、建立接口
        • 3、建立实现类
        • 4、把之前 dispatcherServlet里面的那个方法提取出来
        • 5、层与层之间的依赖,在配置文件里写
        • 6、组装bean之间的依赖关系
            • 再看一遍这个[这个是java操作节点的一些文档](https://www.w3cschool.cn/java/java-dom-intro.html)
        • 7、我NB了,之前觉得最难得一节课我也看懂了
        • 8、好了,我要实现IOC了,开干
          • 1、第一步是把bean 写到配置文件里面
          • 2、BeanFactory
          • 3、依赖注入代码要写在哪个位置
          • 4、我虽然写完了,但肯定会出错,改完了,我就出去骑自行车
            • 1、.InstantiationException 实例化异常
            • 2、beanObj 可能找错了
    • 七、总结
      • 1、控制翻转
      • 2、依赖注入
      • 创建domcument的方法
  • 不懂得问题
    • 八、filter![在这里插入图片描述](https://img-blog.csdnimg.cn/f9de09203c2c4df3a56f0fa44c6503f9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcXFfNDI3NjU0OTM=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
      • 1、 成为filter 要这样
      • 2、 filter放行
      • 3、 @WebFilter(这里要写的和servlet一样,不然怎么拦截?)![在这里插入图片描述](https://img-blog.csdnimg.cn/26f6b74e1aaa462bb8341e9c4aa82308.png#pic_center)
      • 4、 配置文件写法
      • 5、 扩大拦截范围
      • 6、 过滤器链条
      • 7、 过滤器链条执行顺序
      • 8、 应用
      • 9、 容易错的地方
      • 10、 把编码格式写到文件里,不把他写死
      • 11、我犯的错误
  • 九、事务管理(不是service里面的事务管理)
    • 1,引出问题
    • 2、引出方法
    • 3、实现方法
      • 1、在filters 里面 新建个类 实现Filters 方法
      • 2、获取conn 对象
      • 3、提交和回滚方法
      • 3、获取conn抽取到 获取连接的工具类里面
      • 4、吐了,这只是基础的
      • 5、要去掉BaseDao里面的close方法
      • 6、开始写了
      • 7、从threadLocal中移除conn方法
      • 8、之后就是实验
      • 9、老师不是吧try catch 全删了,保留 一部分 try catch 并且向外抛异常
        • 老师这里没有直接抛异常而是 新建了一个异常类原因如下
        • 干,我不会重写RuntimeException方法
      • 成功了
      • 卧槽后面还有配置式和注解式的事务管理??
      • 10.在git分支合并那里有不会的东西
  • 十、ThreadLocal中的get和 set源码分析
    • set方法
    • get方法
    • 每一个threadMap 里面只有一对值、
  • 十一、Listener 一共有八个
    • 1. 监听器
    • 2. 新建
    • 3. 配置方法
    • 4. 应用
    • 5. 在水果管理系统的应用
    • 6. 为什么这么做
    • 7.优化硬编码 这里有些语法我没懂,我要先把它记录下来
    • 8.自己写
      • 1、干,监听器我不会写
      • 我实现了方法,他怎么没让我重写啊
      • 2、名字冲突
      • 3、但还是出错
      • 4、我把这两个弄混了
      • 5、我靠 我的ClassPathXmlApplicationContext和老师的不一样
      • 6、沃日,不一样的也太多了吧
      • 7、无参调有参
      • 8、我靠我没有配置上下文初始ICO配置文件参数,我的tomcat直接启动不了
      • 9、来吧,快三点了,整理完这个就睡觉
        • 1、我说不太好,我直接写代码吧 改造beanFactory 实现类
        • 2、改造触发器 listener 这个类
        • 3、设置初始化参数
  • 十二、复习
  • 十三、cookie了解
    • 1、概念:
    • 2、创建cookie
    • 3、向客服端发送cookie,让客服端保存cookie
      • 请求头携带了cookie
      • 响应头发送了cookie
      • 请求头和响应头都携带了cookie
    • 4、设置cookie的有效时长
    • 5、对cookie进行细分
    • 6、一般情况下不用设置这么细
    • 7、十天免登陆
    • 8、session 与 cookie 的区别
    • 8、!!!切记,更新了cookie,比如时间,立即销毁cookie一定要把cookie发过去,更新浏览器的cookie
    • 9、webStorage
  • 十四、VUE快速学习
    • 1、那个神奇的scope 完成了对象属性发送的
    • 2、导入js文件
    • 3、当页面加载完成的时候
      • 不能把方法和属性声明 放在window.onload里面
      • Vue就是一个对象,类似这个
        • 犯得错误:javascript 创建对象是 new Object; javascript创建对象的方法
        • 怎么定义对象方法。。
        • 怎么绑定成员方法...
        • 加不加括号,好像就是加了()就是把返回值赋给这个对象
    • 4、新建Vue对象
      • 0、这里面的属性左边加不加 “” 都可以
      • 1、el是element的意思
      • 2、data数据 绑定
        • 1、{{}}
        • 2、v-bind
        • 2、v-model
        • 3、trim 可以去除首尾空格
      • 3、条件渲染
        •   空格
        • 1、v-if v-else
          • v-if
        • v-else
        • v-if 和 v-else 直接不能有其他标签!!!
        • v-show
        • v-for
          • 之前thymeleaf 里面 列表循环是这样的 fruit : ${session.fruitList}
          • 1、先准备一个数组
            • 犯的错误
    • 表格属性
    • java Stream api
      • 4、事件绑定
        • 1、当点击的时候吧某一个字符串翻转
        • 2、获取当前鼠标的坐标(好像用不到)
        • 3、侦听属性 watch
          • 1、监听,简易计算
          • 2、我犯的错误
      • 5、vue生命周期 钩子函数
        • 1、钩子函数
  • 十五、跳过原生ajax和 Axios 发送 普通参数请求
    • 1、什么是json
    • 2、发送json
    • string stringBuild stringBuffer 区别
    • 2、发送与接收
      • 1、接收json
      • 2、json转换对象
      • 3、对象转换json
    • 3、MIME类型
    • 4、客户端接收
      • 1、服务器端给客户端响应json格式的字符串,然后客户端需要将字符串转化为jsObject
      • 2、给浏览器打断点
      • 3、给vue data 赋值
      • 4、java 和 javascript 都有 json的api
      • 5、字符串中的\ 是干嘛的
      • 6、js string -> js object JSON.parse(str)
      • 7、js object->js string JSON.stringify(Object)
      • 8、简化方式,沃日
      • 9、因为代码越来元复杂了,除非沙比的bug,其他代码不熟练,将不会被记录
        • 1、json 字符串 不会写
        • 2、axios data 怎么写
        • 3、引入axios 出错
        • 4、我靠,怎么把json对象写回去?
      • 10、黑马的响应成功的方法
  • 十六、element 做登录界面
    • 1、卡片套文本框
    • 2、里面塞个表单
      • 配合element ui 都是用ajax 去发请求的
    • 3、改造
      • 1、删除冗余
      • 2、密码框
      • 4、qs的作用
      • 5、用户名 密码后面加图标
      • 6、文本框 校验 这个我做过
        • 1、使用方法
      • 7、文本框 校验不通过,请求不发出去
        • ref 把表单注册给 vue !! 重要知识点
      • 8、重置表单
        • 这里用不是写死的方法(传形参)
          • 重置功能只重置密码框
      • 9、去掉必填属性左边的红点
      • 10、校验没过,自己加提示框
      • 11、来了,来了,自己写一个登录界面(看看我能犯什么傻逼错误)
        • 1、怎么居中来着
        • 2、图标不会设置
        • 2、输入框长度
        • 3、prop 直接写属性名就可以
        • 4、不会隐藏星星 *
        • 5、方法写对了,但是vue报错
        • 6、我qs怎么点不出来啊
        • 7、引入依赖
          • 1、引入Qs
  • 十七、element 做动态菜单页面
    • 1、JS页面跳转
    • 2、找一个上左右的结构
      • 一些概念类的东西
      • 1、Flex 布局
      • 2、element 容器标签
      • 3、怎么找文档,看自己不认识的标签
    • 3、把页面占满
      • 1、扩html,body
      • 2、扩根标签
      • 3、还是没有效果,里面套的内容也要扩
      • 4、element ui 的样式比较特殊!!重要内容
      • 我们看到的这些element Ui 标签 一般来说最后会转换为 样式的 .class
      • 5、这么设计的好处
    • 4、导航菜单
      • 1、使用方法,先找例子,然后照着官方文档去改
      • 2、如果用别人的东西,连文档都不愿意看的话,对不起,那你就不要用了
      • 3、代码放置位置
      • 4、各个属性详细解释
        • 1、el-row el-col
        • 2、el-menu 属性
        • 因为找的是el-menu 的属性,所以找这个,其他的也一样
        • 3、default-active
        • 4、@open @close
        • 5、el-submenu \ el-menu-item-group\ el-menu-item
        • 6、索引或者标记
    • 5、精简
    • 6、内部属性
      • 1、摁钮模板
      • 2、分组和不分组
      • 不要分组
      • 需要用到的标签
    • 7、用户菜单
      • 1、应该做到不同用户,看到的是不同的菜单
      • 2、难点:不同的用户登录上来要显示不同的左侧菜单 菜单不能写死了
      • 3、动态下拉效果
      • 4、先不管后台,前台找到结构,遍历就可以了
      • 1、做假数据
      • 2、图标和路径
      • 3、手动拼接要做数据校验
      • 5、用这个结构去遍历
        • 这个错误是数据少了括号
      • 6、一级菜单遍历参数填写
      • 7、二级菜单遍历参数填写
      • 8、动态菜单概述
      • 9、二级菜单的链接地址
      • 10、不想要多个菜单都展开的效果
    • 8、看看我会犯什么错误
      • 1、json 嵌套代码不会写
      • 2、v-for 要写在哪里啊

写在最前面,这里有比较全的详细解释 尚硅谷的笔记
之所以还会写这个,是为了起到一个把知识串起来的作用,是写给自己的,不要写的特别详细,写的再详细都没有别人写的好,为的就是自己能一看就能懂,在以后面试的时候,过来瞟一眼,就什么都能想起来。

知识如果学了没有记下来,如果没有真的完全的理解,就等于没学过!!!

一、tomcat 安装

1. 官网下载

下载tomcat8: tomcat8.
【javaweb笔记1】自用_第1张图片

2.安装

直接解压到本地

3.卸载

直接删除文件夹

4.启动

双击:bin\startup.bat

5.控制台中文乱码

修改 conf/logging.propertis
在这里插入图片描述

6.闪退

检查JAVA_HOME 环境变量,一般就是这个问题

7.IDEA使用tomcat的maven插件

 <build>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <port>8080</port><!--访问端口号-->
          <path>/</path><!--项目访问路径-->
        </configuration>
      </plugin>
    </plugins>
  </build>

要先安装 .Mavne Helper 这个插件
选中项目,右键,tomcat run
【javaweb笔记1】自用_第2张图片
注意需要配置虚拟路径不能用tomcat插件

7.IDEA不使用插件配置

1.将本地Tomcat集成到Idea中,进行项目部署
步骤
【javaweb笔记1】自用_第3张图片
【javaweb笔记1】自用_第4张图片
选择本地tomcat目录
【javaweb笔记1】自用_第5张图片
【javaweb笔记1】自用_第6张图片

maven 创建java web项目

【javaweb笔记1】自用_第7张图片

8.导入servlet依赖

<dependencies>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

9.tomcat防止post方式乱码

request.setCharacterEncoding("utf-8")

记得一定要把这个写在最上面

get模式,tomcat8之后不需要更改

10.IDEA自动导包

【javaweb笔记1】自用_第8张图片

11.servlet 线程问题

servlet在tomcat中是 单例 线程不安全的
-单例:所有请求都是同一个实例去响应
-线程不安全:一个线程需要根据这个实例中的某个成员变量去做逻辑判断,但是在中间某个实际,另一个线程改变了这个值,比如通过一个值去做if 或 else 判断,就会导致第一个线程执行路径发生变化

-解决办法:尽量的不要再servlet中定义成员变量,如果不得不定义成员变量,那么
1、不要去修改成员变量的值
2、不要去根据成员变量去做逻辑判断

三、Servlet

1.生命周期

1、先实例化,调用构造方法
2、init() 初始化 service() 执行服务 destroy() 销毁

继承关系
javax.servlet.Servlet接口:
void init(config) - 初始化方法
void service(request,response) - 服务方法
void destory() - 销毁方法

javax.servlet.GenericServlet抽象类:
void service(request,response) - 仍然是抽象的

  javax.servlet.http.HttpServlet 抽象子类:
    void service(request,response) - 不是抽象的

2.HTTP 协议

1、请求行
请求的方式 2、请求的URL3、请求的协议(一般是HTTP1.1)
2、请求头
很多客服端要告诉服务端的信息,我的浏览器型号、版本、我能接收的内容的类型、我给你发的内容的类型、内容的长度等等
3、请求体
get方式,没有请求体,但是有一个queryString
post方式,有请求体,form data
json格式,有请求体,request payload
(这三个我都不懂)

3、Session

1.快速理解

打开谷歌浏览器,先打开F12
输入servlet地址
【javaweb笔记1】自用_第9张图片
因为是第一次访问,服务器会塞给浏览器一个servlet地址,用的是response

第二次访问
因为浏览器已经有session了,所以去请求服务器时候,会通过 request 将session 携带过去

用这个sessionId来区分不同客户端,称作会话跟踪技术
这个sessionId是全球唯一码

2、保存作用域

只在当前浏览器的访问中,一台电脑的其他浏览器都不行

3、一些API

【javaweb笔记1】自用_第10张图片

4、 重定向和转发的区别

转发,服务器内部跳转 浏览器不知道
【javaweb笔记1】自用_第11张图片

重定向:服务器命令浏览器:你立刻给谁谁谁发请求
【javaweb笔记1】自用_第12张图片

4、路径问题

【javaweb笔记1】自用_第13张图片

5、servlet作用域

1、request response

一次连接

2、session

网页关闭之前,一直有效,如果30分钟之内没有使用,也会失效,可以手动设置时间
甚至可以,直接关闭

3、application

叫servlet上下文

tomcat停止,这个上下文就结束了
可以手动移除属性

ServletContext.application=request.getServletContext()
application.setAttributr(k,v)


ServletContext.application=request.getServletContext()
application.getAttributr(k)

四、mybatis

1、依赖部分

1、日志系统


    org.slf4j
    slf4j-api
    1.7.7
  
  
    ch.qos.logback
    logback-core
    1.1.7
  
  
    ch.qos.logback
    logback-access
    1.1.7
  
  
  ch.qos.logback
  logback-classic
  1.1.7
  

彩色日志 logback.xml



    
    
    
    
    

    ${APP_NAME}

    
        
            ${CONSOLE_LOG_PATTERN}
        
    

    
        ${LOG_DIR}/logFile.log
        true
        
            ${FILE_LOG_PATTERN}
        
    

    
        
            ${LOG_DIR}/dayLogFile.%d{yyyy-MM-dd}.log
            30
        
        
            ${FILE_LOG_PATTERN}
        
    

    
    
    

    
    
    

    
        
    

    
        
        
        
    

2、jdbc


    mysql
    mysql-connector-java
    5.1.47
  

mybatis


    org.mybatis
    mybatis
    3.5.7
  

3、test junit

junit @Test依赖



    junit
    junit
    4.12
    test



2、配置部分

1、mapper 包扫描

如果mapper接口名称和sql映射文件名称相同,并在同一目录下,则可以使用包扫描方式简化sql映射文件的加载

这个是写在mybatis-config.xml


        
    


        
    

2、类型别名

【javaweb笔记1】自用_第14张图片
resultType 需要把包名和类名都写上去

【javaweb笔记1】自用_第15张图片
起了别名,就可以直接写类名,而且不区分大小写
这个是写在mybatis-config.xml

3、sqlSession 工具类

public class MyBatisUtils{
        private static SqlSessionFactory sqlSessionFactory=null;
        //初始化SqlSessionFactory对象
        static{
            try{
                //使用MyBatis提供的Resources类加载MyBatis的配置文件
                Reader reader= Resources.getResourceAsReader("mybatis-config.xml");
                //构建SqlSessionFactory工厂
                sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        //获取SqlSessionFactory 对象的静态方法
        public static SqlSessionFactory getSession(){
            return sqlSessionFactory;
        }
    }

4、返回集写法

<resultMap id="fruitReturnMap" type="Fruit">
        <result property="fId" column="f_id">result>
        <result property="fName" column="f_name">result>
        <result property="fPrice" column="f_price">result>
        <result property="fCount" column="f_count">result>
        <result property="fRemark" column="f_remark">result>
    resultMap>

5、名称空间

在mybatis中,映射文件中的namespace是用于绑定Dao接口的,即面向接口编程。

当你的namespace绑定接口后,你可以不用写接口实现类,mybatis会通过该绑定自动帮你找到对应要执行的SQL语句
【javaweb笔记1】自用_第16张图片

五、thymeleaf

1、依赖

 <dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.12.RELEASE</version>
  </dependency>

在页面html 这个标签里面加这行语句


在web.xml配置文件里添加参数


  view-prefix
  /


  view-suffix
  .html

2、部分标签

 

使用例子

名称 单价 库存 购买地址 操作
列表数据为空
苹果 5 100 拼多多

3、ViewBaseServle

新建ViewBaseServlet(有两个方法) , 配置两个 : view-prefix , view-suffix

4、获取作用域参数

1、session

${#lists.isEmpty(fruitList)}

${#lists.isEmpty(session.fruitList)}

${#lists.isEmpty(application.fruitList)}

六、管理水果系统

记录一下,之前跟着黑马也做了增删改查,而且是用VUE和AXIOS做的,所以这里这是看一下用普通方法(thymeleaf)怎么做

1、主页

1、不用相对路径并设置根路径

先设置一个根路径


其中day01是虚拟路径
这样设置之后,再写其他路径,比如 导入js文件就可以直接写比如这样



但是要注意,这个是TOMCAT的地址,在软件里面地址可能是这样的

http://localhost:63342/epidemic01/src/main/webapp/index.html?_ijt=ogf5d4qajludu3bqrucdnjinpg&_ij_reload=RELOAD_ON_SAVE

所以要把服务器跑起来测试

2、设置全局字体颜色

*{
	color: threeddarkshadow;
}

我还以为是多高大上的代码呢,原来就是个设置颜色

4、直接写属性名,就是设置所有属性

比如div 或者 body 就是更改所有这个属性的属性

解决方案:1、更改某个字,当字变了,那也更新过去了
2、不启动服务器,大概写好了,再去弄

5、直接写属性名,就是设置所有属性

【javaweb笔记1】自用_第17张图片
这种结构,我以为只是改了个背景色,没想到居然是这个做的


		
body{ margin:0; padding:0; background-color:#808080; } #div_container{ width:80%; height:100%; border:0px solid blue; margin-left:10%; float:left; background-color: honeydew; border-radius:8px; }

用这个方式,可以让上面的div居中

	width: 80%;
    margin-left: 10%;
    height: 100%;
border-radius: 数值px;

设置椭圆边框

text-align:center;

让文字居中不要设置什么内外边框,直接上这个
而且,注意

	width: 80%;
    text-align: center;

宽度80的时候也不能居中

6、表格边框要这么写

#table_fruit ,#table_fruit tr, #table_fruit th, #table_fruit td{
border: 2px black solid;
}

看好了,表格边框是这样的,不是说你这样就可以了

#table_fruit{
border: 2px black;
}

这个是错的,第一不是单写个表格就行了,还要写后面的tr th td
第二 border 要写上 solid 这个东西

位置信息不能在写在上面

#table_fruit ,#table_fruit tr, #table_fruit th, #table_fruit td{

这种东西里面,不然会变得不幸

border-collapse: collapse;

合并线要写在上面那一坨里面,而不是表格里面

line-height: 26px;

设置行高,写在表格属性里面

font-weight:lighter;

文字粗细演示

    font-family: "黑体";

设置字体

7、表格边粗细不一

调整浏览器缩放比例

8、添加图片


9、合并单元格

列表数据为空


写在html页面里,不是css

10、选中某一种类型

input[type=text]{
    width: 70%;
}

2、编辑和修改特定库存信息

1、渲染覆盖

 苹果

你看这行代码,你在静态访问的时候没有问题,在动态访问的时候也没有问题。

但是一旦通过访问servlet的方法

@WebServlet("/fruit")
public class FruitServlet extends ViewBaseServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        FruitService fruitService=new FruitServiceImpl();
        List fruitsList = fruitService.selectAll();

        HttpSession session = req.getSession();
        session.setAttribute("fruitList",fruitsList);

        super.processTemplate("index",req,resp);
    }

}

就出了问题,是因为被前面的thymeleaf 的渲染给覆盖了,这种东西,要是我自己写,一定会发疯的,一遍一遍的去调试,而不知道错误在哪里,我真的,之前一直因为这种事情心态爆炸。

网页跳转那里也是,所以下回遇到bug千万别急眼,一定是自己的基础知识出了问题,找原因就好,加油!!

2、路径问题

苹果

老师的意思是现在我的index主页位置直接在wepapp下面,如果之后路径很深的话,这样写不太好,要加上根目录,我先在不太懂,等之后碰壁了应该就懂了,要写成下面这样

苹果

没太懂,但是写成这样比较好

3、height设置不生效问题

%是一个相对父元素计算得来的高度,要想使他有效,我们需要设置父元素的height;

要特别注意的一点是,在之中的元素的父元素并不仅仅只是,还包括了。

所以我们要同时设置这两者的height,只设置其中一个是不行的:

html ,body{
    height: 100%;
}

4、取消body边距无效

原因:我的

的边距有问题,我不知道为什么 之前的网页没有这个问题

5、get 可以发送序号过去 ?id=1

苹果

这行代码对应的servlet需要一个id去查询对应的数据,把数据渲染到编辑页面上,原来是通过get方式传递的

6、thymeleaf 拼接属性变换

th:href="@{'/edit.do?fId='+${fruit.fId}}">

th:href="@{/edit.dofId(fId=${fruit.fId})}

7、非空判断最好写在一个工具类里面

1、String 判断非空

8、编辑页面里的一些问题

1、我没写name,这个很重要,我编辑好了,要修改的,所以要有name去提交

2、我不知道thymeleaf那个绑定变量怎么写

不遍历的话直接写
遍历这样写

 
       

        苹果
        
        
        5
        100
        拼多多
        
    
1、原来是直接写的

因为我用req,把数据发送过去了,而且没有遍历,所以可以直接写

th:value="${fruit.fCount}"
2、也可以这样写
th:object="${fruit}";

th:value="*{fname}";

9、servlet映射无效

原来是我

@WebServlet("update.do")
//没写/
@WebServlet("/update.do")

10、bigDecimal 和 String 转换

BigDecimal bigDecimal = new BigDecimal(s);

11、我吐了,真的,那个session 提交和关闭别忘了好不好

12、更新数据后,网页数据没有变

原因是我把数据存到了session里面,然后遍历渲染到网页上。
更新完了数据,但没有把更新后的数据 重新保存到 session 上

但是上面的做法是冗余的

做法是 重定向到主页,(就是给indexServlet发请求)主页会自己获取,就好了

3、添加和删除数据

1、display: inline-block; 无效

因为没有设置宽高

2、display: inline-block; 无效


因为前面的网页我是直接去请求静态资源,导致添加的网页没有经过thymeleaf的渲染,语法不生效

3、取消超链接下划线

text-decoration=none

4、删除

th:onclick="'deleteByid('+${fruit.fId}+')'"

正常的字符串拼接,注意外面是双引号,里面是单引号
简易写法

th:onclick="|deleteByid(${fruit.fId})|"

测试的时候,点那个小箭头,就能看代码生没生效
【javaweb笔记1】自用_第18张图片

5、引入js


6、删除delete语句

delete from fruit where f_id=x;

7、忘了写@WebServlet(“/delete”)

请求的资源[/day01/delete]不可用

4、分页查询

我先自己写
我知道怎么把数据传到前端
但是前端怎么写啊
我先写个写死页数的分页查询吧

后端分页需要的数据写完了

前端是这么写的

 

(page-1)*5

== 记住他是基于当前页码的上一页,下一页进行查询的

1、写了分页查询没有指定返回集

2、调整摁钮大小

.big{
    width: 80px;
    height: 30px;
    font-size: 16px;
    font-weight: bold;
}

给所有摁钮加上class,然后调整width hright

3、调整字体粗细

    font-weight: bold;

4、我要传一个page页码过去,而不是总数

5、计算页数的公式

int lastPage=(pageCount+5-1)/5;

6、判断是否是摁钮不可用

@Test
    public void ifTrue(){
        System.out.println(1==1);
    }

这个结果是true
同理

5、根据关键字查询

说实话上个分页条前端我没写出来,是因为不知道语法,这个我应该能写出来

先写后端,然后测试

再写前端

1、模糊查询

@Select("select * from fruit where f_name like '%${keyWords}%';")

用这种方式写,有被注入攻击的风险



2、提交查询关键字

我是用dom做的,老师使用表单提交做的

3、查询库存总记录数也要考虑keyWord

总体思想
1、隐藏域发送 opea=search
2、判断是怎么过来的
3、如果是搜索进来的,那么 开始页数为一 把keyWord 存到session里面
如果不是keyword要从session中获取

4、走下面需要从session中获取关键字,req里面的session没了

6、总结

1、记得更新session里面的数据

七、MVC各个层的设计

【javaweb笔记1】自用_第19张图片

连接进来

Character Encoding Filter

用来把tomcat post方法默认的 iso8859-1 转换为 UTF-8编码

Open Session InView Filter

用来进行事务管理,把DAO层和Service层里面所有的try catch 都变为运行时异常,在这里捕捉,统一进行commit 或 rollback

1、开启事务
try{
2、放行
3、提交
}catch(){
4、回滚
}

ThreadLocal(难点)

这个是本地线程方法,就类似于流水线上面的工具箱,一个工具箱,三个人用,一个连接,三个方法用,保证连接是一个

为什么要保证连接是一个来着?
:如果连接三个方法用一个连接,回滚能回滚三个

DispatcherServlet 这里没懂的比较多,需要多敲代码

就是黑马那个解析链接 找到controller
根据传过来的参数 找到对应的service方法

难点
1、参数处理
2、invoke(这个不难)
3、视图处理(这个是啥?)

IOC Container

IOC容器 控制翻转 依赖注入

用标签来指定依赖

伪代码

一、servlet优化1

【javaweb笔记1】自用_第20张图片

【javaweb笔记1】自用_第21张图片

1、总体思想

总体思想是,判断传过来的operate这个值的属性,来判断执行哪个方法

在这里插入图片描述

1、把 发送的地方改成 总的那个地方,2、然后用发送两个参数的方法,再传一个
注意要写成单引号

2、function方法怎么改

【javaweb笔记1】自用_第22张图片

3、还可以隐藏的发过去

在这里插入图片描述

为什么是三种方法呢,第一种和第三种的区别是啥
第一种通过连接发值可以发两个
要是提交表单的方式,就只能隐藏域发送了

4、之前的重定向,要统一改成现在的总servlet,会通过初始值 指定到主页

5、如果这里面的值都没有就说明是被手动输入了,抛出个错误

6、浏览器? &

window.location.href='fruit?fId='+fId+'?operate=delete';

window.location.href='fruit?fId='+fId+'&operate=delete';

7、我以为闹鬼了,点击编辑功能,他直接把数据删了,原来是把数据变成空了,然后不显示

原因二是 ,他是要通过edit这个跳转到edit.html这个页面,我把这步省了

还行吧,20分钟的东西,磨了一个小时

servlet优化2 dispatcherServlet引入

1、通过方法名 用反射实现

【javaweb笔记1】自用_第23张图片

2、默认的index

我真他妈草了,一直在怎么得不到参数,让他去找index,直接在上面设置值就可以了
【javaweb笔记1】自用_第24张图片

3、反射的对象获取

【javaweb笔记1】自用_第25张图片

4、对象才有getClass方法,this也是对象

二、servlet优化2.1 dispatcherServlet引入

步骤

1、在dispatcherServlet 的构造方法里面解析那个配置文件
2、创建一个DocumentBuilderFactory
3、创建DocumentBuild对象
4、创建Document对象 一定要导==org.w3c.com ==这个包的

1、setAccessible 访问private 需要这个属性

设置访问性,反射类的方法,设置为true就可以访问private修饰的东西,否则无法访问

2、中央控制器的概念

【javaweb笔记1】自用_第26张图片

1、实现步骤

1、新建servlet,拦截*.do为结尾的请求
2、得到字符串对应控制器
【javaweb笔记1】自用_第27张图片

3、把之前的servlet变成普通的类

4、在一个文件当中,对这两者的关系做一个说明

5、声明这么写
【javaweb笔记1】自用_第28张图片

1、xml声明的固定写法


java操作节点的一些文档

这个是java操作节点的一些文档

2、反射调用方法 变量居然是method
 for (Method fruitMethod : fruitMethods)

我自己写了反射,跑一下试试,哈哈哈哈哈

3、反射调用方法 记得用这个getDeclaredMethod

而且 忘了写 参数类型.class

4、这么搞他的搜索功能是坏的,我不知道他后面是怎么解决的,之后再说吧
private void search(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        index(req,resp);
    }

2、我应该先敲一遍代码,然后看看老师那里翻了错误,我也跟着改

1、根据请求的url获取servletPath,解析出一个名字

【javaweb笔记1】自用_第29张图片

2、解析加载配置文件,读取bean 扔到配置文件里面 (这是我几天前写的,我现在就看不懂了)
3、调用controller里面的方法

【javaweb笔记1】自用_第30张图片

3、卧槽,困扰我那么久的问题终于要解决了

就是因为我把原来的servlet给改成普通类了,他就不会去调用它的Init方法,那个方法里面有个servletContext参数,没有,我现在来写一遍

1、因为FruitController 不是一个servlet方法了,所以不会去调用init方法

之前FruitServlet是一个servlet组件,那么其中的Init方法一定会被调用
之前的init方法会出现一句话,super.init
【javaweb笔记1】自用_第31张图片
有了这句话就会对用 viewBaseServlet 里面的init 方法
【javaweb笔记1】自用_第32张图片
现在它已经不是servlet方法了,所以不会去调用init方法,也就不会去调用viewBaseServlet 里面的init 方法

【javaweb笔记1】自用_第33张图片
【javaweb笔记1】自用_第34张图片

2、不能自动调用,那我就自己调用

【javaweb笔记1】自用_第35张图片
在里面写一个
【javaweb笔记1】自用_第36张图片

【javaweb笔记1】自用_第37张图片

3、不写构造里了,写在Init里

【javaweb笔记1】自用_第38张图片

ServletContext就是最大的那个作用域

4、因为我要把那个参数传进去

写一个set方法
【javaweb笔记1】自用_第39张图片

【javaweb笔记1】自用_第40张图片
把之前调用 成员变量 变成成员方法
【javaweb笔记1】自用_第41张图片

把参数扔到 view那个里面
【javaweb笔记1】自用_第42张图片

扔到这里面

5、还是没用的原因

【javaweb笔记1】自用_第43张图片
这个值的获取方法没改

6、这么改

【javaweb笔记1】自用_第44张图片

【javaweb笔记1】自用_第45张图片

这里也改一下就好了

三、servlet优化3 提取视图资源处理通用代码 与 统一获取参数

【javaweb笔记1】自用_第46张图片
中央控制器类 dispatherServlet
【javaweb笔记1】自用_第47张图片

1、重定向和转发也可以提取出来

1、解决转发冗余

在这里插入图片描述
把这个String发送给中央控制器,让中央控制器帮我们进行统一的转发

【javaweb笔记1】自用_第48张图片
不知道要干嘛
在这里插入图片描述
截取还能这么用,我真是震惊
【javaweb笔记1】自用_第49张图片

核心代码

 try {
            Method declaredMethod = controllerBeanObj.getClass().getDeclaredMethod(operate, HttpServletRequest.class, HttpServletResponse.class);
            if(declaredMethod!=null){
                declaredMethod.setAccessible(true);
                Object invoke = declaredMethod.invoke(controllerBeanObj, req, resp);
                //在这里执行了方法,然后统一去跳转
                if(invoke!=null){
                    String redirectStr=(String)invoke;
                    if(redirectStr.startsWith("redirect")){
                        //如果包含这个,那么跳转
                        String substring1 = redirectStr.substring("redirect:".length());
                        resp.sendRedirect(substring1);
                    }else {
                        super.processTemplate(redirectStr,req,resp);
                    }

                }

            }else{
                throw new RuntimeException("没有这个方法");
            }

2、search 无效 我有点NB了

【javaweb笔记1】自用_第50张图片

【javaweb笔记1】自用_第51张图片

2、解决那个需要view的

【javaweb笔记1】自用_第52张图片
【javaweb笔记1】自用_第53张图片

别忘了,这个调用初始化
【javaweb笔记1】自用_第54张图片

2、每一个方法都有req.getParameter这个方法,代码冗余

1、解决那个需要view的

我超,他把req,和resp都删了
异常也删掉
在这里插入图片描述
真就解耦呗

直接把形参写上去,把需要req.getParameter都删掉,

2、统一抽取到父类里面 就是DispatcherServlet里面【javaweb笔记1】自用_第55张图片

三步走

3、思考过程

每个方法需要获取的参数的都一样,我要获取那些参数,是根据这个方法的参数签名来获取的
参数签名

方法签名由方法名称一个参数列表(方法的参数的顺序和类型)组成。
注意,方法签名不包括方法的返回类型不包括返回值和访问修饰符

public double calculateAnswer(double wingSpan, int numberOfEngines,
                              double length, double grossTons) {
    //do the calculation here
}

上面方法的签名是:

calculateAnswer(double, int, double, double)
1、获取当前方法的参数,返回参数数组
Parameter[] parameters=method.getParameters();
2、这里有个错误,因为之前把方法参数改了,不是每个方法都有req,resp的

在这里插入图片描述

3、解决方法是获取所有方法,然后循环

【javaweb笔记1】自用_第56张图片
但是获取不到方法名

如果能获取到方法名,就可以直接req.getParameter了

4、从JDK8 开始可以获取反射的名称

【javaweb笔记1】自用_第57张图片
这个表示在编译的时候,形参自带参数名称
.class文件会稍微大一点
记得把编译好的文件删一下,重新编译

【javaweb笔记1】自用_第58张图片
真实名称就搞到了

5、把参数存到数组里面

【javaweb笔记1】自用_第59张图片

在这里插入图片描述

如果是复选框的话,用这个方法,但是不考虑那么复杂

【javaweb笔记1】自用_第60张图片
这三个参数是不需要req.getParameter的
【javaweb笔记1】自用_第61张图片
最终写法

6、直接把实参数组传到反射里面了,这能行吗

在这里插入图片描述

7、程序逻辑bug

【javaweb笔记1】自用_第62张图片

8、点下一页的时候报了这个错误

【javaweb笔记1】自用_第63张图片
错误原因是,访问主页的时候
【javaweb笔记1】自用_第64张图片
这张图片里的page是null 然后默认给了1 ,但是一旦,点了下一页

【javaweb笔记1】自用_第65张图片
这里就要值了,但是page这个值应该是integer 我往数组里放的是String
【javaweb笔记1】自用_第66张图片

【javaweb笔记1】自用_第67张图片
可以查看参数类型

java.lang.Integer

【javaweb笔记1】自用_第68张图片
这样就不会报 参数类型不匹配了

9、这样这个controller里面只需要考虑怎么进行业务的操作,怎么获取参数,怎么跳转都不用考虑了

【javaweb笔记1】自用_第69张图片

4、我自己写的时候遇到的问题

1、语言等级

idea还有语言等级,有些方法貌似level 8 才能用,比如这个

Parameter[] parameters = m.getParameters();
2、我不知道怎么找参数的名字

我超,原来打了断点还可以下一步

3、我改了可以获取到参数名字,但是无效

我他吗吐了,我忘了删除已经编译好的文件

4、草拟吗啊,我为什么 -parameters这个不好使,在maven上配置也不好使
    
        
            
                maven-compiler-plugin
                3.8.0
                
                    1.8
                    1.8
                    utf8
                    
                        -parameters
                    
                
            
        
    

用了这个好使了,可能可maven compiler-plugin 的版本有关

5、如果以后还有问题,来看看这个文章

maven-jdk问题

6、索引越界,越来是j和i写错了。。。
  for (int j = 0; j < parameters.length; j++) {
                        //这里把每个参数都取出来了
                        Parameter parameter = parameters[i];
7、声明数组放循环里了,结果导致空指针
8、那个变量数组还没循环存完呢,我就去反射方法了
9、报空指针,添加了非空判断,但是好像没有解决
 if(typeName.equals("java.lang.Integer")){
                                //integer可以存null
                                if(!parameter1.equals("null")){
                                paraObj = Integer.valueOf(parameter1);}
                            }
 if(typeName.equals("java.lang.Integer")){
                                //integer可以存null
                                if(!(parameter1 ==null)){
                                paraObj = Integer.valueOf(parameter1);}
                            }

改成这种格式

10、报类型转换异常
 if(typeName.equals("java.math.BigDecimal")){
                                if(!(parameter1 ==null)){
                                paraObj = new BigDecimal(parameter1);}
                            }


                            paraObj=parameter1;

你看看你写的这个顺序,能不空指针吗

11、为什么invoke 能传进去个object数组,因为 下面这个,想想那些List=Arrlist之类的
public void object1(){
        int a=0;
        Object b=a;
        System.out.println(b instanceof Integer);
    }

5、我把本地项目删了,从git上拉取了一下,出现了错误

java: JDK isn't specified for module 'javaWeb'

解决方法
添加链接描述
vcs 复制码云上面的仓库地址

Git

6、弄了一上午git出错,怎么都不能删除当前分支,但是不知道怎么弄的突然好了,用了下面这个链接以及这个链接的方法

git
添加链接描述
添加链接描述

四、servlet4 api

1、servlet-api

【javaweb笔记1】自用_第70张图片
如果我们想在servlet初始化时做一些准备工作,我们可以
重写那个Init()空实现方法
init 方法只会执行一次

2、配置文件配置方法

【javaweb笔记1】自用_第71张图片

3、注解配置方法

【javaweb笔记1】自用_第72张图片

【javaweb笔记1】自用_第73张图片

4、获取配置参数方法

【javaweb笔记1】自用_第74张图片

5、405报错

因为没有重写servlet里的service方法,所以当网页会报错405,因为我们应该是执行get方法,进来的,doget方法里面会报405
【javaweb笔记1】自用_第75张图片

6、配置上下文参数

【javaweb笔记1】自用_第76张图片
注意配置的位置
在这里插入图片描述
在这里插入图片描述

这样可以获取 这是在Init 里面写的

在服务方法中也可以通过req获取

【javaweb笔记1】自用_第77张图片

【javaweb笔记1】自用_第78张图片

7、读取方法

【javaweb笔记1】自用_第79张图片
注意看他们的不同

五、业务层

【javaweb笔记1】自用_第80张图片

  1. 什么是业务层
    1) Model1和Model2
    MVC : Model(模型)、View(视图)、Controller(控制器)
    视图层:用于做数据展示以及和用户交互的一个界面
    控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型组件来完成
    模型层:模型分为很多种:有比较简单的pojo/vo(value object),有业务模型组件,有数据访问层组件
    1) pojo/vo : 值对象
    2) DAO : 数据访问对象
    3) BO : 业务对象
  1. 区分业务对象和数据访问对象:
    1) DAO中的方法都是单精度方法或者称之为细粒度方法。什么叫单精度?一个方法只考虑一个操作,比如添加,那就是insert操作、查询那就是select操作…
    2) BO中的方法属于业务方法,也实际的业务是比较复杂的,因此业务方法的粒度是比较粗的
    注册这个功能属于业务功能,也就是说注册这个方法属于业务方法。
    那么这个业务方法中包含了多个DAO方法。也就是说注册这个业务功能需要通过多个DAO方法的组合调用,从而完成注册功能的开发。
    注册:
    1. 检查用户名是否已经被注册 - DAO中的select操作
    2. 向用户表新增一条新用户记录 - DAO中的insert操作
    3. 向用户积分表新增一条记录(新用户默认初始化积分100分) - DAO中的insert操作
    4. 向系统消息表新增一条记录(某某某新用户注册了,需要根据通讯录信息向他的联系人推送消息) - DAO中的insert操作
    5. 向系统日志表新增一条记录(某用户在某IP在某年某月某日某时某分某秒某毫秒注册) - DAO中的insert操作
    6. …
    3) 在库存系统中添加业务层组件

六、IOC

【javaweb笔记1】自用_第81张图片

他想做到service删掉 controller 不报错
dao层删掉 service层 不报错
???
啊,就是那个不爆红

【javaweb笔记1】自用_第82张图片
【javaweb笔记1】自用_第83张图片
现在就要解决这个空指针的问题

private FruitService=null

一、核心思想

1、添加配置文件里

【javaweb笔记1】自用_第84张图片
在当前的配置文件里面配置三个bean
这三个bean其实就是对应的单个组件

计划在下一次启动中,他就会把这三个组件准备好,并且放在一个容器里面
谁想要的时候我就主动给谁

2、建立接口

【javaweb笔记1】自用_第85张图片

3、建立实现类

【javaweb笔记1】自用_第86张图片
建立实现类

实现 输入id获得对象的方法

建立一个容器

4、把之前 dispatcherServlet里面的那个方法提取出来

并把dispathcerServlet里面的错误解决掉

dispatcherServlet里面的这个方法报错
【javaweb笔记1】自用_第87张图片
解决方法
【javaweb笔记1】自用_第88张图片
调用这个接口里面的方法
【javaweb笔记1】自用_第89张图片

【javaweb笔记1】自用_第90张图片
但是这样做的问题是 我虽然的到了对象,但是那个对象指向的是Null,我需要把实现类注入进去

5、层与层之间的依赖,在配置文件里写

先描述需要那个组件
再描述组件之间的依赖关系
【javaweb笔记1】自用_第91张图片

【javaweb笔记1】自用_第92张图片
【javaweb笔记1】自用_第93张图片
这个name就是我 水果服务实现类 里面需要的那个属性名字 就是=null 的那个

【javaweb笔记1】自用_第94张图片

最终效果,需要哪个bean 和 bean之间的关系

6、组装bean之间的依赖关系

【javaweb笔记1】自用_第95张图片
只是获取对象扔到容器里面,并没有实现依赖

再看一遍这个这个是java操作节点的一些文档

【javaweb笔记1】自用_第96张图片
在这里插入图片描述
这个鬼东西有五个子节点

【javaweb笔记1】自用_第97张图片

【javaweb笔记1】自用_第98张图片

切记,在中央控制器的init 方法里面一定要 beanFactory初始化了【javaweb笔记1】自用_第99张图片

7、我NB了,之前觉得最难得一节课我也看懂了

IOC 依赖翻转
DI 依赖注入

8、好了,我要实现IOC了,开干

1、第一步是把bean 写到配置文件里面

pro什么那个我不会写
property
name 和 ref 不是 name 和 value

<beans>
    <bean id="fruit" class="com.kerwin.controller.fruitController">
        <property name="fruitService" ref="fruitService"/>
    bean>
    
    <bean id="fruitService" class="com.kerwin.service.impl.FruitServiceImpl">
        <property name="fruitDao" ref="fruitDao"/>
    bean>
    
    <bean id="fruitDao" class="com.kerwin.dao.FruitDao"/>
beans>

配置文件应该是这样吧,我自己写的

2、BeanFactory

我哭了,我的service 里面 用的是SqlSessionFactory session 方法,没有耦合

【javaweb笔记1】自用_第100张图片
这么定义hashMap怎么是错的啊,我超

卧榻嘛杀了,我居然没加括号??这是我写的????

3、依赖注入代码要写在哪个位置

卧槽我写完了,运行一下吧。

4、我虽然写完了,但肯定会出错,改完了,我就出去骑自行车
1、.InstantiationException 实例化异常

我的fruitDao 是一个接口,不能实例化

2、beanObj 可能找错了

要找那个有子节点,并且子节点名字为property 的类

七、总结

在这里插入图片描述

我把serviceimpl写在方法内,作用域小,写在成员变量位置,扩大作用域,线程会不安全

1、控制翻转

无论你把这个实例,写在方法体或者成员变量里,方法体内会频繁的创建销毁,成员变量就会好一些
虽然JAVA虚拟机 有自动垃圾回收机制
但是总的来说,实例的声明周期,是由程序员维护的

但是之后我们把这些实例通过配置文件和BeanFactory 放在了一个容器里面
这个容器创建,那么实例就创建
容器销毁,实例就销毁了
那么这些实例的声明周期就不在程序员的手上了
转移到BeanFactory 里了,这个BeanFactory就称之为IOC容器

2、依赖注入

review:

  1. Servlet生命周期中的初始化方法: init() , init(config)
    public void init(ServletConfig config) throws ServletException {
    this.config = config ;
    init();
    }
    因此,如果我们需要在初始化时执行一些自定义的操作,那么我们可以重写无参的init方法。
    我们可以通过getConfig()获取ServletConfig对象
    可以通过config.getInitParameter()获取初始化参数

  2. 通过ServletContext获取配置的上下文参数

  3. MVC : V:view 视图 ; C:Controller 控制器 ; M:Model 模型
    模型有很多种类:数据访问模型(DAO);业务逻辑模型(BO);值对象模型(POJO);数据传输对象(DTO)

  4. IOC
    IOC - 控制反转 / DI - 依赖注入
    控制反转:

    1. 之前在Servlet中,我们创建service对象 , FruitService fruitService = new FruitServiceImpl();
      这句话如果出现在servlet中的某个方法内部,那么这个fruitService的作用域(生命周期)应该就是这个方法级别;
      如果这句话出现在servlet的类中,也就是说fruitService是一个成员变量,那么这个fruitService的作用域(生命周期)应该就是这个servlet实例级别
    2. 之后我们在applicationContext.xml中定义了这个fruitService。然后通过解析XML,产生fruitService实例,存放在beanMap中,这个beanMap在一个BeanFactory中
      因此,我们转移(改变)了之前的service实例、dao实例等等他们的生命周期。控制权从程序员转移到BeanFactory。这个现象我们称之为控制反转

    依赖注入:

    1. 之前我们在控制层出现代码:FruitService fruitService = new FruitServiceImpl();
      那么,控制层和service层存在耦合。
    2. 之后,我们将代码修改成FruitService fruitService = null ;
      然后,在配置文件中配置:


创建domcument的方法

InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
        //1、创建DocumentBuilderFactory
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        //2、创建DocumentBuilder对象
        DocumentBuilder documentBuilder = null;
        try {
            //3、创建Document对象
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(resourceAsStream);
            //4、获取所有bean节点
            //根据标签名  根据 bean标签,来获取 一个 node集合
            NodeList beanList = document.getElementsByTagName("bean");

不懂得问题

重定向的路径 / 这个问题好迷糊

为什么那个反射 可以传object数组进去 懂了

我想知道在总控servlet里面使用return为什么不会是程序结束,我想在好像懂了一些,他也是servlet,执行完了就退出,我想找个时间,重新写一下那个手写web服务器

八、filter【javaweb笔记1】自用_第101张图片

1、 成为filter 要这样

【javaweb笔记1】自用_第102张图片

2、 filter放行

FilterChain filterChain   这个意思是过滤器链条
放行

xxxx(放行前执行这条)
filterChain.doFilter(req,resp)
xxxx(放行后  它回来了  执行这条)

3、 @WebFilter(这里要写的和servlet一样,不然怎么拦截?)【javaweb笔记1】自用_第103张图片

【javaweb笔记1】自用_第104张图片
mapping 映射的意思

4、 配置文件写法

【javaweb笔记1】自用_第105张图片

5、 扩大拦截范围

在这里插入图片描述
拦截所有资源 /* 访问所有资源时,过滤器都会被执行

6、 过滤器链条

【javaweb笔记1】自用_第106张图片

7、 过滤器链条执行顺序

1、注解方式 按照全类名字母顺序决定的
2、配置文件 是按照配置文件 写的先后顺序 谁先配置的先拦截谁

8、 应用

把设置编码做成过滤器放在前面
记得把servlet转换成HTTPservlet
【javaweb笔记1】自用_第107张图片

9、 容易错的地方

【javaweb笔记1】自用_第108张图片
记得写过滤器的时候,就算什么都没干,也要先把放行写了,类似与Mabits里面的close和 commit

10、 把编码格式写到文件里,不把他写死

【javaweb笔记1】自用_第109张图片
NB了,我超,这个老师,是真的会给你讲

11、我犯的错误

1、 servlet里面的urlPattern 要加/

@WebServlet("/demo.do")

2、过滤器里面的初始化方法和销毁方法,要把super那个去掉??
报错原因
原因是,过滤器中没有重写public void init()和 public void destroy() 方法,jdk 1.9 之后,可以不写这两个方法,如果用jdk1.8必须要写。

注意:
不能直接使用快速生成代码的重写方法,要把init和destroy() 里面的super都删掉,当然不删destroy中的依旧可以启动

3、转发那里,写的是 succ 但是我要转到的是succ.html 这是个错误

4、配置文件不会写
应该像filter标签,不能写servlet
然后 url-pattern 不能写引号
【javaweb笔记1】自用_第110张图片
5、这行报错,不能转换空值为httpservletRequest

(HttpServletRequest)servletRequest.setCharacterEncoding("utf-8");

需要套两个括号,我超

 ((HttpServletRequest)servletRequest).setCharacterEncoding("utf-8");

九、事务管理(不是service里面的事务管理)

1,引出问题

【javaweb笔记1】自用_第111张图片
【javaweb笔记1】自用_第112张图片
这个和我之前写的是一样的,看来最难得可能已经过去了
【javaweb笔记1】自用_第113张图片
【javaweb笔记1】自用_第114张图片

这意味着我的三个da里面的连接都需要用一个,用面向对象的方法,就是传参数
话说,我之前就是这么解决的

2、引出方法

我要的就是这个东西,不是太贴切,但就是这个么东西
【javaweb笔记1】自用_第115张图片

3、实现方法

1、在filters 里面 新建个类 实现Filters 方法

OpenSessionInViewFilter

拦截 *.do

2、获取conn 对象

建了个包 trans 建了个类 TransactionManager
【javaweb笔记1】自用_第116张图片
conn从ThreadLocal里面获取,
如果connection 不为空 就把他的自动提交设置为null

如果conn为空,就说明现在没有连接,我们就需要获取一个连接

【javaweb笔记1】自用_第117张图片
【javaweb笔记1】自用_第118张图片
老师是用JDBC的方法写的,而且没有把获取conn 抽取出去,需要把conn抽取出来,成为一个工具类,通过这个工具类获取连接,就像我的Mybatis里面的这个方法一样
【javaweb笔记1】自用_第119张图片
老师的获取驱动类
【javaweb笔记1】自用_第120张图片
【javaweb笔记1】自用_第121张图片

这样当ThreadLocal 里面没有conn 的时候,就可以获取到连接了,老师精简了下代码

【javaweb笔记1】自用_第122张图片

3、提交和回滚方法

【javaweb笔记1】自用_第123张图片
但是三个方法里面这个步骤 获取conn对象 是一样的
【javaweb笔记1】自用_第124张图片
所以要把它提取到获取连接的那个类里面去

3、获取conn抽取到 获取连接的工具类里面

注意静态 static 问题

1、把那个ThreadLocal 放到了 工具类里面

2
【javaweb笔记1】自用_第125张图片
3!在这里插入图片描述
这个方法也太NB了吧
4、那三个方法就变成这样了
【javaweb笔记1】自用_第126张图片

4、吐了,这只是基础的

比如说事务,两个业务方法包含的时候,这个就比较复杂,称为事务的传播机制

5、要去掉BaseDao里面的close方法

我写的mybatis的方法,所以要注释掉这个 session.close() 在这里关闭就完了

6、开始写了

【javaweb笔记1】自用_第127张图片
在这个过滤器里面调用那个 事务类的方法,他把他写成静态的了
【javaweb笔记1】自用_第128张图片
这么写
【javaweb笔记1】自用_第129张图片

7、从threadLocal中移除conn方法

【javaweb笔记1】自用_第130张图片
注意这个方法不严谨,应该写这个 threadLocal.remove
添加链接描述

之前的提交和回滚改成这样
【javaweb笔记1】自用_第131张图片

8、之后就是实验

故意写错,让他回滚,但是程序结果就会出错,原因是程序内部出错了,没有把错误抛出来,而是try catch了,需要把所有try catch 取消掉,然后把错误都抛出来

它在add 方法里 在调用DAO层的 edit方法,让edit的语句出错,同时回滚掉add添加的数据

好耶,我也模拟出来了,数据库添加成功,但是编辑报错,没有回滚掉add
【javaweb笔记1】自用_第132张图片
就是错误被内部给catch了,所以它提交了,没有回滚
【javaweb笔记1】自用_第133张图片
DAO层的try catch全删

9、老师不是吧try catch 全删了,保留 一部分 try catch 并且向外抛异常

1、先合并异常
【javaweb笔记1】自用_第134张图片
2、向外抛新的异常
【javaweb笔记1】自用_第135张图片

老师这里没有直接抛异常而是 新建了一个异常类原因如下

添加链接描述
【javaweb笔记1】自用_第136张图片
【javaweb笔记1】自用_第137张图片

干,我不会重写RuntimeException方法

1、原来是在构造方法里面写
2、日,原来super(直接就可以写)
3、干,我写了忘记抛了

成功了

【javaweb笔记1】自用_第138张图片

卧槽后面还有配置式和注解式的事务管理??

10.在git分支合并那里有不会的东西

添加链接描述

十、ThreadLocal中的get和 set源码分析

set方法

我之前搞不懂,ThreadLocal 是怎么区分 我要的是哪个值得,这下明白了,原来是通过threadLocal 1 threadLocal 2 threadLocal 3
这样分辨的
【javaweb笔记1】自用_第139张图片
2) ThreadLocal
- get() , set(obj)
- ThreadLocal称之为本地线程 。 我们可以通过set方法在当前线程上存储数据、通过get方法在当前线程上获取数据
- set方法源码分析:
public void set(T value) {
Thread t = Thread.currentThread(); //获取当前的线程
ThreadLocalMap map = getMap(t); //每一个线程都维护各自的一个容器(ThreadLocalMap)
if (map != null)
map.set(this, value); //这里的key对应的是ThreadLocal,因为我们的组件中需要传输(共享)的对象可能会有多个(不止Connection)
else
createMap(t, value); //默认情况下map是没有初始化的,那么第一次往其中添加数据时,会去初始化
}
在这里插入图片描述

get方法

@SuppressWarnings(“unchecked”)

告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。

-get方法源码分析:
public T get() {
Thread t = Thread.currentThread(); //获取当前的线程
ThreadLocalMap map = getMap(t); //获取和这个线程(企业)相关的ThreadLocalMap(也就是工作纽带的集合)
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this); //this指的是ThreadLocal对象,通过它才能知道是哪一个工作纽带
if (e != null) {
@SuppressWarnings(“unchecked”)
T result = (T)e.value; //entry.value就可以获取到工具箱了
return result;
}
}
return setInitialValue();
}

每一个threadMap 里面只有一对值、

添加链接描述

十一、Listener 一共有八个

1. 监听器

1) ServletContextListener - 监听ServletContext对象的创建和销毁的过程
2) HttpSessionListener - 监听HttpSession对象的创建和销毁的过程
3) ServletRequestListener - 监听ServletRequest对象的创建和销毁的过程

4) ServletContextAttributeListener - 监听ServletContext的保存作用域的改动(add,remove,replace)
5) HttpSessionAttributeListener - 监听HttpSession的保存作用域的改动(add,remove,replace)
6) ServletRequestAttributeListener - 监听ServletRequest的保存作用域的改动(add,remove,replace)

7) HttpSessionBindingListener - 监听某个对象在Session域中的创建与移除
8) HttpSessionActivationListener - 监听某个对象在Session域中的序列化和反序列化

2. 新建

【javaweb笔记1】自用_第140张图片

3. 配置方法

注解
【javaweb笔记1】自用_第141张图片
配置文件
【javaweb笔记1】自用_第142张图片

4. 应用

【javaweb笔记1】自用_第143张图片
启动性能低,响应 性能高

5. 在水果管理系统的应用

【javaweb笔记1】自用_第144张图片
【javaweb笔记1】自用_第145张图片
从上下文里面获取过来
【javaweb笔记1】自用_第146张图片
这样就不是当场new了,而是从作用域里面获取

在这里插入图片描述
等会看看我的beanMap里面有什么

6. 为什么这么做

因为dispatcherServlet 1、MVC 中间的角色 2、只是负责转发
而IOC容器 1、是所有组件的管理2、是控制层 业务逻辑层 数据访问层 以及这些层依赖关系的一个注入

IOC容器他的角色要比中央控制器大多了

7.优化硬编码 这里有些语法我没懂,我要先把它记录下来

【javaweb笔记1】自用_第147张图片
优化这个

8.自己写

1、干,监听器我不会写

Listener

我实现了方法,他怎么没让我重写啊

好像要自己手动敲上去

2、名字冲突

【javaweb笔记1】自用_第148张图片

3、但还是出错

啊,我好想没有给监听器 设置路径

4、我把这两个弄混了

@WebFilter
@WebListener

5、我靠 我的ClassPathXmlApplicationContext和老师的不一样

老师的把获取那个 NodeList beanList 这个东西放在构造方法里面了,我直接放在 public Object getBean(String name) { 这个方法里面了,年轻啊

6、沃日,不一样的也太多了吧

老师是这样的

public class ClassPathXmlApplicationContext implements BeanFactory {

    private Map<String,Object> beanMap = new HashMap<>();
    private String path = "applicationContext.xml" ;
    public ClassPathXmlApplicationContext(){
        this("applicationContext.xml");
    }
    public ClassPathXmlApplicationContext(String path){
        if(StringUtil.isEmpty(path)){
            throw new RuntimeException("IOC容器的配置文件没有指定...");
        }
        try {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path);
            //1.创建DocumentBuilderFactory
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            //2.创建DocumentBuilder对象
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder() ;
            //3.创建Document对象
            Document document = documentBuilder.parse(inputStream);

            //4.获取所有的bean节点
            NodeList beanNodeList = document.getElementsByTagName("bean");
            for(int i = 0 ; i<beanNodeList.getLength() ; i++){
                Node beanNode = beanNodeList.item(i);
                if(beanNode.getNodeType() == Node.ELEMENT_NODE){
                    Element beanElement = (Element)beanNode ;
                    String beanId =  beanElement.getAttribute("id");
                    String className = beanElement.getAttribute("class");
                    Class beanClass = Class.forName(className);
                    //创建bean实例
                    Object beanObj = beanClass.newInstance() ;
                    //将bean实例对象保存到map容器中
                    beanMap.put(beanId , beanObj) ;
                    //到目前为止,此处需要注意的是,bean和bean之间的依赖关系还没有设置
                }
            }
            //5.组装bean之间的依赖关系
            for(int i = 0 ; i<beanNodeList.getLength() ; i++){
                Node beanNode = beanNodeList.item(i);
                if(beanNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element beanElement = (Element) beanNode;
                    String beanId = beanElement.getAttribute("id");
                    NodeList beanChildNodeList = beanElement.getChildNodes();
                    for (int j = 0; j < beanChildNodeList.getLength() ; j++) {
                        Node beanChildNode = beanChildNodeList.item(j);
                        if(beanChildNode.getNodeType()==Node.ELEMENT_NODE && "property".equals(beanChildNode.getNodeName())){
                            Element propertyElement = (Element) beanChildNode;
                            String propertyName = propertyElement.getAttribute("name");
                            String propertyRef = propertyElement.getAttribute("ref");
                            //1) 找到propertyRef对应的实例
                            Object refObj = beanMap.get(propertyRef);
                            //2) 将refObj设置到当前bean对应的实例的property属性上去
                            Object beanObj = beanMap.get(beanId);
                            Class beanClazz = beanObj.getClass();
                            Field propertyField = beanClazz.getDeclaredField(propertyName);
                            propertyField.setAccessible(true);
                            propertyField.set(beanObj,refObj);
                        }
                    }
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }


    @Override
    public Object getBean(String id) {
        return beanMap.get(id);
    }
}

我是这样的

public class ClassPathXmlApplicationContext implements BeanFactory{

    private Map<String,Object> beanMap=new HashMap<String,Object>();

    String path="applicationContext.xml";



    @Override
    public Object getBean(String name) {
        InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
        //1、创建DocumentBuilderFactory
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        //2、创建DocumentBuilder对象
        DocumentBuilder documentBuilder = null;
        try {
            //3、创建Document对象
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(resourceAsStream);
            //4、获取所有bean节点
            //根据标签名  根据 bean标签,来获取 一个 node集合
            NodeList beanList = document.getElementsByTagName("bean");
            //然后循环这个集合


            for (int i = 0; i < beanList.getLength(); i++) {
                //这里面不叫get,叫item
                Node beanNode = beanList.item(i);
                if (beanNode.getNodeType() == Node.ELEMENT_NODE) {
                    //这个是 向上转型,用子类里面的方法
                    Element beanElement = (Element) beanNode;

                    String id = beanElement.getAttribute("id");
                    String className = beanElement.getAttribute("class");

                    //id对应实例对象
                    Class<?> aClass = Class.forName(className);

                    Object  beanObj = aClass.newInstance();


                    //把值放进去之后,再往集合里面放
                    beanMap.put(id, beanObj);
                    //我觉的要从这里开始,毕竟我要从map里面取对象

                }
            }
            for (int i = 0; i < beanList.getLength(); i++) {
                Node item = beanList.item(i);
                if (item.getNodeType() == Node.ELEMENT_NODE) {
                    Element element = (Element) item;
                    NodeList childNodes = element.getChildNodes();
                    if(childNodes.getLength()!=0){
                        String objectId = element.getAttribute("id");
                        Object thisObj = beanMap.get(objectId);

                        for (int j = 0; j < childNodes.getLength(); j++) {
                        Node item1 = childNodes.item(j);
                        if (item1.getNodeType() == Node.ELEMENT_NODE&&item1.getNodeName().equals("property")) {
                            Element element1=(Element) item1;
                            String propertyName = element1.getAttribute("name");
                            String propertyRef = element1.getAttribute("ref");

                            //这个beanObj 不能找错了
                            Class<?> aClass = thisObj.getClass();
                            Field declaredField = aClass.getDeclaredField(propertyName);
                            declaredField.setAccessible(true);

                            Object beanObject = beanMap.get(propertyRef);
                            //这步值应该就赋值进去了
                            declaredField.set(thisObj,beanObject);

                        }
                    }
                    }

                }

            }

        } catch (ParserConfigurationException | IOException | SAXException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        Object o = beanMap.get(name);
        return o;
    }
}

…我不知道之前有没有代码 写的这样 烂得离谱

7、无参调有参

添加链接描述

8、我靠我没有配置上下文初始ICO配置文件参数,我的tomcat直接启动不了

9、来吧,快三点了,整理完这个就睡觉

1、我说不太好,我直接写代码吧 改造beanFactory 实现类

public class ClassPathXmlApplicationContext implements BeanFactory{

    private Map<String,Object> beanMap=new HashMap<String,Object>();
    
    //这里给个默认值
    String path="applicationContext.xml";
    
    //老师说过 框架都是用无参构造去反射的,如果不写无参构造,框架就会报错
    //我可能需要无参构造去 用来反射,但是我这个月无参构造没有用,我需要调用下面的有参构造,
    //所以只能这么写了
    
    public ClassPathXmlApplicationContext() {
        this("applicationContext.xml");
    }

    public ClassPathXmlApplicationContext(String path) {
        if(StringUtils.isNull(path)){
            throw new RuntimeException("ICO配置文件参数出错");
        }
        InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(path);
        //1、创建DocumentBuilderFactory

2、改造触发器 listener 这个类

public class ContextListen implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext servletContext = sce.getServletContext();
        String path = servletContext.getInitParameter("contextConfigLocation");
        //注意如果这里的path 不写,那么就会默认调用无参构造,无参构造里面已经指定参数了
        //我这里如果没有获取到初始化参数,tomcat直接启动不了,老师那里却能启动,并且报错??
        BeanFactory beanFactory = new ClassPathXmlApplicationContext(path);

        servletContext.setAttribute("beanFactory",beanFactory);

    }

【javaweb笔记1】自用_第149张图片

3、设置初始化参数

  
    contextConfigLocation
    applicationContext.xml
  

这里报错不用管,老师说idea可能认为这是个spring配置文件,但是却不是

十二、复习

1、连接数据库
2、界面 thymeleaf
3、做了带有分页的
4、添加了根据关键字查询
5、对MCV结构进行优化

servlet->switch case ->反射(reflect)->提取dispatcherServlet(中央控制器)
servlet->controller
controller(1、获取参数2、业务处理3、视图资源转发) 抽取(1,2)->dispatcherServlet

service(多个单精度dao组合而成)

降低耦合,IOC容器 1、生命周期控制翻转到IOC容器 2、依赖注入

过滤器,监听器

事务管理(transaction)connection共享->ThreadLocal(OpenSessionViewFilter 过滤器事务)
TransactionManager(重复代码抽取->connUtil)

ThreadLocal源码

【javaweb笔记1】自用_第150张图片

十三、cookie了解

这部分的知识点,滚来滚去都要滚烂了

1、概念:

1、cookie是浏览器端保存一些数据,适当的时候,把保存的数据发给服务器

2、SessionId是以cookie的形式保存的

3、不同网站的cookie 不会共享

2、创建cookie

3、向客服端发送cookie,让客服端保存cookie

【javaweb笔记1】自用_第151张图片

请求头携带了cookie

【javaweb笔记1】自用_第152张图片

响应头发送了cookie

【javaweb笔记1】自用_第153张图片

请求头和响应头都携带了cookie

【javaweb笔记1】自用_第154张图片

4、设置cookie的有效时长

cookie.setMaxAge(20);  这个单位是秒
60*60*24*7 cookie保存7天

5、对cookie进行细分

6、一般情况下不用设置这么细

【javaweb笔记1】自用_第155张图片
在这里插入图片描述
这两个方法,我都没有用过,是在同一服务器的不同文件夹网站,或者跨域的情况下使用的,如果要使用的话,参考,自己再d多搜一搜

添加链接描述

添加链接描述

7、十天免登陆

1、客服端想服务端发送请求,会把cookie带过去,服务器去cookie里面取,看能不能取到10天免登陆的flag,如果有这种flag为true,表示曾经勾选过十天免登陆。
2、尝试去找Key 用户名 Value kerwin Key 密码 Value 123456 ,然后去后台验证,验证通过之后直接跳转首页

8、session 与 cookie 的区别

cookie客户端保存在本地,session保存在服务器

8、!!!切记,更新了cookie,比如时间,立即销毁cookie一定要把cookie发过去,更新浏览器的cookie

我在这里吃过大亏

resp.addCookie(cookie)

我在html设置了页面加载好的时候
自动访问servle
然后servlet里面判断如果 没有10天为登录的cookie
就会跳转到主页上
然后他两就这样起来了

9、webStorage

十四、VUE快速学习

我还是挺喜欢这节课的

1、那个神奇的scope 完成了对象属性发送的

这是个引子,自己慢慢搜索
添加链接描述
这个东西叫vue 插槽

好像和我想的不一样
算了,这部分先不学了,用的时候再说吧

2、导入js文件

<script type="text/javascript" src="js/vue.js"></script>

3、当页面加载完成的时候

window.οnlοad=function(){
}

window.οnlοad=function(){
var vue=new Vue({ })
}

这个括号里面就是键值对 Key:value

不能把方法和属性声明 放在window.onload里面

Vue就是一个对象,类似这个

【javaweb笔记1】自用_第156张图片

犯得错误:javascript 创建对象是 new Object; javascript创建对象的方法

javascript创建对象的方法。。添加链接描述

怎么定义对象方法。。

var person1={
       name:"kerwin1",
        age:181,
        sayHello:function (){
           alert(person1.name+"  sayHello");
        }
    }

怎么绑定成员方法…

document.getElementById("hello").onclick=person1.sayHello;

加不加括号,好像就是加了()就是把返回值赋给这个对象

添加链接描述
添加链接描述

执行方法之后的返回值 赋给 v-on:click
【javaweb笔记1】自用_第157张图片

4、新建Vue对象

0、这里面的属性左边加不加 “” 都可以

1、el是element的意思

【javaweb笔记1】自用_第158张图片

2、data数据 绑定

1、{{}}

{{ value }} 这个代表和el里面的data里面的属性绑定

    <script type="text/javascript" src="/js/vue.js"></script>
</head>
<body>
<div id="div0">
    <p>{{msg}}</p>
</div>
</body>
<script type="text/javascript">
    var vue=new Vue({
        el:"#div0",
        data:{
            msg:"hello"
        }
    });
    
</script>

2、v-bind

v-bind:value 表示绑定 value属性,v-bind 可以省略,也就是 :value

{{msg}}

你可能感兴趣的:(java)