IDEA新建module的时候没有javaee的选项,这时候可以先选择普通的java项目进行创建。
图片中的a就是新建的java module。
右键a文件夹,选择Add Framework Support。
然后选中Web Application,点击右下角的ok即可。
a文件夹下出现带小蓝的web就说明成功了。
关联相关包
将jar包拷到libs文件夹下,右键add as library
tomcat 学习中。tomcat布置好后。再导入jdbc的包时。需要如下操作一下。不然使用jdbc包会奔溃。
设置编码
tomcat8之前,设置编码:
1)get请求方式:
//get方式目前不需要设置编码(基于tomcat8)
//如果是get请求发送的中文数据,转码稍微有点麻烦(tomcat8之前)
String fname = request.getParameter(“fname”);
//1.将字符串打散成字节数组
byte[] bytes = fname.getBytes(“ISO-8859-1”);
//2.将字节数组按照设定的编码重新组装成字符串
fname = new String(bytes,“UTF-8”);
2)post请求方式:
request.setCharacterEncoding(“UTF-8”);
tomcat8开始,设置编码,只需要针对post方式
request.setCharacterEncoding(“UTF-8”);
注意:
需要注意的是,设置编码(post)这一句代码必须在所有的获取参数动作之前
Servlet的继承关系 - 重点查看的是服务方法(service())
继承关系
javax.servlet.Servlet接口
javax.servlet.GenericServlet抽象类
javax.servlet.http.HttpServlet抽象子类
相关方法
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) - 不是抽象的
1. String method = req.getMethod(); 获取请求的方式
2. 各种if判断,根据请求方式不同,决定去调用不同的do方法
if (method.equals(“GET”)) {
this.doGet(req,resp);
} else if (method.equals(“HEAD”)) {
this.doHead(req, resp);
} else if (method.equals(“POST”)) {
this.doPost(req, resp);
} else if (method.equals(“PUT”)) {
3. 在HttpServlet这个抽象类中,do方法都差不多:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString(“http.method_get_not_supported”);
if (protocol.endsWith(“1.1”)) {
resp.sendError(405, msg);
} else {
resp.sendError(400, msg);
}
}
3.小结:
Servlet的生命周期
1) 生命周期:从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init(),service(),destroy()
2) 默认情况下:
第一次接收请求时,这个Servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service())
从第二次请求开始,每一次都是服务
当容器关闭时,其中的所有的servlet实例会被销毁,调用销毁方法
3) 通过案例我们发现:
- Servlet实例tomcat只会创建一个,所有的请求都是这个实例去响应。
- 默认情况下,第一次请求时,tomcat才会去实例化,初始化,然后再服务.这样的好处是什么? 提高系统的启动速度 。 这样的缺点是什么? 第一次请求时,耗时较长。
- 因此得出结论: 如果需要提高系统的启动速度,当前默认情况就是这样。如果需要提高响应速度,我们应该设置Servlet的初始化时机。
4) Servlet的初始化时机:
- 默认是第一次接收请求时,实例化,初始化
- 我们可以通过来设置servlet启动的先后顺序,数字越小,启动越靠前,最小值0
5) Servlet在容器中是:单例的、线程不安全的
- 单例:所有的请求都是同一个实例去响应
- 线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化
- 我们已经知道了servlet是线程不安全的,给我们的启发是: 尽量的不要在servlet中定义成员变量。如果不得不定义成员变量,那么不要去:①不要去修改成员变量的值 ②不要去根据成员变量的值做一些逻辑判断
Http协议
1) Http 称之为 超文本传输协议
2) Http是无状态的
3) Http请求响应包含两个部分:请求和响应
会话
1) Http是无状态的
- HTTP 无状态 :服务器无法判断这两次请求是同一个客户端发过来的,还是不同的客户端发过来的
- 无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一个用户的,那么就会导致混乱
- 通过会话跟踪技术来解决无状态的问题。
2) 会话跟踪技术
一个浏览器会是一个session,同一个浏览器的不同页面是同一个session。不同浏览器是不同session.
- 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端
- 下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到了,那么服务器就判断这一次请求和上次某次请求是同一个客户端,从而能够区分开客户端
- 常用的API:
request.getSession() -> 获取当前的会话,没有则创建一个新的会话
request.getSession(true) -> 效果和不带参数相同
request.getSession(false) -> 获取当前会话,没有则返回null,不会创建新的
session.getId() -> 获取sessionID
session.isNew() -> 判断当前session是否是新的
session.getMaxInactiveInterval() -> session的非激活间隔时长,默认1800秒
session.setMaxInactiveInterval()
session.invalidate() -> 强制性让会话立即失效
....
3) session保存作用域
服务器内部转发以及客户端重定向
1) 服务器内部转发 : request.getRequestDispatcher(“…”).forward(request,response);
Thymeleaf - 视图模板技术
1) 添加thymeleaf的jar包
2) 新建一个Servlet类ViewBaseServlet
3) 在web.xml文件中添加配置
- 配置前缀 view-prefix
- 配置后缀 view-suffix
4) 使得我们的Servlet继承ViewBaseServlet
5) 根据逻辑视图名称 得到 物理视图名称
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
super.processTemplate(“index”,request,response);
6) 使用thymeleaf的标签
th:if , th:unless , th:each , th:text
// 200 : 正常响应
// 404 : 找不到资源
// 405 : 请求方式不支持
// 500 : 服务器内部错误
存在的html用http://localhost:8080/pro08/add2.html访问,不存在的html用http://localhost:8080/pro08/add2访问(结尾不带.html),这样可进行调试
添加lib,记得在file-project Structure-module中添加关联,和problem点fix
alt+enter后多了这一行
将这一行改为,改完后,敲代码就有提示了
,WEB也是蓝色的,
mudule文件夹有蓝色的方框代表以及成功加入项目了。
添加Artifacts
review:
post提交方式下的设置编码,防止中文乱码
request.setCharacterEncoding(“utf-8”);
get提交方式,tomcat8开始,编码不需要设置
tomcat8之前,get方式设置比较麻烦:
String fname = request.getParameter(“fname”);
byte[] bytes = fname.getBytes(“iso-8859-1”);
fname = new String(bytes,“UTF-8”);
Servlet继承关系以及生命周期
1) Servlet接口 : init() , service() , destroy()
GenericServlet抽象子类: abstract service();
HttpServlet抽象子类:实现了service方法,在service方法内部通过request.getMethod()来判断请求的方式,
然后根据请求的方式去调用内部的do方法。每一个do方法进行了简单实现,主要是如果请求方式不符合,则报405错误。
目的是让我们的Servlet子类去重写对应的方法(如果重写的不对,则使用父类的405错误实现)
2) 生命周期:实例化、初始化、服务、销毁
- Tomcat负责维护Servlet实例的生命周期
- 每个Servlet在Tomcat容器中只有一个实例,它是线程不安全的
- Servlet的启动时机:
- Servlet3.0开始支持注解: @WebServlet
HTTP协议:
1) 由 Request 和 Response 两部分组成
2) 请求包含了三部分:请求行、请求消息头、请求主体: 普通的get方式请求-query string;post方式- form data ; json格式 - request payload
3) 响应包含了三部分:响应行、响应消息头、响应主体
HttpSession
1) HttpSession :表示 会话
2) 为什么需要HttpSession , 原因是因为 Http协议是无状态的
3) Session保存作用域 :一次会话范围都有效 ; void session.setAttribute(k,v) ,Object session.getAttribute(k)
4) 其他的API: session.getId() , session.isNew() , session.getCreationTime() , session.invalidate() 等等
服务器端转发和客户端重定向
thymeleaf的部分标签
1) 使用步骤: 添加jar , 新建ViewBaseServlet(有两个方法) , 配置两个 : view-prefix , view-suffix
2) 部分标签: th:if , th:unless , th:each , th:text
今日内容:
保存作用域
原始情况下,保存作用域我们可以认为有四个: page(页面级别,现在几乎不用) , request(一次请求响应范围) , session(一次会话范围) , application(整个应用程序范围)
1) request:一次请求响应范围
2) session:一次会话范围有效
3) application: 一次应用程序范围有效
路径问题
1) 相对路径
2) 绝对路径
实现库存系统的功能
<beans>
<bean id="fruit" class="com.atguigu.fruit.controllers.FruitController"/>
beans>
build完成后,out文件夹会多一个production文件夹
完成后会多一个artifacts文件夹
此次是需要使用Integer类型的参数,但是直接获取到的是String类型,所以需要进行类型判断,然后转换成Integer
//从请求中获取参数值
String parameterValue = request.getParameter(parameterName);
String typeName = parameter.getType().getName();
Object parameterObj = parameterValue ;
if(parameterObj!=null) {
if ("java.lang.Integer".equals(typeName)) {
parameterObj = Integer.parseInt(parameterValue);
}
}
parameterValues[i] = parameterObj ;
review:
学习Servlet中的ServletContext和
什么是业务层
Model1和Model2
MVC : Model(模型)、View(视图)、Controller(控制器)
视图层:用于做数据展示以及和用户交互的一个界面
控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型组件来完成
模型层:模型分为很多种:有比较简单的pojo/vo(value object),有业务模型组件,有数据访问层组件
区分业务对象和数据访问对象:
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. …
在库存系统中添加业务层组件
IOC
过滤器Filter
事务管理
TransActionManager、ThreadLocal、OpenSessionInViewFilter
review:
Servlet生命周期中的初始化方法: init() , init(config)
public void init(ServletConfig config) throws ServletException {
this.config = config ;
init();
}
因此,如果我们需要在初始化时执行一些自定义的操作,那么我们可以重写无参的init方法。
我们可以通过getConfig()获取ServletConfig对象
可以通过config.getInitParameter()获取初始化参数
通过ServletContext获取配置的上下文参数
MVC : V:view 视图 ; C:Controller 控制器 ; M:Model 模型
模型有很多种类:数据访问模型(DAO);业务逻辑模型(BO);值对象模型(POJO);数据传输对象(DTO)
IOC
IOC - 控制反转 / DI - 依赖注入
控制反转:
依赖注入:
今日内容:
1. 过滤器Filter
2. 事务管理(TransactionManager、ThreadLocal、OpenSessionInViewFilter)
3. 监听器(Listener , ContextLoaderListener)
事务管理
监听器
ServletContextListener - 监听ServletContext对象的创建和销毁的过程
HttpSessionListener - 监听HttpSession对象的创建和销毁的过程
ServletRequestListener - 监听ServletRequest对象的创建和销毁的过程
ServletContextAttributeListener - 监听ServletContext的保存作用域的改动(add,remove,replace)
HttpSessionAttributeListener - 监听HttpSession的保存作用域的改动(add,remove,replace)
ServletRequestAttributeListener - 监听ServletRequest的保存作用域的改动(add,remove,replace)
HttpSessionBindingListener - 监听某个对象在Session域中的创建与移除
HttpSessionActivationListener - 监听某个对象在Session域中的序列化和反序列化
ServletContextListener的应用 - ContextLoaderListener
Cookie
Kaptcha
JS - Exp
1)正则表达式的使用三步骤:
1. 定义正则表达式对象
正则表达式定义有两个方式:
1) 对象形式
var reg = new RegExp(“abc”)
2) 直接量形式
var reg = /abc/;
3) 匹配模式:
- g 全局匹配
- i 忽略大小写匹配
- m 多行匹配
- gim这三个可以组合使用,不区分先后顺序
例如: var reg = /abc/gim , var reg = new RegExp(“abc”,“gim”);
2. 定义待校验的字符串
3. 校验
2)元字符
. , \w , \W , \s , \S , \d , \D , \b , ^ , $
3)[]表示集合
[abc] 表示 a或者b或者c
[^abc] 表示取反,只要不是a不是b不是c就匹配
[a-c] 表示a到c这个范围匹配
![在这里插入图片描述](https://img-blog.csdnimg.cn/7341e6bbd53c4267b393f34e9cbafb08.png)
# 网页右键检查,network![在这里插入图片描述](https://img-blog.csdnimg.cn/91d0d4b30475452b95438f8650dd0e2d.png)
1. 回顾:
Ajax : 异步的JavaScript and XML
目的: 用来发送异步的请求,然后当服务器给我响应的时候再进行回调操作
好处: 提高用户体验;局部刷新:降低服务器负担、减轻浏览器压力、减轻网络带宽压力
开发步骤:
1) 创建XMLHttpRequest
2) 调用open进行设置:"GET" , URL , true
3) 绑定状态改变时执行的回调函数 - onreadystatechange
4) 发送请求 - send()
5) 编写回调函数,在回调函数中,我们只对XMLHttpRequest的readystate为4的时候感兴趣
我们只对XMLHttpRequest的status为200的时候感兴趣
0: (Uninitialized) the send( ) method has not yet been invoked.
1: (Loading) the send( ) method has been invoked, request in progress.
2: (Loaded) the send( ) method has completed, entire response received.
3: (Interactive) the response is being parsed.
4: (Completed) the response has been parsed, is ready for harvesting.
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
今天内容:
Vue
Axios
Axios是Ajax的一个框架,简化Ajax操作
Axios执行Ajax操作的步骤:
2-1. 客户端向服务器端异步发送普通参数值
基本格式: axios().then().catch()
示例:
axios({
method:“POST”,
url:“…”,
params:{
uname:“lina”,
pwd:“ok”
}
})
.then(function(value){}) //成功响应时执行的回调 value.data可以获取到服务器响应内容
.catch(function(reason){}); //有异常时执行的回调 reason.response.data可以获取到响应的内容
reason.message / reason.stack 可以查看错误的信息
2-2. 客户端向服务器发送JSON格式的数据
客户端中params需要修改成: data:
服务器获取参数值不再是 request.getParameter()…
而是:
StringBuffer stringBuffer = new StringBuffer(“”);
BufferedReader bufferedReader = request.getReader();
String str = null ;
while((str=bufferedReader.readLine())!=null){
stringBuffer.append(str);
}
str = stringBuffer.toString() ;
我们会发现 str的内容如下:
{“uname”:“lina”,“pwd”:“ok”}