JavaWeb学习笔记
站得高,看得远,从设计框架的角度出发去思考问题。
源码不能只看,一定要上手。
HTML
- html语言是解释型语言,不是编译型,浏览器是容错的,写错了浏览器也会解析。
- html页面中由一对标签组成:
<html>
开始标签,</html>
结束标签 - html中有
<head>
标签和<body>
标签 - head标签中的title表示网页的主体(浏览器的标签上显示),可以在meta标签中设置编码方式
表示换行 。br标签是一个单标签。单标签:开始标签和结束标签是同一个,斜杠放在单词后面- p 表示段落标签
- img 标签图片标签
- h1~h6 : 标题标签
- 列表标签:
- ol 有序列表(start 表示从第几开始,type 显示的类型:A a I i 1(deafult))
- ul 无序列表(type disc(default) , circle , square)
- u 下划线 b 粗体 i 斜体
- 上标 sup 下标 sub
- HTML中的实体: 小于号 < 大于等于号 ≥ 版权 ©
- span 不换行的块标记
- a 表示超链接
- href 链接的地址
- target:
-_self 在本窗口打开
-_blank 在一个新窗口打开
-_parent 在父窗口打开
-_top 在顶层窗口打开
- div 层
- 表格 table
- 行 tr(table row)
- 列 td(table data,行中的一个小格)
- 表头列 th(table head)
- table中有如下属性(虽然已经淘汰,但是最好了解一下)
- border:表格边框的粗细
- width:表格的宽度
- cellspacing:单元格间距
- cellpadding:单元格填充
- rowspan : 行合并(tr)
- colspan : 列合并(td)
- tr中有一个属性: align -> center , left , right,居中、居左、居右
- 表单 form
input type="text" 表示文本框 , 其中 name属性必须要指定,否则这个文本框的数据将来是不会发送给服务器的
input type="password" 表示密码框
input type="radio" 表示单选按钮。需要注意的是,name属性值保持一致,这样才会有互斥的效果;可以通过checked属性设置默认选中的项
input type="checkbox" 表示复选框。name属性值建议保持一致,这样将来我们服务器端获取值的时候获取的是一个数组
select 表示下拉列表。每一个选项是option,其中value属性是发送给服务器的值 , selected表示默认选中的项
textarea 表示多行文本框(或者称之为文本域),它的value值就是开始结束标签之间的内容
input type="submit" 表示提交按钮
input type="reset" 表示重置按钮
input type="button" 表示普通按钮
input type="text" 表示文本框 , 其中 name属性必须要指定,否则这个文本框的数据将来是不会发送给服务器的
input type="password" 表示密码框
- frame,表示框架中的具体页面引用
frameset 表示页面框架,这个标签已经淘汰,了解,把页面划分为多个页面,不能有body标签
iframe,页面上嵌入其他页面,放在body里
# html中页面显示效果相关的标签、属性基本都淘汰了,使用css替代(层叠式样式表)
CSS
- html决定页面上显示哪些内容,CSS决定显示的样式、风格
- css代码可以完全脱离html
- 基础语法:标签样式表,类样式表,ID样式表,组合样式。
- 从位置上:嵌入式样式表(在标签的内部写),内部样式表(style标签内),外部样式表(.css)
- 盒子模型:border(边框),margin(间距),padding(填充)
- 定位和浮动:position,float,div+css布局
JavaScript
- 客户端(浏览器端)运行的一个脚本语言,语法风格与java比较类似,是一门弱类型的语言,变量的数据类型由后面赋的值的类型决定。
- 有一些内置对象:window,document
- 函数 function hello(){},调用时参数可任意传
- js代码可以完全脱离html,标签绑定事件可以在页面加载时
window.onload
使用js绑定
Servlet
tomcat安装使用
- 下载:https://mirrors.cnnic.cn/apache/tomcat/ ,解压即可,版本选择参考官网
- 需要配置好JAVA_HOME环境变量
- idea配置
- 启动项中配置tomcat启动,在模板中配置好tomcat的home目录
- 创建一个启动项,选择tomcat,deployment配置自己的工程,如果没有artifact选项,需要在Project Structure -> Artifacts中添加Web Applicatoin,选择From Modules,选择项目
- Application context配置为/
- 返回server界面,配置
On Update action
为Redeploy,配置On frame deactivation
为Update classes and resources。 - tomcat输出乱码问题:在idea Help -> Edit custom VM options,增加
-Dfile.encoding=UTF-8
- 代码没有编译到
WEB-INF
下:在Artifacts下,Output Layout
,Available Elements
右键Put into Output Root
,然后重启idea,或者删除idea的配置文件,重写加载项目,后加的依赖也需要使用这种方式将依赖加到部署项目的WEB-INFO下的lib目录 - 中文在output显示异常(不是乱码),需要增加tomcat启动配置
-Dfile.encoding=UTF-8
- 在web下写一个html文件,写一个表单,发送post请求,server端web.xml配置servlet和servlet-mapping,在
HttpServlet
子类中重写doPost
方法,这个方法就用来处理web.xml中配置的mapping请求路径。web.xml是web工程的入口配置文件(注册Servlet、Listener、Filter,Spring有注解方式可以代替配置文件)
pom需要添加javax.servlet-api
依赖:
<!--javaee servlet api-->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
配置web.xml:
<servlet>
<servlet-name>addServlet</servlet-name>
<servlet-class>org.example.servlet.AddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addServlet</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
Servlet继承关系
抽象类HttpServLet,继承抽象类GenericServlet,实现接口Servlet
接口Servlet中有三个核心方法(init(),service(),destroy()),请求进来后会调用service()方法,里面会根据调用请求方法分别调用doXxx()方法,在HttpServlet里有对doXxx的默认实现,返回都是405。
Servlet生命周期
在第一次调用时,容器通过反射创建对应的Servlet,调用init()方法,调用service()方法响应,之后的调用都会调用service()方法,在容器关闭时,调用destroy()方法。
因此,Servlet实例tomcat只会创建一个,所有请求都是这个实例去响应。只有第一次请求时,才会实例化,初始化,好处是提高系统启动速度,坏处是第一次调用较耗时。
Servlet初始化时机:可以通过<load-on-startup>
设置Servlet的启动顺序(随着tomcat容器的启动而启动),数字越小,优先级越高,最小值0。
Servlet是单例的、线程不安全的:单例指所有请求都由一个Servlet对象处理。
Http协议
Http协议称为超文本传输协议,是无状态的,Http包含请求和响应
- 请求:包含请求行、请求消息头、请求体。
- 请求行包含:请求方式,请求的url,请求的协议(Http1.1)
- 请求消息头:包含了很多客户端需要告诉服务器的信息,比如浏览器版本号、版本、能接受的媒体类型、发送内容的长度等
- 请求体:get方式没有请求体(有queryString),post方式有请求体(form data),json格式有请求体(request payload)
- 响应:包含响应行,响应头,响应体
- 响应行包含:协议,响应状态码(200),响应状态(OK)
- 响应头:包含了服务器的信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)
- 响应体:响应的实际内容(比如html文本内容)
200:正常响应
404:找不到资源
405:请求方式不支持
500:服务器内部错误
会话跟踪技术
客户端第一次发送请求给服务器,服务器获取session,获取不到创建新的,将session响应给客户端,下次客户端给服务器发请求时,会把sessionId带给服务器,那么服务器可以判断这一次请求和上一次请求时同一个客户端
常用api:
- request.getSession(),获取当前会话,没有则创建一个新的会话
- request.getSession(true),与不带参数相同
- request.getSession(false),获取当前会话,没有则返回null
- session.getId(),获取sessionId
- session.isNew(),判断当前会话是不是新的
- session.getMaxInactiveInterval(),session的非激活时间间隔时长,默认1800秒
- session.invalidate(),让会话立即失效
- ...
session保存作用域:向session中setAttribute(k,v),在别的Servlet中可以在同一个会话(同一个浏览器访问)中获取到该数据
其他作用域:
- request作用域:单个请求内有效
- application作用域:整个应用内有效,通过获取ServletContext获取到Application作用域
服务器转发和重定向
- 服务器转发是内部转发,客户端无感,客户端发送一次
- 客户端重定向:服务器响应302,客户端重写发送请求,客户端发送两次,请求url会变
Thymeleaf
视图模板技术,将Servlet里获取到的数据渲染到html上,并将html返回给客户端。这样在前端就可以显示html页面了(直接访问的话是静态页面,数据都是固定的,可以使用thymeleaf语法进行渲染,并且不让客户端直接访问静态页面)
需要用到javax里面的dom技术解析xml文件,xml文件中配置thymeleaf配置前缀后缀的配置
Servlet优化(DispatcherServlet思想)
页面上每一个请求,对应一个Servlet处理,该结构过于简单,Servlet太多了。
优化思想1:把一系列请求都对应一个Servlet,通过一个请求参数确定不同的操作,使用switch-case
分别调用不同方法(这是的方法都是原来的Servlet,参数都是一样的)。
优化思想2:在Servlet中处理的时候根据这个参数利用反射调用不同的方法(不用switch-case
),用多个方法替代多个Servlet,用参数区分调那个方法,要求参数值与方法名相同,才能通过反射找到(或者写Map对应关系)。
然而,在每个方法内,都会有转发、重定向不同页面、获取request作用域的参数等操作,这些操作过程都是相同的。同时,当有很多业务时,每个Serv都要利用反射调用不同方法,这样的处理方式有更多,而且处理过程类似。
优化思想2:考虑一个业务为一个Controller(也就是上面的一个Servlet,后面优化后不在是Servlet),对于不同业务的不同url,都使用同一个Servlet处理(DispatcherServlet),根据url的地址分别让不同的Controller处理,该映射关系可以通过一个xml文件配置,如<bean id="hello" class="HelloController">
(Spring IOC思想),首先将该配置文件处理为Map<String, Class>
,在这个Servlet内,通过url在Map中查找指定的class,并通过反射创建该对象。
同时,将原来所以Servlet中的利用反射调用方法的逻辑放入DispatcherServlet处理,原来Servlet方法中的转发、重定向、获取request参数,都在DispatcherServlet中利用反射获取、调用(Controller功能主要有三个:获取参数、业务处理、视图处理,将获取参数和视图处理放在DispatcherServlet中)。
其中,request作用域的参数需要根据原来Servlet方法中的参数名称获取,可以在File | Settings | Build, Execution, Deployment | Compiler | Java Compiler
增加命令行参数-parameters
,就可以通过反射获取到参数名称了,否则编译的都是arg0,arg1...
Servlet api
Servlet生命周期:实例化(无参构造)、初始化(init方法)、服务(service方法)、销毁(destroy方法)
init有两个,一个是带参数的(ServletConfig),一个是不带参数的,带参数的会调用不带参数的,因此,不带参数的是留给开发人员重写做一些初始化操作的。
ServletCongfig里面的参数可以在web.xml配置Servlet时通过<init-param>
配置,并在代码中获取。也可以在@WebServlet
注解中配置(单个Servlet的初始化参数)
也可以在web.xml中配置上下文参数<context-param>
,这些值可以在代码获取的上下文中获取(应用级别的初始化参数,需要先获取ServletContext)
获取post请求体的数据需要使用req.getInputStream()
获取输入流
MVC
Model(模型):pojo(Plain Ordinary Java Object)、vo(Value Object),dao(Data Access Object),包括保存数据和处理数据,像实体类就是保存数据的,DAO类和Service类都是处理数据的
View(视图层):用于做数据展示以及和用户交互的一个界面,比如html/jsp页面
Controller(控制层):用于接收用户的请求并响应,具体的业务需要借助模型层的模型完成,比如Service和DAO
控制反转(IOC):一个实现的例子,多层之间的对象耦合通过配置xml文件实现,在程序启动时,将依赖的属性注入。自定义容器实现MVC解耦(根据xml文件,实现Controller层、Service层、DAO层的IOC、DI)
DAO中都是单精度的方法,一个Service方法会调用多个单精度方法,Controller中就可以调Service层的方法,而不是调用多个DAO方法。因为,Controller直接调用业务方法,业务有多复杂都封装到Service层
Filter
也属于Servlet规范,需要实现Filter接口,实现其中的三个方法(init,doFilter,destroy),配置@WebFilter("/filter/url")
(也可以通过配置文件,类似Servlet的xml配置)。放行是执行filterChain.doFilter(req, res)
如果使用注解形式配置,按照全类名的先后顺序,如果是xml配置文件形式,按照配置先后顺序执行
应用:
- 可以在编码过滤器中设置编码,后续DispatcherServlet就不用考虑编码了
- 做事务,开启事务后放行,放行后提交事务
- 难点是所有DAO都要用同一个connection
事务
事务管理不能以DAO单精度操作管理,而是应该以业务层的方法为单位
事务实现:使用ThreadLocal在Utils中处理连接,在TransactionManager中做事务管理,利用TransactionManager在Filter中对单个要处理的业务做事务管理(开启事务、提交事务、回滚事务),在底层的DAO里面也使用Utils(ThreadLocal)获取连接,因为这里Filter - DispatcherServlet - Controller - Service - DAO都是同一个线程的调用,所以获取到的是同一个连接。
DispatcherServlet里面init方法创建ClassPathXmlApplicationContext对象,该对象解析xml文件向beanFactory注入Controller、Service、DAO。DispatcherServlet通过反射解析url,根据url去beanFactory里面获取到Controller,然后根据url中的参数调用Controller中的指定方法(url中的参数配置与Controller中的方法是一样的)
Listener
主要有8个:
监听各自级别对象的创建和销毁的过程:ServletContext对象、HttpSession对象、Servlet对象,两个方法,xxxInitialized(),xxxDestroyed()
- ServletContextListener
- HttpSessionListener
- ServletRequestListener
监听各自保存作用域的改动的过程:ServletContext、HttpSession、Servlet,三个方法,添加、删除、替换
- ServletContextAttributeListener
- HttpSessionAttributeListener
- ServletContextAttributeListener
监听某个对象在session域中的创建和移除:
- HttpSessionBindingListener
监听某个对象在session域中的序列化和反序列化:tomcat重新部署的时候会将内存中的对象序列化,然后再反序列化,保存原来的数据
- HttpSessionActivationListener
应用:当上下文创建的时候希望ioc已经准备好了,而不是在DispatcherServlet的init方法里面初始化,使用上下文监听器,创建ioc容器,在DispatcherServlet的init中根据属性获取到ioc容器
Cookie
浏览器保存连接数据的地方,比如sessionId,服务器创建Cookie,添加到响应中,浏览器就会保存该Cookie,下次访问服务器时会携带
api:
- 设置有效期
- 设置Domain、Path
应用:
- 浏览器记住用户名和密码
- 免登陆
Kaptcha:验证码
正则表达式
vue
简单使用:
window.onload=function(){
var vue = new Vue({
el: "#div0",
data: {
k: "value"
},
methods: {//这里面要是引用vue的数据需要使用vue.k,而不是this.k
myFunc: function(){
//your function
}
}
watch: { //监听属性变化
k: function(newK){
this.k=newK;
}
},
//生命周期
beforeCreate: function(){}, # 对象创建之前
created: function(){}, # 创建之后
beforeMount: function(){}, # 数据装载之前
mounted: function(){}, # 数据装载之后
beforeUpdate: function(){}, # 数据更新之前
updated: function(){}, # 数据更新之后
});
}
{{}},相当于.innerText
v-bind:value="k" 或者:value="k",绑定属性
v-model:value="k"或者v-model="k",双向绑定
v-model.trim,去除输入的首位空格
v-if="num%2==0",v-else:"num%2==0",两个元素直接不能有其他元素
v-show="num%2==0",是通过修改样式display:none控制是否显示
v-for="a in as",{{a.xxx}},表示迭代
v-on:click="myFunc",或者@cliek,表示绑定点击事件
Axios
是ajax的一个框架,简化ajax操作。
axios({
method:"POST",
url:"/xxx",
params: { //发送普通参数,可以使用data发送json数据
k1: v1
}
}).then(function(value){ //成功时的回调,value.data可以拿到服务器响应数据,详细可调试前端输出
//when success
}).catch(function(reason){ //reason.response.data可以获取到异常信息
//when fail
})
# js中string与json格式转换
JSON.stringify(Object),Object -> String
JSON.parse(String),String -> Object
# 前端
alert(typeof xxx),查看xxx的类型
console.log(xxx),向前端的consul打印日志
项目
QQZone项目
书城项目
本文来自博客园,作者:Bingmous,转载请注明原文链接:https://www.cnblogs.com/bingmous/p/16391831.html