JavaWeb——Makedown笔记
JavaWeb
JavaWeb笔记
- JavaWeb
- 1.Servlet技术
- 2.ServletConfig类
- 3.ServletContext类
- 4.Http协议
- 5.HttpServletRequest类
- 6.HttpServletResponse类
- 7.书城第二阶段————用户注册和登录
- 8.JSP
- 9.文件的上传和下载
- 10.会话
- 11.Thymeleaf 视图模版技术
- 12.review复习
- 13.Cookie
- 14.Maven
- #
- #
- 15.MyBatis
- 16.Filter过滤器
- 17.Listener监听器
- 18.AJAX
1.Servlet技术
1.什么是Servlet
- Servlet是JavaEE规范之一,规范就是接口
- Servlet就是JavaWeb三大组件之一。
- Servlet是运行在服务器上的一个Java程序,他可以接受客户端发来的请求,并响应给客户端
2.手动实现Servlet程序
- 编写一个类实现Servlet接口
- 实现service方法,处理请求,并响应数据
- 到web.xml中配置servlet程序的访问地址映射
web.xml配置
<!-- servlet标签被Tomcat配置servlet程序 -->
<servlet>
<!-- servlet-name给程序起一个别名 -->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet-class是程序的全类名 -->
<servlet-class>com.atguigudb.servlet.HelloServlet</servlet-class>
</servlet>
<!-- servlet-mapping标签给servlet程序配置访问地址 -->
<servlet-mapping>
<!-- servlet-name标签的作用是告诉服务器,我当前配置的地址给那个Servlet程序使用 -->
<servlet-name>HelloServlet</servlet-name>
<!-- URL-pattern标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为http://ip:port/工程路径
/hello http://ip:poot/工程路径/hello
-->
<url-pattern>/hello</url-pattern><!—自定义路径 —>
</servlet-mapping>
常见的错误:
1、url-pattern中配置的路径没有一斜杠打头:
2、xml配置别名不一致
3.Servlet的生命周期
- 1.执行Servlet构造器方法(Servlet是一个接口),不需要执行构造器。
- 2.init初始化方法
- 第一、第二步,是在第一次访问的时候创建Servlet程序会调用
- 该程序是一个单例模式
- 3.执行service方法
- 第三部,每次都被访问了,
- 4.执行destroy销毁方法
- 第四部,在web工程停止的时候调用。
4.GET和POST请求的分发处理
public class HelloServlet implements Servlet {
/**
* servlet专门来处理请求和访问的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3 service方法");
//类型转换(因为他有getMethod()方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
//获取请求的方式
String method = httpServletRequest.getMethod();
if(method.equals("POST")) {
doPost();
} else if (method.equals("GET")) {
doGet();
}
}
private void doGet() {
System.out.println("Get请求");
}
private void doPost() {
System.out.println("Post请求");
}
}
5.通过继承HttpServlet实现Servlet程序
一般在实际项目开发中,都是使用继承HttpServlet类的方式实现Servlet程序。
- 1.编写一个类去继承HttpServlet类
- 2.根据业务需要重写doGet方法和doPost方法
- 3.到web.xml中的配置Servlet程序的访问地址
6.使用IDEA创建Servlet程序
菜单:new -> create new servlet
7.Servlet类的继承体系
Servlet -> Servlet接口,只是负责定义Servlet程序的 访问规范
|实现接口
GenericServlet -> GenericServlet类实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用,并对ServletConfig的使用做了一些方法
|继承抽象类
HttpServlet -> 抽象类实现了service方法,并实现了请求的分发处理
String method = req.getMethod();
|继承抽象类
自定义的Servlet程序
2.ServletConfig类
ServletConfig类从类名上来看,就知道是Servlet程序的配置信息类
Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用,Servlet程序模式是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象。
1.ServletConfig类的三大作用
- 1.可以获取Servlet程序的别名servlet-name的值
- 2.获取初始化参数init-param
- 3.获取ServletConfig类的对象
web.xml中的配置
<!-- servlet标签被Tomcat配置servlet程序 -->
<servlet>
<!-- servlet-name给程序起一个别名 -->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet-class是程序的全类名 -->
<servlet-class>com.atguigudb.servlet.HelloServlet01</servlet-class>
<!--init-param是初始化参数-->
<init-param>
<!--param-name是参数名-->
<param-name>username</param-name>
<!--param-value是参数值-->
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
</servlet>
3.ServletContext类
1.什么是ServletContext类?
- 1.ServletContext是一个接口,它表示Servlet上下文对象。
- 2.一个web工程,只有一个ServletContext对象实例。
- 3.ServletContext对象是一个域对象。
- 4.ServletContext是在web工程部署启动的时候创建。在Web工程停止的时候销毁。
什么是域对象?
域对象,是可以像Map一样存取数据的对象,叫域对象。
这里的域指的是存取数据的操作范围。
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
2.ServletContext类的四个作用
- 1.获取web.xml中配置的上下文参数context-param
- 2.获取当前的工程路径,格式:/工程名
- 3.获取工程部署后,在服务器硬盘上的绝对路径
- 4.像Map一样存储数据
4.Http协议
1.什么是HTTP协议
什么是协议?
协议是指,双方或多方,相互约定好,大家都需要遵守的规则,叫协议
所谓HTTP协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫HTTP协议。HTTP协议中的数据又叫报文。
2.请求的HTTP协议格式
客户端给服务器发送数据叫请求。
服务器给客户端回传数据叫响应。
请求又分为GET请求,和POST请求两种。
2.1.GET请求
- 1.请求行
- 1.请求的方式 -> get
- 2.请求的资源路径[+?+请求参数]
- 3.请求的协议和版本号 -> HTTP/1.1
- 2.请求头
key : value 组成 不同的键值对,表示不同的含义
键值对
2.2.POST请求
- 1.请求行
- 1.请求的方式 -> POST
- 2.请求的资源路径[+?+请求参数]
- 3.请求的协议和版本号 -> HTTP/1.1
- 2.请求头
key : value 组成 不同的键值对,表示不同的含义
空行
- 3.请求体 -> 就是发送给服务器的数据
2.3.常用请求头的说明
Accept:表示客户端可以接受的数据类型
Accept-Language:表示客户端可以接受的语言类型
User-Agent:表示客户端浏览器的信息
Host:表示请求时的服务器ip和端口号
2.4.那些是GET请求,那些是POST请求
-
GET请求有哪些:
-
1.form标签 method=get
-
2.a标签
-
3.link标签引入css
-
4.Script标签引入js文件
-
5.img标签引入图片
-
6.iframe引入html页面
-
7.在浏览器地址栏中输入地址后敲回车
-
POST请求有哪些:
-
8.form标签method=post
3.响应的HTTP协议格式
- 1.响应行
- 1.1.响应的协议和版本号 -> HTTP/1.1
- 1.2.响应的状态码 -> 200
- 1.3.响应状态描述符 ok
- 2.响应头
- 2.1.key:value -> 不同的响应头,有其不同含义
空行 - 3.响应体 -> 就是回传给客户端的数据
4.常见的响应码说明
状态码 | 说明 |
---|---|
200 | 表示请求成功 |
302 | 表示请求重定向 |
404 | 表示请求服务器已经收到,但是请求的数据不存在,请求地址有错误 |
500 | 表示服务器已经收到请求,但是服务器内部错误,(代码错误) |
5.MIME类型说明
MIME是HTTP协议中数据类型。
MIME的英文全称是”Multipurpose Internet Mail Extensions“多功能Internet邮件扩充服务,MIME类型是大类型/小类型,并于某一种文件的扩展名相对应。
常见的MIME类型:
文件 | MIME类型 |
---|---|
超文本标记语言文本 | .html,.htm -> text/html |
普通文本 | .txt -> text/plain |
RTF文本 | .rtf -> application/rtf |
GIF图形 | .gif -> image/gif |
JPEG图形 | .jpeg,.jpg -> image/jpeg |
au声音文件 | .au -> audio/basic |
MIDI音乐文件 | mid,.midi -> audio/mi di,audio/x-midi |
RealAudio音乐文件 | .ra,.ram -> audio/x-pn-realaudio |
MPEG文件 | .mpg,.mpeg -> video/mpeg |
AVI文件 | .avi -> video/x-msvideo |
GZIP | .gz -> application/x-gzip |
TAR文件 | .tar -> application/x-tar |
5.HttpServletRequest类
1.HttpServletRequest类有什么作用?
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的Http协议信息解析好封装到Request对象中,然后传递到service方法(doGet\doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取所有请求的信息。
2.HttpServletRequest类的常用方法
- 1.getRequestURI() -> 获取请求的资源路径
- 2.getRequestURL() -> 获取请求的统一资源定位符(绝对路径)
- 3.getRemoteHost() -> 获取客户端的ip地址
- 4.getHeader() -> 获取请求头
- 5.getParameter() -> 获取请求的参数
- 6.getParameterValues() -> 获取请求的参数(多个值的时候使用)
- 7.getMethod() -> 获取请求的方式GET或POST
- 8.setAttribute(key, value); -> 设置域数据
- 9.getAttribute(key); -> 获取域数据
- 10.getRequestDispatcher() -> 获取请求转发对象
3.如何获取请求参数
System.out.println("---doGet---");
// getParameter() -> 获取请求的参数
String username = req.getParameter("username");
// getParameterValues() -> 获取请求的参数(多个值的时候使用)
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println(username);
System.out.println(password);
for (int i = 0; i < hobbies.length; i++) {
System.out.print(hobbies[i] + ", ");
}
4.Get和Post请求的中文乱码解决:
在请求之前添加setCharacterEncoding("utf-8");
//在获取请求参数之前调用才有效
req.setCharacterEncoding("utf-8");
System.out.println("---doPost---");
// getParameter() -> 获取请求的参数
String username = req.getParameter("username");
// getParameterValues() -> 获取请求的参数(多个值的时候使用)
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println(username);
System.out.println(password);
for (int i = 0; i < hobbies.length; i++) {
System.out.print(hobbies[i] + ", ");
}
5.请求的转发(服务器内部转发)
什么是请求的转发?
请求转发是指,服务器收到请求后,从一个资源跳转到另一个服务器资源的操作叫请求转发。
- 请求转发的特点:
- 1.浏览器地址栏没有变化
- 2.他们是一次请求
- 3.他们共享Request对象
- 4.可以转发到WEB-INF目录下
- 5.是否可以访问工程以外的资源
6.base标签的作用
7.Web中的相对路径和绝对路径
在JavaWeb中,路径分为相对路径和绝对路径两种:
相对路径是:
相对路径 | 解释 |
---|---|
. | 表示当前目录 |
.. | 表示上一级目录 |
资源名 | 表示当前目录/资源名 |
绝对路径:
http://ip:port/工程路径/资源路径
8.Web中 / 斜杠的不同意义
在web中 / 斜杠是一种绝对路径。
/ 斜杠如果被浏览器解析,得到的地址是:http://ip:port/
<a href=“/“>斜杠</a>
/ 斜杠如果被服务器解析,得到的地址是:http://ip:port/工程路径
1、<url-pattern>/servlet1</url-pattern>
2、servletContext.getRealPath("/");
3、request.getRequestDispatcher("/");
请求重定向:
特殊情况:response.sendRediect(“/“); 把斜杠发送给浏览器解析。得到http://ip:port/
6.HttpServletResponse类
1.HttpServletResponse类的作用
HttpServletResponse和HttpServletRequest类一样。每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用,HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息,我们如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置。
2.两个输出流的说明
字节流
字符流
| 流 | 方法 | 说明 |
|:--|:--|:--|:--|
| 字节流 | getOutPutStream; | 常用于下载(传递二进制数据) |
| 字符流 | getWriter(); | 常用于回传字符串(常用) |
两个流同时只能使用一个。
使用了字节流,就不能再使用字符流,反之亦然,否则就会报错。
同时使用了两个响应流,就会报错
3.如何往客户端回传数据
PrintWriter writer = resp.getWriter();
writer.write("response's content!!!");
4.响应的乱码问题解决
- 1.设置服务器字符串
resp.setCharacterEncoding("utf-8");
- 2.设置浏览器字符串
//通过响应头:设置浏览器也适用 utf-8 字符集
resp.setHeader("content-Type", "text/html; charset=UTF-8");
5.请求重定向(客户端重定向)
请求重定向,是指客户端给服务器发请求。然后服务器告诉客户端,让客户端重新去新的地址访问,叫做请求重定向(可能之前的地址已经被废弃)。
第一种请求重定向的方式:
//设置响应状态吗302,表示重定向,(已搬迁)
resp.setStatus(302);
//设置响应头,说明新的地址在哪里
resp.setHeader("location", "http://localhost:8080/servlet/WEB-INF/form.html");
第二种请求重定向的方式(推荐使用):
//简写请求重定向
//直接写要请求重定向的地址
resp.sendRedirect("http://locahost:8080/servlet/index.html");
7.书城第二阶段————用户注册和登录
1.JavaEE项目的三层架构
分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。
层次 | 包名 | |
---|---|---|
web层 | com.atguigu.web/servlet/controller | |
service层 | com.atguigu.service | Service接口包 |
com.atguigu.service.impl | Service接口实现类 | |
DAO持久层 | com.atguigu.dao | DAO接口包 |
com.atguigu.dao.impl | DAO接口实现类 | |
实体bean对象 | com.atguigu.pojo/entify/domain/bean | JavaBean类 |
测试包 | com.atguigu.test/juint | |
工具类 | com.atguigu.utils |
1、先创建书城需要的数据库和表。
drop database if exists book;
create database book;
use book;
create table t_user (
#id
`id` INT primary key auto_increment,
#用户名
`username` varchar(20) not null unique ,
#密码
`password` varchar(32) not null ,
#邮箱
`email` varchar(50)
);
insert into t_user(username, password, email)
values ('admin', 'admin', 'admin@atguigu.com');
select * from t_user;
2、编写数据库表对应的JavaBean对象
public class User {
private Integer id;
private String username;
private String password;
private String email;
3、编写工具类JDBCUtils
- 3.1倒入需要的jar包
- 3.2在src源码下编写jdbc.properties属性配置文件
- 3.3编写JDBCUtils工具类
- 3.4JDBCUtils测试
4、编写BaseDao
public abstract class BaseDao {
//使用DBUtils操作数据库
private QueryRunner queryRunner = new QueryRunner();
/**
* update方法用来执行:insert、update、delete语句
* @return 如果返回-1,说明执行失败,返回其他表示影响的行数
*/
public int update(String sql, Object ... args) {
Connection connection = JDBCUtils.getConnection();
try {
return queryRunner.update(connection, sql, args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(connection);
}
return -1;
}
/**
* 查询返回一个javaBean的sql语句
* @param type 对象类型
* @param sql sql语句
* @param args sql对应的参数
* @param <T> 类型的泛型
* @return
*/
public <T> Object queryForOne(Class<T> type, String sql, Object ... args) {
Connection connection = JDBCUtils.getConnection();
try {
return queryRunner.query(connection, sql, new BeanHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(connection);
}
return null;
}
/**
* 查询返回多个javaBean的sql语句
* @param type 对象类型
* @param sql sql语句
* @param args sql对应的参数
* @param <T> 类型的泛型
* @return
*/
public <T> List<T> queryForList(Class<T> type, String sql, Object ... args) {
Connection connection = JDBCUtils.getConnection();
List<T> query = null;
try {
query = queryRunner.query(connection, sql, new BeanListHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
}
JDBCUtils.close(connection);
return query;
}
/**
* 特殊单行值的查询
* @param sql 执行的sql语句
* @param args
* @return
*/
public Object queryForSingleValue(String sql, Object ... args) {
Connection connection = null;
try {
connection = JDBCUtils.getConnection();
return queryRunner.query(connection, sql, new ScalarHandler(), args);
} catch (SQLException e) {
e.printStackTrace();
}
JDBCUtils.close(connection);
return null;
}
}
5、编写UserDAO和测试
@Test
public void queryUserByUsername() {
UserDAO userDAO = new UserDaoImpl();
if (userDAO.queryUserByUsername("admin") == null) {
System.out.println("用户名可以用✅");
} else {
System.out.println("用户名已存在❌");
}
}
@Test
public void queryUserByUsernameAndPassword() {
UserDAO userDAO = new UserDaoImpl();
if (userDAO.queryUserByUsernameAndPassword( "admin", "admin") == null) {
System.out.println("用户名和密码错误,登录失败");
} else {
System.out.println("登录成功");
}
}
@Test
public void saveUser() {
UserDAO userDAO = new UserDaoImpl();
User user = new User(1, "mazilong", "root", "290205991@qq.com");
int i = userDAO.saveUser(user);
if(i == 0) {
System.out.println("存储失败");
} else {
System.out.println("存储成功");
}
}
6、编写UserService和测试
/**
* 注册用户
* @param user
*/
public void registUser(User user);
/**
* 登录
* @param user
* @return
*/
public User Login(User user);
/**
* 检查用户名是否可用
* @param username
* @return 返回true表示用户名已存在,返回false表示用户名可用
*/
public boolean existsUsername(String username);
7、编写web层
1、实现用户注册的功能
private UserService userService = new UserServletImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
//2.验证验证码是否正确 -- 写死:abcde
if("abcde".equalsIgnoreCase(code)) {
//验证码正确
//检查用户名是否可用
if(userService.existsUsername(username)) {
//用户名已存在
System.out.println("用户名【"+ username +"】已存在");
req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp );
} else {
//用户名可用
User user = new User(null, username, password, email);
//保存到数据库
userService.registUser(user);
//跳转到注册成功页面
req.getRequestDispatcher("/pages/user/regist_success.html").forward(req, resp);
}
} else {
//不正确
//跳回注册页面
System.out.println("验证吗【"+ code +"】错误");
req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp );
}
}
2、IDEA中DeBug调试的使用
debug调试代码,首先需要两个元素:断点 + debug启动
-
1.断点,只需要在代码需要停的左边上单击,就可以添加和取消。
-
2.Debug启动Tomcat运行代码
3.用户登录功能的实现
2.项目阶段二:用户注册后登录的实现。
需求1:用户注册
需求如下:
-
1.访问注册页面
-
2.填写注册信息,提交给服务器
-
3.服务器应该保存用户
4.当用户已经存在——提示用户注册 失败,用户名一存在
8.JSP
1.什么是jsp,有什么用?
2.jsp的本质是什么
3.jsp的三种语法
4.jsp九大内置对象
5.jsp四大域对象
6.jsp中的out输出和response
7.jsp的常用标签
9.文件的上传和下载
文件的上传和下载,是非常常见的功能,很多的系统中,或者软件中都经常文件的上传和下载。
比如:qq头像,就是用来上传,邮箱中也有附件的上传和下载功能。
OA系统中审批有附件材料的上传。
1、文件的上传介绍
- 1、要有一个form标签,method=post请求
- 2、form标签的enctype属性值必须为multipart/form-data值
- 3、在form标签中使用input type=file添加上传的文件
- 4、编写服务器代码接受,处理上传的数据
encType = multipart/form-data 表示提交的数据以多段(每一个表单项一个数据段)的形式拼接,然后以二进制流的形式发送给服务器
1.1 文件上传,HTTP协议的说明
1.2 commons-fileupload.jar 常用 API 介绍说明
commons-fileupload.jar 需要依赖 commons-io.jar 这个包,所以两个包我们都要引入。
第一步,就是需要导入两个 jar 包:
- commons-fileupload-1.2.1.jar
- commons-io-1.4.jar
commons-fileupload.jar 和 commons-io.jar 包中,我们常用的类有哪些?
ServletFileUpload 类,用于解析上传的数据。
FileItem 类,表示每一个表单项。
boolean ServletFileUpload.isMultipartContent(HttpServletRequest request);
- 判断当前上传的数据格式是否是多段的格式。
public List<FileItem> parseRequest(HttpServletRequest request)
- 解析上传的数据
boolean FileItem.isFormField()
- 判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。
- true 表示普通类型的表单项
- false 表示上传的文件类型
String FileItem.getFieldName()
- 获取表单项的 name 属性值
String FileItem.getString()
- 获取当前表单项的值。
String FileItem.getName();
- 获取上传的文件名
void FileItem.write( file );
- 将上传的文件写到 参数 file 所指向抽硬盘位置 。
1.3 fileupload 类库的使用
上传文件的表单:
<form action="http://192.168.31.74:8080/09_EL_JSTL/uploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type name /> <br>
头像:<input type name > <br>
<input type value="上传">
</form>
解析上传的数据的代码:
//1、判断上传的数据是否是多端数据(只有多端数据才是文件上传的)
if(ServletFileUpload.isMultipartContent(req)) {
//创建FileItemFactory工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
//创建用于解析上传数据的工具类ServletFileUpload类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
//解析上传的数据,得到每一个表单项FileItem
List<FileItem> list = servletFileUpload.parseRequest(req);
//循环判断,每一个表单项,是普通类型,还是上传的文件
for (FileItem fileItem : list) {
if(fileItem.isFormField()) {
//普通类型的表单项
System.out.println("表单项的Name属性值:" + fileItem.getFieldName());
//参数utf-8,解决乱码问题
System.out.println("表单项的value属性值:" + fileItem.getString("utf-8"));
} else {
//上传的文件
System.out.println("表单项的Name属性值:" + fileItem.getFieldName());
System.out.println("上传的文件名:" + fileItem.getName());
fileItem.write(new File("/Users/mazilong/Desktop/"));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
2、文件下载
10.会话
10.1 HTTP是无状态的
Http无状态:服务器无法判断这两次请求是同一个客户端发过来的,还是不同的客户端发过来的。
无状态带来的现实问题:第一次请求时添加商品购物车,第二次请求是结账,如果这两次请求服务器无法识别统一客户端,导致订单错乱。
以上问题通过使用会话跟踪技术来解决无状态的问题
10.2 会话跟踪技术
客户端第一次发请求给服务器,服务器获取session,获取不到则创建一个新的session Id,然后响应给客户端。
下次客户端给服务器发请求时,会把session Id带给服务器,那么服务器就能获取到了,那么服务器就判断这一次请求和上次某次请求是否是同一次请求,从而能够区分开客户端。
常用的API:
API | 说明 |
---|---|
request.getSession() | 获取当前的会话,没有则创建一个新的会话 |
request.getSession(true) | 效果和不带参数相同 |
request.getSession(false) | 获取当前会话,没有则返回null,不会创建新的 |
session.getId() | 获取sessionId |
session.isNew() | 判断当前的session是否是新的 |
session.getMaxInactiveInterval() | session的非激活间隔时长,默认1800秒 |
session.setMaxInactiveInterval() | 设置session的非激活间隔时长 |
session.invalidate() | 强制让会话立即失效 |
session.getLastAccessedTime() | 距上一次最近的访问时间 |
session.getAttribute | 获取session的域对象 |
session.setAttribute | 设置session的域对象 |
session.removeAttribute | 清除session的域对象 |
…… |
10.3 session保存作用域
Session保存作用域是和具体的某一个session对应的
常用的API:
Void session.setAttribute(k, v)
Object session.getAttribute(k)
void removeAttribute(k)
原始情况下,保存作用域我们可以认为有四个: page(页面级别,现在几乎不用) , request(一次请求响应范围) , session(一次会话范围) , application(整个应用程序范围)
1) request:一次请求响应范围
2) session:一次会话范围有效
3) application: 一次应用程序范围有效
11.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
12.review复习
- 1.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");
- 2.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
-
3.HTTP协议:
-
1.由Request和Response两部分组成
-
2.请求包含了三部分:请求行、请求消息头、请求主体:(普通get方法请求)query String、 (post方式)form data、 (json格式请求负载)request payload
-
3.响应包含了三部分:响应行、响应消息头、响应主体
-
4.HttpSession
-
1.HttpSession:表示 会话
-
2.为什么需要HttpSession,原因是因为Http协议时无状态的
-
3.Session保存作用域:一次会话范围都有效;
session.setAttribute(k, v), Object session.getAttribute(k)
-
4.其他API:
session.getId(), session.isNew(), session.getCreationTime(), session.invalidate()
-
5.服务器端转发和客户端重定向
-
1.服务器端转发:
request.getRequestDispatcher(“index.html”).forward(request, response);
-
2.客户端重定向:
response.sendRedirect(“index.html”);
-
6.Thymeleaf的部分标签
-
1.使用步骤:添加jar包,新建ViewBaseServlet(有两个方法),配置两个
:前缀视图view-prefix,后缀视图view-suffix -
2.部分标签:
<th:if>, <th:unless>, <th:each>, <th:text>
13.Cookie
由于Http是无状态的,导致服务器无法识别不同的会话是否是同一浏览器发出,所以可以使用Cookie和Session来解决会话跟踪技术
1.Cookie的基本使用
- 1、发送Cookie
//发送Cookie
//1、创建Cookie对象
Cookie cookie = new Cookie("username", "zs");
//2、发送Cookie response
response.addCookie(cookie);
- 2、获取Cookie
//获取Cookie
//1、获取Cookie数组
Cookie[] cookies = request.getCookies();
//2、遍历数组
for (Cookie cookie : cookies) {
String name = cookie.getName();
//判断当username 和 cookie的name相同时,再获取映射的value
if("username".equals(name)) {
String value = cookie.getValue();
System.out.println(name + " : " + value);
//结束循环
break;
}
}
2.Cookie原理
-
Cookie的实现是基于HTTP协议的
-
响应头:set-cookie
-
请求头:cookie
3.Cookie使用细节
-
Cookie存活时间
-
默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁
-
setMaxAge(int seconds):设置Cookie存活时间
-
1.正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储,到时间自动删除。
-
2.附属:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie将销毁
-
3.零:删除对应Cookie
-
Cookie存储中文
-
Cookie默认不能存储中文
4.Session基本使用
- 服务端会话跟踪技术:将数据保存到服务端
- JavaEE提供HttpSession接口,来实现一次会话的多次请求间数据共享功能
- 使用
- 1.获取Session对象
HttpSession session = request.getSession();
- 2.Session对象功能
Void session.setAttribute(k, v)
:存储数据到Session域中
Object session.getAttribute(k)
:根据key,获取值
void removeAttribute(k)
:根据key,删除该键值对
5.Session原理
- Session是基于Cookie实现的
- 在浏览器首次访问时,如果浏览器没有sessionID的话,服务器会默认给浏览器响应一个sessionID。
- 如果浏览器再次访问,并且有sessionID的话,服务器会根据sessionId判断会话,并且不会再给浏览器分配sessionId
6.Session使用细节
- Session 钝化、活化:
- 服务器重启后,Session中的数据是否还在
钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中
活化:再次启动服务器后,从文件中加载数据到Session中
- Session 销毁:
- 默认情况下,误操作,30分钟自动销毁
<session-config>
<session-timeout>30</session-timeout>
</session-config>
- 调用Session对象的invalidate()方法
7.小结
- Cookie和Session都是来完成一次会话内多次请求间数据共享的
- 区别:
- 存储位置:Cookie是将数据存储在客户端,Session将数据存储在服务端
- 安全性:Cookie不安全,Session安全
- 数据大小:Cookie最大3kb,Session无大小限制
- 存储时间:Cookie可以长期存储,Session默认30分钟
- 服务器性能:Cookie不占服务器资源,Session占服务器资源
14.Maven
1.Maven安装配置
- 1、解压apache-maven-3.x.x.zip为安装完成
- 2、配置环境变量MAVEN_HOME为安装路径的bin目录
- 3、配置本地仓库:修改conf/settings.xml中的
为一个指定目录 - 4、配置阿里云私服:修改conf/settings.xml中的
标签,为其添加如下子标签:
<mirror>
<id>aliyunmaven</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
- 5、配置jdk默认版本:将profile配置文件放置到
标签中
<profile>
<id>jdk-17</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>17</jdk>
</activation>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
</properties>
</profile>
2.基本使用
Maven常用命令
-
compile:编译 -Java源程序编译成*.class字节码文件
-
clean:清理 -删除上一次构建的结果,为下一次构建做好准备
-
test:测试 -运行提前准备好的测试程序 junit
-
package:打包
-
Java工程:jar包
-
Web工程:war包
-
install:安装 -把一个Maven工程经过打包操作生成的jar包货war包存入Maven仓库
-
部署:
-
部署jar包:把一个jar包部署到Nexus私服服务器上
-
部署war包:借助相关Maven插件(例如cargo),将war包部署到Tomcat服务器上
3.Maven生命周期
-
Maven构建项目生命周期描述的是一次构建过程历经了多少个时间
-
Maven对项目构建的生命周期划分为3套
clean:清理工作
default:核心工作,例如编译、测试、打包、安装等
site:产生报告、发布站点等
4.Maven工作机制

