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.

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

注意需要配置虚拟路径不能用tomcat插件

7.IDEA不使用插件配置

1.将本地Tomcat集成到Idea中,进行项目部署
步骤


选择本地tomcat目录

maven 创建java web项目

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自动导包

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地址

因为是第一次访问,服务器会塞给浏览器一个servlet地址,用的是response

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

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

2、保存作用域

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

3、一些API

4、 重定向和转发的区别

转发,服务器内部跳转 浏览器不知道

重定向:服务器命令浏览器:你立刻给谁谁谁发请求

4、路径问题

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、日志系统

<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.1.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-access</artifactId><version>1.1.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.1.7</version></dependency>

彩色日志 logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false"><property name="APP_NAME" value="MY_APP_NAME" /><property name="LOG_DIR" value="logs" /><property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS}  %-5level [%thread] %logger{15} - %msg%n" /><!-- 彩色日志格式 --><property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %boldYellow([%thread])  %cyan(%logger{15}) %msg%n"/><contextName>${APP_NAME}</contextName><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern></encoder></appender><appender name="FILE" class="ch.qos.logback.core.FileAppender"><file>${LOG_DIR}/logFile.log</file><append>true</append><encoder><pattern>${FILE_LOG_PATTERN}</pattern></encoder></appender><appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${LOG_DIR}/dayLogFile.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>${FILE_LOG_PATTERN}</pattern></encoder></appender><!-- 使用root的appender-ref --><logger name="com.example.Logger1" level="DEBUG" additivity="true"></logger><!-- 不使用root的appender-ref --><logger name="com.example.Logger2" level="DEBUG" additivity="false"></logger><logger name="com.example.Logger3" level="DEBUG" additivity="false"><appender-ref ref="STDOUT"/></logger><root level="DEBUG"><appender-ref ref="STDOUT" /><appender-ref ref="FILE" /><appender-ref ref="RollingFile" /></root>
</configuration>

2、jdbc

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>

mybatis

<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency>

3、test junit

junit @Test依赖

<!--引入junit的依赖       -->
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
</dependency>

2、配置部分

1、mapper 包扫描

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

这个是写在mybatis-config.xml

<mappers><mapper resource="org/mybatis/example/BlogMapper.xml"/></mappers><mappers><package name="com.kerwin.dao"/></mappers>

2、类型别名


resultType 需要把包名和类名都写上去


起了别名,就可以直接写类名,而且不区分大小写
这个是写在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语句

五、thymeleaf

1、依赖

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

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

<html xmlns:th="http://www.thymeleaf.org">

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

<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、部分标签

<th:if> <th:unless><th:each><th:text>

使用例子

<table id="table_fruit"><tr><th>名称</th><th>单价</th><th>库存</th><th>购买地址</th><th>操作</th></tr><tr th:if="${#lists.isEmpty(session.fruitList)}"><td colspan="4">列表数据为空</td></tr><tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}"><!-- <td  ><a th:text="${fruit.fName}" th:href="@{'/edit.do?fId='+${fruit.fId}}">苹果</a></td>--><td><a th:text="${fruit.fName}" th:href="@{/edit.do(fId=${fruit.fId})}">苹果</a></td><!--这里要把id带过去,才能去查询--><!--用 . 其实就是在get方法--><td th:text="${fruit.fPrice}">5</td><td th:text="${fruit.fCount}">100</td><td th:text="${fruit.fRemark}">拼多多</td><td><img src="imgs/del.jpg" class="delImg" th:onclick="|deleteById(${fruit.fId})|"></td></tr>
</table>

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、不用相对路径并设置根路径

先设置一个根路径

<base href="http://localhost:8080/day01">

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

<link href="js/vue.js">
<link rel="stylesheet" href="css/index.css">

但是要注意,这个是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、直接写属性名,就是设置所有属性


这种结构,我以为只是改了个背景色,没想到居然是这个做的

<body><div id="div_container">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、添加图片

<td><img src="imgs/del.jpg" </td>

9、合并单元格

<td colspan="4">列表数据为空</td><td colspan="2"><input type="button" value="修改"></td>

写在html页面里,不是css

10、选中某一种类型

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

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

1、渲染覆盖

<td th:text="${fruit.fName}"><a href="edit.do"> 苹果</a></td>

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

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

