零.前置知识
1.tomcat—服务器容器
tomcat就是一个服务器容器,通常说的将项目部署到服务器,就是将项目部署到tomcat中(将项目放到tomcat容器中)。
浏览器向服务器发送一个HTTP请求,请求访问demo09.html页面,(容器里面是有这个资源的,因为代码就在项目里写着,项目已经放到容器里了),服务器响应资源,给浏览器返回字符串<html><from>…那些。浏览器解析成网页,给用户展示出来。
2.IDEA创建一个web项目
1.先建立一个普通的Java工程(或者模块)
2.右击工程或者模块点击:
3.勾上Web Application,点击OK
4.导入依赖
点击工程结构,里面有这个工程下的模块
将依赖加进去:
再点击应用,点击OK
5.注意先有的Artifacts,添加jar后需要在工程结构下的problems将jar add到Artifacts中,点一下就行啦
7.配置tomcat,点击Edit Configurations
点击apply,然后点Server
点击apply,点击OK,tomcat部署成功,点击小绿箭头就可以运行了。
3.Servlet服务器端的小组件
可以看到:Servlet就是服务器端的一个小组件。
Sevlet是服务器端的应用程序
AddServlet完成的功能
1.获取用户(客户端)发给我的数据。为什么要获取这个数据?
2.调用DAO中的方法完成功能,比如完成添加功能。(一个Servlet对应一个业务功能)。
3.在控制台打印添加成功。
配置一个Servlet的具体流程如下:
- 客户端给服务器发HTTP请求(将这个请求封装成Http request对象,里面封装的是信息,可以得到发送的信息,如何得到?),客户端响应<html字符串给浏览器,浏览器解析成页面
- 用户在浏览器输入表单点击添加后,又向服务器发送一个请求。action=“add”。请求的就是Servlet为add的组件,浏览器并把数据带给服务器。服务器里面有个组件叫做add,add就是一个java类,AddServlet是服务器端的应用程序,add和AddServlet是如何对应上的?
- add组件下还有一个DAO组件,是用来操作数据库的。
为什么要获取请求的信息?
因为在添加功能时,获取到了用户输入的信息,将这些信息封装到对象中(对象对应着一条一条的记录)。再调用DAO层的方法,将对象都追加到list中,就添加到数据库中了。
如何获取请求的信息?
req.getParameter(“fname”); "fname"和<form标签中的name="fname"相对应,否则获取不到。
图解:
add和AddServlet是如何对应上的?
1.用户给服务器发请求。action=add
2.服务器tomcat中,web.xml中找到url-pattern=/add。(在xml文件中要配置)
3.找到url-pattern=/add上一行servlet-name=AddServlet
4.找到和sevlet-mapping中servlet-name一致的servlet
5.找到sevlet中servlet-calss—>找到了com.atguigu.servlets.Addservlet。这是一个Java类,写的是全类名
用户发送的是post请求(method=post),因此tomcat会执行AddServlet中的doPost方法
配置图解:
Servlet3.0新增了注解,在AddServlet类上加注解:
@WebServlet(“/add”) 就可以通过action=add 直接找到AddServlet类(Servlet组件)
就不用web.xml文件了,删掉都可以~
整体架构:
代码:
Servlet:AddServlet:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post方式下,设置编码,防止中文乱码
//需要注意的是,设置编码这一句代码必须在所有的获取参数之前
//get方式目前不需要设置编码(基于tomcat8)
//(tomcat8之前)如果是get请求发送的中文数据,转码稍微有些麻烦
req.setCharacterEncoding("UTF-8");
//通过请求把数据带给服务器 通过request对象获取的
String fname = req.getParameter("fname");
//通过Http请求得到的信息只能是字符串,可以强转
String priceStr = req.getParameter("price");
Integer price = Integer.parseInt(priceStr);
String fcountStr = req.getParameter("fcount");
Integer fcount = Integer.parseInt(fcountStr);
String remark = req.getParameter("remark");
FruitDAO fruitDAO=new FruitDAOImpl();
boolean flag = fruitDAO.addFruit(new Fruit(0, fname, price, fcount, remark));
System.out.println(flag?"添加成功":"添加失败");
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>AddServlet</servlet-name>
<servlet-class>com.atguigu.servlets.AddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AddServlet</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
</web-app>
add.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="add" method="post">
名称:<input type="text" name="fname"><br>
价格:<input type="text" name="price"><br>
库存:<input type="text" name="fcount"><br>
备注:<input type="text" name="remark"><br>
<input type="submit" value="添加">
</form>
</body>
</html>
一.设置编码
tomcat8之后使用get方式不用设置编码,使用post方式如下设置编码,要放在doPost()方法的首行
req.setCharacterEncoding("UTF-8");
tomcat8之前get方式较麻烦,post和上述方式一样
String fname=req.getParameter("fname");
//先用原始的方式打散,打散成字节流
byte[] bytes=fname.getBytes("iso-8859-1");
//再使用utf-8的编码格式组合
fname=new String(bytes,"UTF-8");
二.Servlet的继承关系
1.Servlet接口:init() service() destory()
------GenericServlet抽象子类:实现了init() destory() 抽象方法service()
------------ HttpServlet抽象子类:实现了service()方法,在方法内部通过了request.getMethod()来判断请求的方式,然后根据请求方式调用内部的do方法。每一个do方法进行了简单实现,主要是请求方式不符合,则报405错误。目的是让我们的Servlet子类去重谢对应的方法(如果重写的不对,则使用父类的405错误实现)
目前遇到的状态码:
200:正常响应。
404:找不到资源。
405:请求方式不支持。比如,表单发送请求method=post,Servlet方法中必须重写doPost。没有重写(重写错)默认调用的是父类的service方法,就报405。
500:服务器内部错误。比如没连接上数据库,空指针异常,找不到类等等
三.Servlet的生命周期
实例化、服务、销毁
1.tomcat负责维护Servlet的生命周期
2.每个Servlet在tomcat容器中只有一个实例,它是线程不安全的
3.Servlet的启动时机:<load-on-start-up>,数字越小,启动越早,最小值是0,设置为1时,是随着tomcat启动的。
<servlet>
<servlet-name>Demo02Servlet</servlet-name>
<servlet-class>com.aiguigu.servlets.Demo02Servlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Demo02Servlet</servlet-name>
<url-pattern>/demo02</url-pattern>
</servlet-mapping>
四.Http协议
由Request和Response组成
1.请求包含了三部分:请求行、请求消息头、请求主体
2.响应包含了三部分:相应行、响应消息行、相应主体
五.会话Session HttpSession
HttpSession表示一次会话:
**为什么需要会话?**通过会话跟踪技术解决Http无状态问题
因为Http协议是无状态的,默认情况下,服务器无法区分两次请求是否来源于同一个客户端。第一次创建一个唯一的SessionID(通过cookie)的方式交给客户端,下一次客户端发请求的适合会把这个ID带过来,服务器就知道是谁了。
Session保存作用域:一次会话范围都有效
常用的API:
六.服务器内部转发以及客户端重定向
1.服务器内部转发:
2.客户端重定向:
七.thymeleaf视图模板技术
简单来说就是把数据库中的数据渲染在页面上:
步骤:
1.添加thymeleaf的jar
2.新建一个Servlet类ViewBaseServlet。(里面有两个方法)固定的,以后会被框架替代,先不管里面是什么了
3.在web.xml文件中添加配置:配置前缀view-prefix,配置后缀suffix
4.使我们的Servlet继承ViewBaseServlet
5.根据逻辑视图名称 得到 物理视图名称
6.使用thymeleaf标签
th:if
th:unless
th:each
th:text
整体架构:
web.xml中配置thymeleaf的参数
<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>
IndexServlet中:
将得到的list放在session作用域中,后续用key取。
并得到真实的视图名称:
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
FruitDAO fruitDAO = new FruitDAOImpl();
List<Fruit> fruitList = fruitDAO.getFruitList();
//保存到session作用域
HttpSession session = req.getSession();
//向当前的session作用域保存一个数据
session.setAttribute("fruitList",fruitList);
//处理模板:视图名称index
//那么thymeleaf会将这个 逻辑视图名称 对应到物理视图名称上去
//逻辑视图名称:index
//物理视图名称:view-prefix + 逻辑视图名称 + view-suffix
//所以 真实的视图名称是:/index.html 所以这是最终跳转的页面 就是web下的index.html
super.processTemplate("index",req,resp);
}
}
index.html中:
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div id="div_container">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<table id="tbl_fruit">
<tr>
<th class="w20">名称</th>
<th class="w20">单价</th>
<th class="w20">库存</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 th:text="${fruit.fname}">苹果</td>
<td th:text="${fruit.price}">5</td>
<td th:text="${fruit.fcount}">20</td>
<td><img src="imgs/del.jpg" class="delImg"/></td>
</tr>
</table>
</div>
</div>
</body>
</html>
大概解释一下:这块应该不用很懂。。。vue有渲染的技术
八.保存作用域
原始情况下,有四个:page(页面级别,已经不用了,除非用的是jsp),request(请求级别,一次请求响应范围),session(一次会话范围),application(整个应用程序范围)
1.request 一次请求响应范围有效
两个Servlet之间使用客户端重定向的方式:第二次获取不到,因为不是一次响应
两个Servlet之间使用服务器内部转发的方式:第二次能获取到,属于一次响应
2.session 一次会话范围有效
是一次会话范围,不管是客户端重定向还是服务器内部转发的方式,都能获取到,因为是一次会话范围,只要session没有失效。
c1访问组件2是能获取到的。
c2直接访问组件2是获取不到的,null.
3.application 一次应用程序有效
应用程序级别,只要有一个客户端给里面保存了,剩下的所有客户端也能访问到。
总结了一天~点个赞趴~代码放的不全,需要哪块的工具包或者jar请留言~