5.Maven入门实战
实验一:根据坐标创建Maven工程
1、Maven核心概念:坐标
1.数学中的坐标
- 使用x、y、z三个【向量】作为空间的坐标系,可以在【空间】中唯一的定位到一个【点】。
2.Maven中的坐标
-
向量说明
-
groupld:公司或组织的id
-
artifactId:一个项目或者是项目中的一个模块的id
-
version:版本号
-
三个向量的取值方式
-
groupId:公司或组织域名的倒叙,通常也会加上项目名称
-
例如com.atguigu.maven
-
artifactId:模块的名称,将来作为Maven工程的工程名
-
version:模块的版本号,根据自己的需要设定
-
例如:SNAPSHOT表示快照版本,正在迭代过程中,不稳定的版本
-
例如:RELEASE表示正式版本
举例:
-
groupId:com.atguigu.maven
-
artifactId:pro01-atguigu-maven
-
Version:12.1.3-SNAPSHOP
3.坐标和仓库中 jar 包的存储路径之间的对应关系
- 坐标
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
- 上面坐标对应的jar包载Maven本地仓库中的位置
Maven仓库的根目录\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar
- 一定要学会根据坐标到本地仓库中找到对应的jar包
2、实验操作
1.创建目录作为后面操作的工作空间
例如:User/maven-workspace/space201025
::⚠️
此时我们已经有了三个目录,分别是:
- Maven核心程序:中军大帐
- Maven本地仓库:兵营
- 本地工作空间:战场
:::
2.在工作空间目录下打开命令行窗口
3.使用命令生成Maven工程
- 运行maven命令:
man archetype:generate