@WebServlet("/fruit")
public class FruitServlet extends ViewBaseServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {FruitService fruitService=new FruitServiceImpl();List<Fruit> fruitsList = fruitService.selectAll();HttpSession session = req.getSession();session.setAttribute("fruitList",fruitsList);super.processTemplate("index",req,resp);}}

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

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

2、路径问题

<td ><a th:text="${fruit.fName}" href="edit.do">苹果</a></td>

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

<td  ><a th:text="${fruit.fName}" th:href="@{edit.do}">苹果</a></td>

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

3、height设置不生效问题

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

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

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

html ,body{height: 100%;
}

4、取消body边距无效

原因:我的

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

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

<td  ><a th:text="${fruit.fName}" th:href="@{edit.do}">苹果</a></td>

这行代码对应的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那个绑定变量怎么写

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

 <tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}"><!-- <td  ><a th:text="${fruit.fName}" th:href="@{'/edit.do?fId='+${fruit.fId}}">苹果</a></td>--><td><a th:text="${fruit.fName}" th:href="@{/edit.do(fId=${fruit.fId})}">苹果</a></td><!--这里要把id带过去,才能去查询--><!--用 . 其实就是在get方法--><td th:text="${fruit.fPrice}">5</td><td th:text="${fruit.fCount}">100</td><td th:text="${fruit.fRemark}">拼多多</td><td><img src="imgs/del.jpg" class="delImg"></td></tr>
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; 无效

<!--<form method="post" th:action="@{/add}">-->

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

3、取消超链接下划线

text-decoration=none

4、删除

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

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

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

测试的时候,点那个小箭头,就能看代码生没生效

5、引入js

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

6、删除delete语句

delete from fruit where f_id=x;

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

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

4、分页查询

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

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

前端是这么写的

 <div id="pageButton" ><input type="button" class="big" value="首 页" th:onclick="page(1)" th:disabled="${session.page==1}"><input type="button" class="big" value="上一页" th:onclick="|page(${session.page-1})|" th:disabled="${session.page==1}"><input type="button" class="big" value="下一页" th:onclick="|page(${session.page+1})|" th:disabled="${session.page==session.lastPage}"><input type="button" class="big" value="尾 页" th:onclick="|page(${session.lastPage})|" th:disabled="${session.page==session.lastPage}"></div>

