JavaWeb——Makedown笔记

JavaWeb

JavaWeb笔记

目录

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中配置的路径没有一斜杠打头:
url-pattern

2、xml配置别名不一致
xmlpeizhi

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程序

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 组成 不同的键值对,表示不同的含义
键值对

get

2.2.POST请求

  • 1.请求行
  • 1.请求的方式 -> POST
  • 2.请求的资源路径[+?+请求参数]
  • 3.请求的协议和版本号 -> HTTP/1.1
  • 2.请求头

key : value 组成 不同的键值对,表示不同的含义
空行

  • 3.请求体 -> 就是发送给服务器的数据

post

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标签的作用

lujing

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(); | 常用于回传字符串(常用) |

两个流同时只能使用一个。
使用了字节流,就不能再使用字符流,反之亦然,否则就会报错。

IllError

同时使用了两个响应流,就会报错

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.请求重定向(客户端重定向)

请求重定向,是指客户端给服务器发请求。然后服务器告诉客户端,让客户端重新去新的地址访问,叫做请求重定向(可能之前的地址已经被废弃)。

forward

第一种请求重定向的方式:

//设置响应状态吗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项目的三层架构

J2EE_3

分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。

层次 包名
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协议的说明

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 视图模版技术

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工作机制

Mavenjizhi

5.Maven入门实战

实验一:根据坐标创建Maven工程

1、Maven核心概念:坐标
1.数学中的坐标
  1. 使用x、y、z三个【向量】作为空间的坐标系,可以在【空间】中唯一的定位到一个【点】。
2.Maven中的坐标
  1. 向量说明

  2. groupld:公司或组织的id

  3. artifactId:一个项目或者是项目中的一个模块的id

  4. version:版本号

  5. 三个向量的取值方式

  6. groupId:公司或组织域名的倒叙,通常也会加上项目名称

  7. 例如com.atguigu.maven

  8. artifactId:模块的名称,将来作为Maven工程的工程名

  9. version:模块的版本号,根据自己的需要设定

  10. 例如:SNAPSHOT表示快照版本,正在迭代过程中,不稳定的版本

  11. 例如: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工程
  1. 运行maven命令:man archetype:generate
mvn
  1. 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.调整
  1. Maven默认生成的工程,对Junit的依赖是较低的3.8.1版本,我们可以手动改成适合的4.12版本

  2. 自动生成的App.java和AppTest.java可以删除

pow.xml
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。

src

​ 另外还有一个target目录专门存放构建操作输出的结果。

2.约定目录结构的意义

Maven为了让构建过程能够尽可能自动化完成,所以必须约定目录结构的作用。例如:Maven执行编译操作,必须先去Java源程序目录读取Java源代码,然后执行编译,最后把变异结构放在target目录。

3.约定大于配置

Maven对于目录结构这个问题,没有采用配置的方式,而是基于约定。这样会让我们在开发过程中非常方便。如果每次创建Maven工程后,还需要针对各个目录的位置进行详细的配置,那肯定非常麻烦。

目前开发领域的技术发展趋势就是:约定大于配置,配置大于编码.

实验二:在Maven工程中编写代码

1、主题程序
zhuti

主题程序指的是被测试的程序,同时也是将来在项目中真正要使用的程序。

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

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工程的目录结构
mulujiegou

webapp 目录下有 index.jsp

WEB-INF 目录下有 web.xml

5、创建Servlet
  1. 在main目录下创建java目录

mulu1

  1. 在java目录下创建Servlet类所在的包的目录

mulu2

  1. 在包下创建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");
}
}

  1. 在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 包。

gongchengyilai
8、配置对servlet-api.jar包的依赖

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

www

比如,我们找到的 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 包的位置如下图所示:

webWar
10、将war包部署到Tomcat上运行

将 war 包复制到 Tomcat/webapps 目录下

tomcat1

启动 Tomcat:

tomcatStart

通过浏览器尝试访问: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工程中,编写测试代码
  1. 补充创建目录

pro02-maven-web\src\test\java\com\atguigu\maven

  1. 确认Web工程依赖了junit
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
  1. 创建测试类

把 Java 工程的 CalculatorTest.java 类复制到 pro02-maven-wb\src\test\java\com\atguigu\maven 目录下

4、执行Maven命令
  1. 测试命令

mvn test

说明:测试操作中会提前自动执行编译操作,测试成功就说明编译也是成功的。

  1. 打包命令

mvn package

package_1

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

package_2
  1. 查看当前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包,用这样的方式解决我们遇到的报错的情况。

  1. 以树形结构查看当前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

  1. compile和test对比
main目录(空间 test目录(空间) 开发过程(时间) 部署到服务器(时间)
compile 有效 有效 有效 有效
test 无效 有效 有效 无效
  1. compile和provided对比
main目录(空间 test目录(空间) 开发过程(时间) 部署到服务器(时间)
compile 有效 有效 有效 有效
provided 有效 有效 有效 无效
  1. 结论

compile:通常使用的第三方框架的 jar 包这样在项目实际运行时真正要用到的 jar 包都是以 compile 范围进行依赖的。比如 SSM 框架所需jar包。

test:测试过程中使用的 jar 包,以 test 范围依赖进来。比如 junit。

provided:在开发过程中需要用到的“服务器上的 jar 包”通常以 provided 范围依赖进来。比如 servlet-api、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类 jar 包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!

2、测试
  1. 验证compile范围对main目录有效

TIP

main目录下的类:HelloServlet 使用compile范围导入的依赖:pro01-atguigu-maven

验证:使用compile范围导入的依赖对main目录下的类来说是有效的

有效:HelloServlet 能够使用 pro01-atguigu-maven 工程中的 Calculator 类

验证方式:在 HelloServlet 类中导入 Calculator 类,然后编译就说明有效。

  1. 验证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不存在

  1. 验证test和provided范围不参与服务器部署

其实就是验证:通过compile范围依赖的jar包会放入war包,通过test范围依赖的jar包不会放入war包。

scope

  1. 验证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的缺点

jdbcquedian
  1. 硬编码 - 配置文件
  • 注册驱动,获取链接
  • SQL语句
  1. 操作繁琐 - 自动完成
  • 手动设置参数
  • 手动封装结果集

2 - MyBatis快速入门

步骤:查询user表中所有数据

  1. 创建user表,添加数据
  2. 创建模块导入坐标
  3. 编写MyBatis核心配置文件 ——> 替换连接信息 解决硬编码问题
  4. 编写SQL映射文件 ——> 统一管理SQL语句,解决硬编码问题
  5. 编码
  6. 定义POJO类
  7. 加载核心配置文件,获取SqlSessionFactory对象
  8. 获取SqlSession对象,执行SQL对象
  9. 释放资源

16.Filter过滤器

1.什么是过滤器

  • 概念:Filter表示过滤器,是JavaWeb三大组件(Servlet,Filter,Listener)之一。

  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。

  • 过滤器一般完成一些通用的操作,比如:权限控制、统一编码处理、敏感字符处理等等。。。

2.Filter快速入门

  • 1.让类实现Filter接口

  • 2.配置类的过滤器注解,如果是以下配置,则默认拦截所有请求的资源

@WebFilter("/*")
  • 3.在doFilter写过滤器代码,并放行
//拦截代码。。。
……
//放行
filterChain.doFilter(servletRequest, servletResponse);

filter

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.异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索华为、用户名是否可用校验,等等。。。

AJAX

  • 同步和异步的区别:

yibu

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);
posted @   QBT~大吃货  阅读(151303)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示