- 在
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 7:
后按回车
Define value for property 'groupId': com.atguigu.maven
Define value for property 'artifactId': pro01-maven-java
Define value for property 'version' 1.0-SNAPSHOT: : [默认回车]
Define value for property 'package' com.atguigu.maven: : [默认回车]
Confirm properties configuration:
groupId: com.atguigu.maven
artifactId: pro01-maven-java
version: 1.0-SNAPSHOT
package: com.atguigu.maven
Y: : [确定使用配置,回车,如有错误,重新输入则输入N再回车]
mazilong#mazilong:...
4.调整
-
Maven默认生成的工程,对Junit的依赖是较低的3.8.1版本,我们可以手动改成适合的4.12版本
-
自动生成的App.java和AppTest.java可以删除

5.自动生成的pom.xml解读
<!-- project 标签:根标签,表示对当前工程进行配置、管理 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- modelVersion 标签: 从Maven2开始就固定是4.0.0-->
<!-- 代表当前pom.xml所采用的标签结构 -->
<modelVersion>4.0.0</modelVersion>
<!-- gav坐标信息 -->
<!-- groupId标签:坐标的向量之一:代表公司或组织 -->
<groupId>com.atguigu.maven</groupId>
<!-- artifactId标签:坐标的向量之一:代表项目下的某一个模块 -->
<artifactId>pro01-maven-java</artifactId>
<!-- version标签:坐标向量之一:代表当前模块的版本 -->
<version>1.0-SNAPSHOT</version>
<!-- packaging标签:打包方式 -->
<!-- 默认取值jar包:生成jar包,说明是一个java工程 -->
<!-- 取值为war包:生成war包,说明是一个web工程 -->
<!-- 取值pom:说明这个工程是用来管理其他工程的工程 -->
<packaging>jar</packaging>
<name>pro01-maven-java</name>
<url>http://maven.apache.org</url>
<!-- properties标签:aven中定义属性值 -->
<properties>
<!-- 在构建过程中读取源码时使用的字符集 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- dependencies配置具体的依赖信息,可以包含多个dependency标签 -->
<dependencies>
<!-- dependency标签:配置一个具体的依赖信息 -->
<dependency>
<!-- 坐标信息:导入那个jar包,就配置他的坐标信息即可 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- scope标签:配置当前依赖的范围 -->
<scope>test</scope>
</dependency>
</dependencies>
</project>
3、Maven核心概念:POM
1.含义
POM:Project Object Model,项目对象模型。和POM类似的是:DOM,文档对象模型。他们都是模型化思想的具体体现。
2.模型化思想
POM表示将工程抽象为一个模型,再用程序中的对象来描述这个模型。这样我们就可以用程序来管理项目了。我们在开发过程中,最基本的做法就是将现实生活中的事物抽象为模型,然后封装模型相关的数据作为一个对象,这样就可以在程序中计算与现实事物相关的数据。
3.对应的配置文件
POM理念集中体现在Maven工程根目录下pom.xml这个配置文件中。所以这个pom.xml配置文件就是Maven工程的核心配置文件。其实学习Maven就是学这个文件怎么配置,各个配置有什么用。
4、Maven核心概念:约定的目录结构
1.各个目录的作用
这个应该有超级pom里进行配置,超级pom是所有pom的父pom。