(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、判断是否是摁钮不可用

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

这个结果是true
同理

5、根据关键字查询

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

先写后端,然后测试

再写前端

1、模糊查询

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

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

<select id="fuzzyQuery" resultType="com.bin.pojo.Book">select * from mybatis.book where bookName like concat('%',#{info},'%');
</select>

2、提交查询关键字

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

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

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

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

6、总结

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

七、MVC各个层的设计

连接进来

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容器 控制翻转 依赖注入

用标签来指定依赖

伪代码
<bean id="fruit" //这个是控制器<property fruitService<bean id="fruitService"<property fruitDal<bean id="fruitDAO"

一、servlet优化1

1、总体思想

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

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

2、function方法怎么改

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、通过方法名 用反射实现

2、默认的index

我真他妈草了,一直在怎么得不到参数,让他去找index,直接在上面设置值就可以了

3、反射的对象获取

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

二、servlet优化2.1 dispatcherServlet引入

步骤

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

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

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

2、中央控制器的概念

1、实现步骤

1、新建servlet,拦截*.do为结尾的请求
2、得到字符串对应控制器

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

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

5、声明这么写

1、xml声明的固定写法
<??>
<?xml version="1.0" encoding="utf-8"?>
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,解析出一个名字

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

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

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

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

之前FruitServlet是一个servlet组件,那么其中的Init方法一定会被调用
之前的init方法会出现一句话,super.init

有了这句话就会对用 viewBaseServlet 里面的init 方法

现在它已经不是servlet方法了,所以不会去调用init方法,也就不会去调用viewBaseServlet 里面的init 方法


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


在里面写一个

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

ServletContext就是最大的那个作用域

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

写一个set方法


把之前调用 成员变量 变成成员方法

把参数扔到 view那个里面

扔到这里面

5、还是没用的原因


这个值的获取方法没改

6、这么改

这里也改一下就好了

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


中央控制器类 dispatherServlet

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

1、解决转发冗余


把这个String发送给中央控制器,让中央控制器帮我们进行统一的转发


不知道要干嘛

截取还能这么用,我真是震惊

核心代码

 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了

2、解决那个需要view的


别忘了,这个调用初始化

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

1、解决那个需要view的

我超,他把req,和resp都删了
异常也删掉

真就解耦呗

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

2、统一抽取到父类里面 就是DispatcherServlet里面

三步走

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、解决方法是获取所有方法,然后循环


但是获取不到方法名

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

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


这个表示在编译的时候,形参自带参数名称
.class文件会稍微大一点
记得把编译好的文件删一下,重新编译


真实名称就搞到了

5、把参数存到数组里面

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


这三个参数是不需要req.getParameter的

最终写法

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

7、程序逻辑bug

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


错误原因是,访问主页的时候

这张图片里的page是null 然后默认给了1 ,但是一旦,点了下一页


这里就要值了,但是page这个值应该是integer 我往数组里放的是String


可以查看参数类型

java.lang.Integer


这样就不会报 参数类型不匹配了

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

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

1、语言等级

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

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

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

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

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

4、草拟吗啊,我为什么 -parameters这个不好使,在maven上配置也不好使
    <build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version><configuration><source>1.8</source><target>1.8</target><encoding>utf8</encoding><compilerArgs><arg>-parameters</arg></compilerArgs></configuration></plugin></plugins></build>

用了这个好使了,可能可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可以存nullif(!parameter1.equals("null")){paraObj = Integer.valueOf(parameter1);}}
 if(typeName.equals("java.lang.Integer")){//integer可以存nullif(!(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


如果我们想在servlet初始化时做一些准备工作,我们可以
重写那个Init()空实现方法
init 方法只会执行一次

2、配置文件配置方法

3、注解配置方法

4、获取配置参数方法

5、405报错

因为没有重写servlet里的service方法,所以当网页会报错405,因为我们应该是执行get方法,进来的,doget方法里面会报405

6、配置上下文参数


注意配置的位置

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

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

7、读取方法


注意看他们的不同

五、业务层

  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

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



现在就要解决这个空指针的问题

private FruitService=null

一、核心思想

1、添加配置文件里


在当前的配置文件里面配置三个bean
这三个bean其实就是对应的单个组件

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

2、建立接口

3、建立实现类


建立实现类

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

建立一个容器

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

并把dispathcerServlet里面的错误解决掉

dispatcherServlet里面的这个方法报错

解决方法

调用这个接口里面的方法


但是这样做的问题是 我虽然的到了对象,但是那个对象指向的是Null,我需要把实现类注入进去

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

先描述需要那个组件
再描述组件之间的依赖关系



这个name就是我 水果服务实现类 里面需要的那个属性名字 就是=null 的那个

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

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


只是获取对象扔到容器里面,并没有实现依赖

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



这个鬼东西有五个子节点

切记,在中央控制器的init 方法里面一定要 beanFactory初始化了

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 方法,没有耦合


这么定义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、创建DocumentBuilderFactoryDocumentBuilderFactory 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

1、 成为filter 要这样

2、 filter放行

FilterChain filterChain   这个意思是过滤器链条
放行xxxx(放行前执行这条)
filterChain.doFilter(req,resp)
xxxx(放行后  它回来了  执行这条)

3、 @WebFilter(这里要写的和servlet一样,不然怎么拦截?)


mapping 映射的意思

4、 配置文件写法

5、 扩大拦截范围


拦截所有资源 /* 访问所有资源时,过滤器都会被执行

6、 过滤器链条

7、 过滤器链条执行顺序

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

8、 应用

把设置编码做成过滤器放在前面
记得把servlet转换成HTTPservlet

9、 容易错的地方


记得写过滤器的时候,就算什么都没干,也要先把放行写了,类似与Mabits里面的close和 commit

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


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 不能写引号

5、这行报错,不能转换空值为httpservletRequest

(HttpServletRequest)servletRequest.setCharacterEncoding("utf-8");需要套两个括号,我超((HttpServletRequest)servletRequest).setCharacterEncoding("utf-8");

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

1,引出问题



这个和我之前写的是一样的,看来最难得可能已经过去了

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

2、引出方法

我要的就是这个东西,不是太贴切,但就是这个么东西

3、实现方法

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

OpenSessionInViewFilter

拦截 *.do

2、获取conn 对象

建了个包 trans 建了个类 TransactionManager

conn从ThreadLocal里面获取,
如果connection 不为空 就把他的自动提交设置为null

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



老师是用JDBC的方法写的,而且没有把获取conn 抽取出去,需要把conn抽取出来,成为一个工具类,通过这个工具类获取连接,就像我的Mybatis里面的这个方法一样

老师的获取驱动类

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

3、提交和回滚方法


但是三个方法里面这个步骤 获取conn对象 是一样的

所以要把它提取到获取连接的那个类里面去

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

注意静态 static 问题

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

2

3!在这里插入图片描述
这个方法也太NB了吧
4、那三个方法就变成这样了

4、吐了,这只是基础的

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

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

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

6、开始写了


在这个过滤器里面调用那个 事务类的方法,他把他写成静态的了

这么写

7、从threadLocal中移除conn方法


注意这个方法不严谨,应该写这个 threadLocal.remove
添加链接描述

之前的提交和回滚改成这样

8、之后就是实验

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

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

好耶,我也模拟出来了,数据库添加成功,但是编辑报错,没有回滚掉add

就是错误被内部给catch了,所以它提交了,没有回滚

DAO层的try catch全删

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

1、先合并异常

2、向外抛新的异常

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

添加链接描述

干,我不会重写RuntimeException方法

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

成功了

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

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

添加链接描述

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

set方法

我之前搞不懂,ThreadLocal 是怎么区分 我要的是哪个值得,这下明白了,原来是通过threadLocal 1 threadLocal 2 threadLocal 3
这样分辨的

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. 新建

3. 配置方法

注解

配置文件

4. 应用


启动性能低,响应 性能高

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



从上下文里面获取过来

这样就不是当场new了,而是从作用域里面获取


等会看看我的beanMap里面有什么

6. 为什么这么做

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

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

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


优化这个

8.自己写

1、干,监听器我不会写

Listener

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

好像要自己手动敲上去

2、名字冲突

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.创建DocumentBuilderFactoryDocumentBuilderFactory 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();}}@Overridepublic 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";@Overridepublic Object getBean(String name) {InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");//1、创建DocumentBuilderFactoryDocumentBuilderFactory 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,叫itemNode 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 {@Overridepublic void contextInitialized(ServletContextEvent sce) {ServletContext servletContext = sce.getServletContext();String path = servletContext.getInitParameter("contextConfigLocation");//注意如果这里的path 不写,那么就会默认调用无参构造,无参构造里面已经指定参数了//我这里如果没有获取到初始化参数,tomcat直接启动不了,老师那里却能启动,并且报错??BeanFactory beanFactory = new ClassPathXmlApplicationContext(path);servletContext.setAttribute("beanFactory",beanFactory);}

3、设置初始化参数

  <context-param><param-name>contextConfigLocation</param-name><param-value>applicationContext.xml</param-value></context-param>

这里报错不用管,老师说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源码

十三、cookie了解

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

1、概念:

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

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

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

2、创建cookie

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

请求头携带了cookie

响应头发送了cookie

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

4、设置cookie的有效时长

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

5、对cookie进行细分

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



这两个方法,我都没有用过,是在同一服务器的不同文件夹网站,或者跨域的情况下使用的,如果要使用的话,参考,自己再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就是一个对象,类似这个

犯得错误: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

4、新建Vue对象

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

1、el是element的意思

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

<div id="div0"><input type="text" v-bind:value="name"></input><p>{{msg}}</p>
</div>
</body>
<script type="text/javascript">var vue=new Vue({el:"#div0",data:{msg:"hello",name:"kerwin"}});

2、v-model

v-model:value
:value 可以省略

不仅可以吧对象的属性值渲染到页面上,还能当页面上数据修改后反向修改属性值

<div id="div0"><input type="text" v-model:value="name"></input><p>{{msg}}</p><p>{{name}}</p>
</div>
</body>
<script type="text/javascript">var vue=new Vue({el:"#div0",data:{msg:"hello",name:"kerwin"}});

3、trim 可以去除首尾空格

v-model.trim

3、条件渲染

&nbsp 空格

空格,在html 里,不管多少个“ ”(这里是5个空格),但在网页里只显示1个的距离,所以要用 来代替。

1、v-if v-else

v-if

v-if 后面接的是== = ==

 <div v-if="num%2==0" style="width:80px;height:80px;display:block;background-color:red"></div><input type="text" v-model:value="num"></input>data:{msg:"hello",name:"kerwin",num:1}

如果这个不成立,整个div就都没有了

v-else

<div v-if="num%2==0" style="width:80px;height:80px;display:block;background-color:red"></div><div v-else="num%2==1" style="width: 80px;height: 80px;background-color: green"></div>

v-if 和 v-else 直接不能有其他标签!!!

v-show


v-show 是利用display来控制显示或不显示的

v-for

之前thymeleaf 里面 列表循环是这样的 fruit : ${session.fruitList}

嘿,你别说,看着还挺高级的

vue里面是 fruit in fruitList

1、先准备一个数组


犯的错误

1、fruit数组是这么定义的

fruit[]
fruit[{}]
fruit[{key:value,key:value},{key:value,key:value},]


没有反应

要在tr里面写td

表格属性

cellspacing=“0” 合并边
cellpadding=“5px” 单元边沿与其内容之间的空白

java Stream api

引子添加链接描述

完了,全忘完了

4、事件绑定

v-on:click

1、当点击的时候吧某一个字符串翻转

不好使

原来要赋给 msg

这里需要""

2、获取当前鼠标的坐标(好像用不到)

3、侦听属性 watch

1、监听,简易计算

2、我犯的错误

watch 后面的代码不会写

不好使

直接写watch ,不要写在methods里面

5、vue生命周期 钩子函数

vue对象创建之前
beforeCreate
vue对象创建了
created
vue创建好了,但还没有装载值,数据装载之前
beforeMount
数据装载之后
mounted
数据有更新之前
beforeUpdate
数据更新完成之后
updated
vue 对象销毁之前
beforeDestroy
vue 对象销毁之后
destroyed


1、钩子函数

十五、跳过原生ajax和 Axios 发送 普通参数请求

发送的请求体是json

1、什么是json

JSON是一种数据格式
表示两个学生对象

2、XML也是一种数据格式
表示两个学生对象

3、json表达数据更加简洁,更能节约网络带宽(是指在单位时间(一般指的是1秒钟)内能传输的数据量)
坏处,过于灵活

很有可能看第一条数据,你不知道他还有address属性

2、发送json

发送普通数据,servlet里面要修改这个

string stringBuild stringBuffer 区别

添加链接描述

2、发送与接收


用GsonBuilder 创建功能会强一些,比如做格式化,假如你的pojo 实体类里面有日期类型的
以后有需求再说

1、接收json

2、json转换对象

3、对象转换json

3、MIME类型

添加链接描述
比如我要向客户端发送json数据,我要告诉客户端我发送的是json数据

MIME类型的基础格式是 大类/具体类型

4、客户端接收

1、服务器端给客户端响应json格式的字符串,然后客户端需要将字符串转化为jsObject

2、给浏览器打断点

3、给vue data 赋值

4、java 和 javascript 都有 json的api

1、java

2、javascript

5、字符串中的\ 是干嘛的

6、js string -> js object JSON.parse(str)

7、js object->js string JSON.stringify(Object)

8、简化方式,沃日

9、因为代码越来元复杂了,除非沙比的bug,其他代码不熟练,将不会被记录

1、json 字符串 不会写

var user="/"name/":/"kerwin/",/"age/":/"18/"";

干,写反了
数字不要加""

var user="{\"name\":\"kerwin\",\"age\":18}";

2、axios data 怎么写

methods:{axios1:function (){axios({method:"POST",url:"user.do",data:{name:vue.user.name,age:vue.user.age}}).then({})}}

3、引入axios 出错

用idea直接拉文件到主窗口过去没有问题,自己打的就有问题??

4、我靠,怎么把json对象写回去?

setContentType Content=内容,靠,居然没保存

user.setName("张鹏");user.setAge(26);String userStrToVue = gson.toJson(user);//把对象写回去response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().write(userStrToVue);

10、黑马的响应成功的方法


十六、element 做登录界面

1、卡片套文本框



操作摁钮也用不到,整行删掉

达到这样一个结构

2、里面塞个表单


塞到主体内容里面

js,代码

因为表单在用的时候有很多选项,在配置json对象的时候也允许这么去配
通过对象去 " . "

并且在属性上,它自己又多加了一个绑定的model 去绑定 根元素 (form),用起来会更方便

配合element ui 都是用ajax 去发请求的

3、改造

1、删除冗余

2、密码框


4、qs的作用




老师说,变成这样 tomcat 会自动帮我解析?不太懂

5、用户名 密码后面加图标


直接加就可以

效果

6、文本框 校验 这个我做过

1、使用方法



老师是自己把属性加上去的,真NB啊,我只会复制粘贴

7、文本框 校验不通过,请求不发出去

ref 把表单注册给 vue !! 重要知识点

1、传一个参数,参数是form的name

2、$refs   带"$"符号  是注册给vue对象的一些参数和属性  比如找 "el"

refs 是注册给vue 对象的组件

组件就是vue封装好的让你来复用

我们现在如果要做校验,我们要先找到当前的form组件,把它注册给vue

怎么把组件注册给vue 呢 很容易
在属性上写ref,然后

这里解释更清楚些:添加链接描述


在28分33 这里

我们没有传值,直接写死了


接收返回值

8、重置表单


通过this refs 注册的组件里面 找到我们刚才注册好的Loginform 直接调 resetFields() 这个方法

这里用不是写死的方法(传形参)


重置功能只重置密码框

form 里面的 el from item 里面都要有 prop 属性,有这个属性, 才会帮你进行控制

不管下面有没有验证规则 如果想让重置控制起来 要加prop 属性

9、去掉必填属性左边的红点



10、校验没过,自己加提示框



直接加就可以了

11、来了,来了,自己写一个登录界面(看看我能犯什么傻逼错误)

1、怎么居中来着

margin: 140px auto;

2、图标不会设置

原来图标设置的位置 和不同的组件 是有区别的

2、输入框长度


3、prop 直接写属性名就可以

4、不会隐藏星星 *

我超,直接加载表单根上面

5、方法写对了,但是vue报错

原来是断网了,插件没有从网上下载下来

6、我qs怎么点不出来啊

7、引入依赖

添加链接描述

1、引入Qs


原来不是 . 出来的,是自己敲出来的

十七、element 做动态菜单页面

1、JS页面跳转

这个是JS跳转,不是vue跳转
我之前理解错了
详情,看这个引子添加链接描述

2、找一个上左右的结构

常见的布局就是上左右


一些概念类的东西

1、Flex 布局

添加链接描述


2009年,W3C提出了一种新的方案—-Flex布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。

2、element 容器标签

3、怎么找文档,看自己不认识的标签

3、把页面占满


他说的不是页面边距,而是页面只占了上面那20%左右的地方

1、扩html,body

2、扩根标签

3、还是没有效果,里面套的内容也要扩

4、element ui 的样式比较特殊!!重要内容

代码是这样的
在浏览器编译后是这样的

看到了吗,标签名是类名
1、他在展示页面效果的时候,是会重新组织元素的元素名的

没太懂

哦哦,懂了

我们看到的这些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

el-submenu 有展开效果的菜单,就是子菜单
el-menu-item 没有展开效果的菜单
el-menu-item-group

6、索引或者标记



这种形式,不是太懂

5、精简

6、内部属性

1、摁钮模板


slot 用法 引子
添加链接描述
添加链接描述

可以更换文字和图标

2、分组和不分组

不要分组


效果

需要用到的标签

7、用户菜单

1、应该做到不同用户,看到的是不同的菜单

如果不这样做,客户看到的菜单一样,但是有的选项因为权限不够,不能用会有挫败感

2、难点:不同的用户登录上来要显示不同的左侧菜单 菜单不能写死了

登录的时候后台知道用户有哪些权限

3、动态下拉效果

从后台拿数据来展示到前端页面上

4、先不管后台,前台找到结构,遍历就可以了

后端需要传回有父子结构的数据

1、做假数据

一级菜单:
二级菜单:

2、图标和路径

3、手动拼接要做数据校验

添加链接描述

5、用这个结构去遍历

这个错误是数据少了括号

6、一级菜单遍历参数填写


一定要加: 注意是v-bind

7、二级菜单遍历参数填写

v-for 里面可以嵌套循环

8、动态菜单概述

1、在用户登录的时候,要查出来,它具有哪些菜单的功能权限
2、并且拼成这种有父子结构的json数据,发到前端
3、前端读取,展示数据

9、二级菜单的链接地址



去掉链接下划线

10、不想要多个菜单都展开的效果


8、看看我会犯什么错误

1、json 嵌套代码不会写


子直接在,后面写就行


记得 submenu 也要加 “”

2、v-for 要写在哪里啊

哪里遍历,写在哪里

【javaweb笔记1】自用相关推荐

  1. JavaWeb笔记:JDBC总结

    JavaWeb笔记:JDBC总结 目录 JavaWeb笔记:JDBC总结 一.JDBC概述 二.开发一个JDBC程序(重要) 三.JDBC常用的类和接口详解 1.java.sql.Drivermana ...

  2. JavaWeb笔记:CSS总结

    JavaWeb笔记:CSS总结 目录 JavaWeb笔记:CSS总结 一.css的简介 二.css选择器 三.css属性 四.css盒子模型 一.css的简介     1.什么是css        ...

  3. JavaWeb笔记:Html总结

    JavaWeb笔记:Html总结 目录 JavaWeb笔记:Html总结 一.html简介 二.html基本标签 三.html表单标签(重点) 一.html简介     1.html是什么       ...

  4. JavaWeb笔记:第07章 MVC |EL |JST |Filter |Listener |JQuery |AJAX |Maven |JSON |Redis |Linux |Nginx

    JavaWeb笔记:第07章 MVC |EL |JST |Filter |Listener |JQuery |AJAX |Maven |JSON |Redis |Linux |Nginx 1. MVC ...

  5. 联想y7000-2019黑苹果安装笔记(自用)

    联想y7000-2019黑苹果安装笔记(自用) 第一步:bios设置 第二步:准备文件和程序 第三步:安装MAC 第四步:享受MAC 首先感谢各位大佬提供的教程和相关程序文件. 本文全程参考https ...

  6. MYSQL学习笔记(自用)第九章

    MYSQL学习笔记(自用)第九章 第一节. 触发器 | Triggers DELIMITER $$CREATE TRIGGER payments_after_insertAFTER INSERT ON ...

  7. MYSQL学习笔记(自用)第七章

    MYSQL学习笔记(自用)第七章 第一节.创建视图| Creating Views USE sql_invoicing;CREATE VIEW sales_by_client AS SELECT c. ...

  8. Linux学习笔记(自用)

    Linux学习笔记(自用) 该笔记由尚硅谷的"3天上手LInux"视频整理而成,若有侵权,请联系作者删除 文章目录 Linux学习笔记(自用) 1. 概述 2. 下载 3.文件与目 ...

  9. 25-day24黑马javaweb笔记-redis

    目录 25-day24黑马javaweb笔记-redis 概念 什么是NOSQL 主流的NOSQL产品 什么是Redis 下载安装 命令操作 1. redis的数据结构: 2. 字符串类型 strin ...

最新文章

  1. 骚操作:不重启 JVM,如何替换掉已经加载的类?
  2. 清华大学第四届大数据开放日(Big Data Day)
  3. python写入csv文件的几种方法
  4. SSM框架下结合 log4j、slf4j打印日志
  5. Android L 仍需改善的三个问题
  6. 设计模式方法VB.NET机房个人重构版-磨刀篇(一)
  7. Json数组列表中的数据分组排序、组内排序
  8. TODO-MVP-Loaders源码体验
  9. linux一些好用的命令和快捷键
  10. mysql5.7是测试版本吗_mysql免安装版本测试(mysql-5.7.18-winx64)
  11. 备份spfil、控制文件等
  12. anguarjs 上传图片预览_前端图片上传那些事儿
  13. 【Python】Python3.7.3 - Collections (Arrays) - List数据类型
  14. 【excel技巧读书笔记007】此工作薄包含一个或多个无法更新的链接
  15. 我的世界boat运行库JAVA10_我的世界boat运行库
  16. 英语测试用什么软件有哪些,学习英语的软件哪个好 什么比较好用
  17. 语音处理:音频信号采样点白化方法初探
  18. Quiz-Style Question Generation for News Stories
  19. AI基础:图解Transformer
  20. GBase 8c产品简介

热门文章

  1. contactform7 ajax,WordPress询盘插件 – Contact Form 7
  2. 5906. 【NOIP2018模拟10.15】传送门 (portal)
  3. Chained Predictions Using Convolutional Neural Networks
  4. 一些关于三角函数的公式
  5. javascript escape()和unescape()区别
  6. 高数基础-第五章-反常积分的计算
  7. Android 仿手机通讯录页面
  8. 2009年度EXIN中国金牌、银牌、铜牌以及常规授权机构
  9. 中国无酒精饮料包装行业市场供需与战略研究报告
  10. background-size cover和contain的区别