另外还有一个target目录专门存放构建操作输出的结果。
2.约定目录结构的意义
Maven为了让构建过程能够尽可能自动化完成,所以必须约定目录结构的作用。例如:Maven执行编译操作,必须先去Java源程序目录读取Java源代码,然后执行编译,最后把变异结构放在target目录。
3.约定大于配置
Maven对于目录结构这个问题,没有采用配置的方式,而是基于约定。这样会让我们在开发过程中非常方便。如果每次创建Maven工程后,还需要针对各个目录的位置进行详细的配置,那肯定非常麻烦。
目前开发领域的技术发展趋势就是:约定大于配置,配置大于编码.
实验二:在Maven工程中编写代码
1、主题程序

主题程序指的是被测试的程序,同时也是将来在项目中真正要使用的程序。
package com.atguigu.maven;
public class Calculator {
public int sum(int i, int j) {
return i + j;
}
}
2、测试程序
package com.atguigu.maven;
import org.junit.Test;
import com.atguigu.maven.Calculator;
//静态导入的效果是将Assert类中的静态资源导入当前类
//这样一来,在当前类中就可以直接使用Assert类中的静态资源,不需要写类名
import static org.junit.Assert.*;
public class CalculatorTest {
@Test
public void testSum() {
// 1.创建Calculator对象
Calculator calculator = new Calculator();
// 2.调用Calculator对象的方法,获取到程序运行实际的结果
int actualResult = Calculator.sum(5, 3);
// 3.声明一个变量,表示程序运行期待的结果
int expectedResult = 8;
// 4.使用断言来判断实际结果和期待结果是否一致
// 如果一致:测试通过,不会抛出异常
// 如果不一致:抛出异常,测试失败
assertEquals(expectedResult, actualResult);
}
}
实验三:执行Maven的构建命令
1、要求
运行Maven中和构建操作相关的命令时,必须进入到pom.xml所在的目录。如果没有在pom.xml所在的目录运行Maven的构建命令,那么会报以下错误信息:
The goal you specified requires a project to execute but there is no POM in this directory
mvn -v命令和构建操作无关,只要正确配置了PATH,在任何目录下执行都可以。而构建相关的命令要在pom.xml所在目录下运行——操作那个工程,就进入这个工程的pom.xml目录
2、清理操作
mvn clean
效果:删除target目录
3、编译操作
主程序编译:mvn compile
测试程序编译:mvn test-compile
主体程序编译结果存在的目录:target/classes
测试程序编译结果存放的目录:target/test-classes
4、测试操作
mvn test
测试的报告存放的目录:target/surefire-reports
5、打包操作
mvn package
打包的结果——jar报,存放的目录:target
6、安装操作
mvn install
安装的效果是将本地构建过程中生成的jar包存入人Maven本地仓库。这个jar包在Maven仓库中的路径是根据它的坐标生成的。
坐标信息如下:
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
在Maven仓库中生成的路径如下:
/Users/mazilong/software/Maven-repo/com/atguigu/maven/pro01-maven-java/1.0-SNAPSHOT/pro01-maven-java-1.0-SNAPSHOT.jar
另外,安装操作还会将pom.xml文件转换为xxx.pom文件一起存入本地仓库。所以我们在Maven的本地仓库中想看一个jar包原始的pom.xml文件时,查看对应XXX.pom文件即可,他们是名字发生了改变,本质上是同一个文件。
实验四:创建Maven版的Web工程
1、说明
使用mvn archetype:generate命令生成Web工程时,需要使用一个专门的archetype。这个专门生成Web工程估价的archetype可以操找官网看到他的用法:

Maven生成的Web工程结构目录
project
|---pom.xml
`--src
`--main
`--webapp
|--WEB-INF
|-- `--web.xml
`-- index.jsp
参数archetypeGroupId,archetypeArtifactId,archetypeVersion用来指定 现在使用的maven- archetype-webapp的坐标。
2、操作
注意:如果在上一个工程的目录下执行 mvn archetype:generate 命令,那么 Maven 会报错:不能在一个非 pom 的工程下再创建其他工程。所以不要再刚才创建的工程里再创建新的工程,请回到工作空间根目录来操作。
然后运行生成工程的命令:
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.4
TIP
Define value for property 'groupId': com.atguigu.maven Define value for property 'artifactId': pro02-maven-web Define value for property 'version' 1.0-SNAPSHOT: :【直接回车,使用默认值】
Define value for property 'package' com.atguigu.maven: :【直接回车,使用默认值】 Confirm properties configuration: groupId: com.atguigu.maven artifactId: pro02-maven-web version: 1.0-SNAPSHOT package: com.atguigu.maven Y: :【直接回车,表示确认】
#
3、生成的pom.xml
确认打包的方式是war包形式
<packaging>war</packaging>
4、生成的Web工程的目录结构

webapp 目录下有 index.jsp
WEB-INF 目录下有 web.xml
5、创建Servlet
- 在main目录下创建java目录
- 在java目录下创建Servlet类所在的包的目录
- 在包下创建Servlet类
package com.atguigu.maven;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
public class HelloServlet extends HttpServlet{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("hello maven web");
}
}
- 在web.xml中注册Servlet
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.atguigu.maven.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
6、在index.jsp页面编写超链接
<html>
<body>
<h2>Hello World!</h2>
<a href="helloServlet">Access Servlet</a>
</body>
</html>
TIP
JSP全称是 Java Server Page,和 Thymeleaf 一样,是服务器端页面渲染技术。这里我们不必关心 JSP 语法细节,编写一个超链接标签即可。
#
7、编译
此时直接执行 mvn compile 命令出错:
DANGER
程序包 javax.servlet.http 不存在
程序包 javax.servlet 不存在
找不到符号
符号: 类 HttpServlet
……
上面的错误信息说明:我们的 Web 工程用到了 HttpServlet 这个类,而 HttpServlet 这个类属于 servlet-api.jar 这个 jar 包。此时我们说,Web 工程需要依赖 servlet-api.jar 包。

8、配置对servlet-api.jar包的依赖
对于不知道详细信息的依赖可以到https://mvnrepository.com/网站查询。使用关键词搜索,然后在搜索结果列表中选择适合的使用。

比如,我们找到的 servlet-api 的依赖信息:
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
这样就可以把上面的信息加入 pom.xml。重新执行 mvn compile 命令。
9、将web工程打包为war包
运行 mvn package 命令,生成 war 包的位置如下图所示:

10、将war包部署到Tomcat上运行
将 war 包复制到 Tomcat/webapps 目录下
启动 Tomcat:

通过浏览器尝试访问:http://localhost:8080/pro02-maven-web/index.jsp
实验五:让 Web 工程依赖 Java 工程
1、观念
明确一个意识:从来只有 Web 工程依赖 Java 工程,没有反过来 Java 工程依赖 Web 工程。本质上来说,Web 工程依赖的 Java 工程其实就是 Web 工程里导入的 jar 包。最终 Java 工程会变成 jar 包,放在 Web 工程的 WEB-INF/lib 目录下。
2、操作
在 pro02-maven-web 工程的 pom.xml 中,找到 dependencies 标签,在 dependencies 标签中做如下配置:
<!-- 配置对Java工程pro01-maven-java的依赖 -->
<!-- 具体的配置方式:在dependency标签内使用坐标实现依赖 -->
<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3、在Web工程中,编写测试代码
- 补充创建目录
pro02-maven-web\src\test\java\com\atguigu\maven
- 确认Web工程依赖了junit
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
- 创建测试类
把 Java 工程的 CalculatorTest.java 类复制到 pro02-maven-wb\src\test\java\com\atguigu\maven 目录下
4、执行Maven命令
- 测试命令
mvn test
说明:测试操作中会提前自动执行编译操作,测试成功就说明编译也是成功的。
- 打包命令
mvn package

通过查看 war 包内的结构,我们看到被 Web 工程依赖的 Java 工程确实是会变成 Web 工程的 WEB-INF/lib 目录下的 jar 包。

- 查看当前Web工程所依赖的jar包的列表
mvn dependency:list
TIP
[INFO] The following files have been resolved:
[INFO] org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] junit:junit:jar:4.12:test
说明:javax.servlet:javax.servlet-api:jar:3.1.0:provided 格式显示的是一个 jar 包的坐标信息。格式是:
TIP
groupId:artifactId:打包方式:version:依赖的范围
这样的格式虽然和我们 XML 配置文件中坐标的格式不同,但是本质上还是坐标信息,大家需要能够认识这样的格式,将来从 Maven 命令的日志或错误信息中看到这样格式的信息,就能够识别出来这是坐标。进而根据坐标到Maven 仓库找到对应的jar包,用这样的方式解决我们遇到的报错的情况。
- 以树形结构查看当前Web工程的依赖信息
mvn dependency:tree
TIP
[INFO] com.atguigu.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] - com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
我们在 pom.xml 中并没有依赖 hamcrest-core,但是它却被加入了我们依赖的列表。原因是:junit 依赖了hamcrest-core,然后基于依赖的传递性,hamcrest-core 被传递到我们的工程了。
实验六:测试依赖的范围
1、依赖范围
标签的位置:dependencies/dependency/scope
标签的可选值:compile/test/provided/system/runtime/import
- compile和test对比
main目录(空间 | test目录(空间) | 开发过程(时间) | 部署到服务器(时间) | |
---|---|---|---|---|
compile | 有效 | 有效 | 有效 | 有效 |
test | 无效 | 有效 | 有效 | 无效 |
- compile和provided对比
main目录(空间 | test目录(空间) | 开发过程(时间) | 部署到服务器(时间) | |
---|---|---|---|---|
compile | 有效 | 有效 | 有效 | 有效 |
provided | 有效 | 有效 | 有效 | 无效 |
- 结论
compile:通常使用的第三方框架的 jar 包这样在项目实际运行时真正要用到的 jar 包都是以 compile 范围进行依赖的。比如 SSM 框架所需jar包。
test:测试过程中使用的 jar 包,以 test 范围依赖进来。比如 junit。
provided:在开发过程中需要用到的“服务器上的 jar 包”通常以 provided 范围依赖进来。比如 servlet-api、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类 jar 包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!”
2、测试
- 验证compile范围对main目录有效
TIP
main目录下的类:HelloServlet 使用compile范围导入的依赖:pro01-atguigu-maven
验证:使用compile范围导入的依赖对main目录下的类来说是有效的
有效:HelloServlet 能够使用 pro01-atguigu-maven 工程中的 Calculator 类
验证方式:在 HelloServlet 类中导入 Calculator 类,然后编译就说明有效。
- 验证test范围对main目录无效
测试方式:在主体程序中导入org.junit.Test这个注解,然后执行编译。
具体操作:在pro01-maven-java\src\main\java\com\atguigu\maven目录下修改Calculator.java
package com.atguigu.maven;
import org.junit.Test;
public class Calculator {
public int sum(int i, int j){
return i + j;
}
}
执行Maven编译命令:
[ERROR] /D:/maven-workspace/space201026/pro01-maven-java/src/main/java/com/atguigu/maven/Calculator.java:[3,17] 程序包org.junit不存在
- 验证test和provided范围不参与服务器部署
其实就是验证:通过compile范围依赖的jar包会放入war包,通过test范围依赖的jar包不会放入war包。

- 验证provided范围对测试程序有效
测试方式是在pro02-maven-web的测试程序中加入servlet-api.jar包中的类。
修改:pro02-maven-web\src*test**\java\com\atguigu\maven*CalculatorTest.java**
package com.atguigu.maven;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import org.junit.Test;
import com.atguigu.maven.Calculator;
// 静态导入的效果是将Assert类中的静态资源导入当前类
// 这样一来,在当前类中就可以直接使用Assert类中的静态资源,不需要写类名
import static org.junit.Assert.*;
public class CalculatorTest{
@Test
public void testSum(){
// 1.创建Calculator对象
Calculator calculator = new Calculator();
// 2.调用Calculator对象的方法,获取到程序运行实际的结果
int actualResult = calculator.sum(5, 3);
// 3.声明一个变量,表示程序运行期待的结果
int expectedResult = 8;
// 4.使用断言来判断实际结果和期待结果是否一致
// 如果一致:测试通过,不会抛出异常
// 如果不一致:抛出异常,测试失败
assertEquals(expectedResult, actualResult);
}
}
然后运行Maven的编译命令:mvn compile
然后看到编译成功。
15.MyBatis
1 - MyBatis概述
1.什么是MyBatis?
- MyBatis是一款优秀的持久层框架,用于简化JDBC开发
- MyBatis本是Apache的一个开源项目iBatis,2010年这个项目有apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到了Github
- 官网:https://mybatis.org/mybatis-3/zh/index.html
2..持久层
- 负责将数据到保存到数据库的那一层代码
- JavaEE三层架构:表现层,业务层,持久层
3.框架
- 框架就是一个半成品软件,是一套可重用的,通用的软件基础代码模型。
- 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展。
4.JDBC的缺点

- 硬编码 - 配置文件
- 注册驱动,获取链接
- SQL语句
- 操作繁琐 - 自动完成
- 手动设置参数
- 手动封装结果集
2 - MyBatis快速入门
步骤:查询user表中所有数据
- 创建user表,添加数据
- 创建模块导入坐标
- 编写MyBatis核心配置文件 ——> 替换连接信息 解决硬编码问题
- 编写SQL映射文件 ——> 统一管理SQL语句,解决硬编码问题
- 编码
- 定义POJO类
- 加载核心配置文件,获取SqlSessionFactory对象
- 获取SqlSession对象,执行SQL对象
- 释放资源
16.Filter过滤器
1.什么是过滤器
-
概念:Filter表示过滤器,是JavaWeb三大组件(Servlet,Filter,Listener)之一。
-
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
-
过滤器一般完成一些通用的操作,比如:权限控制、统一编码处理、敏感字符处理等等。。。
2.Filter快速入门
-
1.让类实现Filter接口
-
2.配置类的过滤器注解,如果是以下配置,则默认拦截所有请求的资源
@WebFilter("/*")
- 3.在doFilter写过滤器代码,并放行
//拦截代码。。。
……
//放行
filterChain.doFilter(servletRequest, servletResponse);
3.Filter使用细节
- Filter拦截路径配置
拦截具体的资源:/index.jsp,只有访问index.jsp时,才会被拦截
目录拦截:/user/*,访问/user下的所有资源,都会被拦截
后缀名拦截:*.jsp,访问后缀名为jsp的资源,都会被拦截
拦截所有:/*,访问所有资源,都会被拦截
- Filter过滤器链
过滤器 -〉 过滤器 -〉 servlet
17.Listener监听器
1.监听器概念
- 1.Listener表示监听器,是JavaWeb三大组件(Servlet\Filter\Listener)之一
- 2.监听器可以监听就是在application,session,request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件
- 3.Listener分类:JavaWeb中提供了8个监听器
监听器分类 | 监听器名称 | 作用 |
---|---|---|
ServletContext监听 | ServletContextListener | 用于对ServletContext对象进行监听(创建、销毁) |
ServletContextAttributeListener | 对ServletContext对象中属性的监听(增删改属性) | |
Session监听 | HttpSessionListener | 对Session对象的整体状态的监听(创建、销毁) |
HttpSessionAttributeListener | 对Session对象中的属性监听(增删改属性) | |
HttpSessionBindingListener | 监听对象于Session的绑定和解除 | |
HttpSessionActivationListener | 对Session数据的钝化和活化的监听 | |
Request监听 | ServletRequestListener | 对Request对象进行监听(创建、销毁) |
ServletRequestAttributeListener | 对Request对象中属性的监听(增删改属性) |
2.ServletContextListener使用
- 1.定义类、实现ServletContextListener接口
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//加载资源
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//释放资源
}
}
- 2.在类上添加@WebListener注解
@WebListener
public class ContextLoaderListener implements ServletContextListener {
18.AJAX
1.AJAX概念
- 概念:AJAX(Asynchronous JavaScript And XML):一步的JavaScript和XML
- AJAX作用:
- 1.与服务器进行数据交换:通过AJAX可以给服务器发送请求,并获取服务器响应的数据
- 使用AJAX和服务器进行通信,就可以使用HTML+AJAX来替换JSP页面了
- 2.异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索华为、用户名是否可用校验,等等。。。
- 同步和异步的区别:
2.AJAX快速入门
-
1.编写AjaxServlet,并使用response输出字符串
-
2.创建XMLHttpRequest对象:用于和服务器交换数据
var xmlhttp;
if(window.XMLHttpRequest) {
//code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
//code for IE6, IE5
xmlhttp = new ActiveObject("Microsoft.XMLHTTP");
}
- 3.向服务器发送请求
xmlhttp.open("GET", "url");
xmlhttp.send(); //发送请求
- 4.获取服务器响应数据
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseTest);
}
}
3.Axios异步框架
- Axios对原生的AJAX进行封装,简化书写
3.1 Axios快速入门
- 1.引入axios的js文件
<script src="js/axios-0.18.0.js"></script>
- 2.使用axios发送请求,并获取相应结果
axios({
method:"get",
url:"http:localhost:8080/index?username=zhangsan"
}).then(function(resp){
alert(resp.data);
})
axios({
method:"post",
url:"http://localhost:8080/index",
data:"username=zhangsan"
}).then(function(resp){
alert(resp.data);
});
4.JSON
-
概念:JavaScript Object notation.JavaScript对象表示法
-
JavaScript对象
{
name:"zhangsan",
age:23,
city:"Beijing"
}
- JSON
{
"name":"zhangsan",
"age":23,
"city":"Beijing"
}
4.1 JSON基础语法
- 定义:
var 变量名 = {"key1":value1,
"key2":value2,
…
};
- 示例:
var json = {"name":"zhangsan",
"age":23,
"addr":["beijing", "Shanghai", "Xian"]
};
-
获取数据:
-
变量名.key
-
json.name
-
value的数据类型为:
-
数字(整数或浮点数)
-
字符串(在双引号中)
-
逻辑值(true或false)
-
数组(在方括号中)
-
对象(在花括号中)
-
null
4.2 JSON数据和JAVA对象转换
- 请求数据:JSON字符串转化为Java对象
- 响应数据:Java对象转为JSON字符串
JSON数据和Java对象转换
-
Fastjson是阿里巴巴提供的一个java语言编写的高性能功能完善的json库,目前Java语言中最快的JSON库,可以实现Java对象和JSON字符串的相互转换。
-
使用:
-
1.导入坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
- 2.Java对象转JSON
String jsonStr = JSON.toJSONString(obj);
- 3.JSON字符串转Java对象
User user = JSON.parseObject(jsonStr, User.class);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!