目录

Java Web阶段核心内容

(一)初识Web

1、JavaWeb定义

2、B/S与C/S模式

3、网站与网页

4、Tomcat服务器

5、Maven

6、常见的Http状态码

7、Servlet

8、三层架构

(二)访问/提交/获取

1、访问服务器的某个URL

2、页面向服务端提交数据的方式

3、服务器端获取页面传递的数据

4、表单提交数据注意事项

5、解决请求和响应的中文乱码

6、web.xml文件中的常用标签

7、Servlet的生命周期

8、使用注解开发Servlet

小结:

1)B/S模式的访问流程

2)页面提交数据的方式

(三)Jsp

1、定义

2、JSP的组成

(四)跳转

1、页面与页面之间跳转

2、页面跳转至Servlet

3、Servlet跳转到页面或另一个Servlet

1)请求转发(内部跳转)

2)重定向(外部跳转)

4、跳转时传递数据

1)保存

2)获取

(五)分页

1、MySQL分页查询

1)原理

2)dao层中分页相关方法

3)servlet中加入分页请求判断

4)页面

2、条件分页(关键字搜索)

1)原理

2)dao

3)servlet

4)页面

5)首页

(六)路径

1、绝对路径

2、相对路径

(七)作用域

1、作用域定义

2、四大作用域对象

1)pageContext

2)request

3)session

4)application

3、作用域范围

4、作用域对象的使用

1)在JSP页面中

2)在servlet中使用

小结:

(八)EL

1、定义

2、特点

3、使用

1)在页面中输出保存在作用域中的对象

2)在页面中获取请求中的参数

3)用于获取当前项目上下文(根目录+项目名)路径

4、注意

(九)JSTL

1、定义

2、使用

1)导入JSTL对应的依赖

2)在JSP页面中,加入标签库指令

3)具体用法

(十)Ajax

1、定义

2、使用

1)在页面中导入jquery文件

2)在script标签中写ajax

(十一)JSP内置对象

(十二)Session和Cookie

1、Cookie

1)cookie的创建

2)cookie的获取

2、Session

1)原理

2)session对象的常用方法

3)设置全局session有效时长

3、Session和Cookie对比

(十三)监听器

1、常用的三个监听器接口

2、实现一个监听器

(十四)过滤器Filter

1、使用

2、在web.xml中配置的话

3、使用@WebFilter("/*")注解配置的话

(十五)Web项目开发模式

1、Model1

2、Model2(MVC)


Java Web阶段核心内容

(一)初识Web

1、JavaWeb定义

使用Java开发Web服务的技术,统称为JavaWeb。

2、B/S与C/S模式

  • B/S:Browser/Server 浏览器/服务器模式 用户只需要一个浏览器即可访问服务器。
  • C/S:Clint/Server 客户端/服务器模式 用户需要下载客户端才能访问服务器。

3、网站与网页

1)网站:用户通过浏览器访问某个域名或IP地址时,浏览到的综合性页面。实际就是发布在服务器上的一个应用程序,用户通过浏览器访问该程序。

2)网页:网站中的一个页面。

>>网页分类

  • 静态页面:所有人看到的数据都一致。
  • 动态页面:不同的人看到的页面中的数据不一致 JavaWeb就是B/S模式下的软件开发,开发综合性的服务网站。

4、Tomcat服务器

网络服务器:部署Web项目的平台。

Tomcat:由Apache、Sun和其他公司及个人共同开发的web服务器。 免费、开源、轻量级,在中小型系统中普遍被使用。 是开发和调试Web项目的首选。

>>解决Tomcat控制台乱码:

加上        -Dfile.encoding=utf-8        。如下图所示:

5、Maven

用于结构化管理jar文件的工具。 通过在Maven项目中加入某个jar文件的依赖,让其自动从Maven云仓库中下载对应的jar文件。

6、常见的Http状态码

常见状态码

含义
200 成功
404 资源未找到
500 服务器内部错误
405 方法不允许

7、Servlet

Server+Applet 运行在服务器上的程序

>>编写Servlet的步骤:

  • 在项目中导入Servlet相关依赖
  • 在项目的java目录下,创建一个类,继承HttpServlet,重写 doGet和doPost方法
  • 在web.xml中设置Servlet的请求映射
  • 访问Servlet

8、三层架构

在软件开发中,并不是将所有功能都交给一个类去实现,而是要将其进行分层,从而达到"高内聚、低耦合"的目的。

  • 低耦合是指降低各个模块之间的关联程度,这样便于开发和维护,每个模块各司其职。
  • 高内聚是指每个模块内的功能不可再分。

通常所说的三层架构中的三层,是指“数据访问层、业务逻辑层和视图表现层”

  • 数据访问层,用于连接数据库,对数据做增删改查的操作
  • 业务逻辑层,用于处理业务逻辑,在适当的情况下调用数据访问层中的方法
  • 视图表现层,用于展示数据和提供用户输入数据的渠道,在适当的情况下调用业务逻辑层中的方法

(二)访问/提交/获取

1、访问服务器的某个URL

  • 在浏览器的地址栏中输入对应的URL,属于GET提交
  • 使用a标签,在href中输入对应的URL,属于GET提交
  • 使用form表单,在action中输入对应的URL,通过method修改提交方式为GET或POST

2、页面向服务端提交数据的方式

  • 使用form表单的name属性显示提交
<form action="http://localhost:8080/day1/hero" method="get">
<input type="text" name="username">
<input type="submit">
</form>

>>提交的数据会暴露在浏览器的地址栏中。

  • 使用form表单的name属性隐式提交
<form action="http://localhost:8080/day1/hero" method="post">
<input type="text" name="username">
<input type="submit">
</form>

>>提交的数据不会暴露在浏览器的地址栏中。

  • 通过"?参数名=值"方式提交

1)在地址栏中输入URL的时候,末尾加入这部分

https://www.baidu.com/s?wd=hello

2)在a标签的href属性中加入这部分,如果有多个参数,通过&拼接

<a href="https://www.baidu.com/s?wd=hello&a=1&b=2">访问</a>

3、服务器端获取页面传递的数据

以上任何方式提交到服务器的数据,都可以使用以下方式获取。

String str=request.getParameter("name名或?后的参数名");

例如:

class TestServlet extends HttpServlet{
doGet(HttpServletRequest req,HttpServletResponse resp){
//获取表单提交的数据req.getParameter("表单中某个表单元素的name值");
String username = req.getParameter("username");
}
doPost(HttpServletRequest req,HttpServletResponse resp){
doGet();
}
}

4、表单提交数据注意事项

  • 表单通过action提交设置的路径,如果要在路径中传递参数,只能使用post方式提交
<form action="xxxxx?参数=值" method="post">
</form>
  • 使用get方式提交,无法识别action路径中的参数,如果要传递参数,使用隐藏域
<form action="xxxxx" method="get">
<input type="hidden" name="参数名" value="参数值">
</form>

5、解决请求和响应的中文乱码

//在servlet的doGet或doPost所有代码之前中加入
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");

6、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">
<!--设置项目启动的欢迎页-->
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
<!--设置错误页面-->
<error-page>
<!--错误码-->
<error-code>404</error-code>
<!--页面路径-->
<location>/404.html</location>
</error-page>
<error-page>
<!--异常类型-->
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error.html</location>
</error-page>
<!--上下文参数-->
<context-param>
<!--参数名-->
<param-name>contentParam</param-name>
<!--参数值-->
<param-value>全局参数</param-value>
</context-param>
<!--servlet标签-->
<!--servlet-mapping标签-->
<!--filter标签-->
<!--filter-mapping标签-->
<!--session-config标签-->
</web-app>

7、Servlet的生命周期

构造方法-->init()-->service()/doGet()/doPost()-->destory()

>>在访问某servlet时

  1. 执行构造方法一次
  2. 初始化一次,调用init()方法
  3. 调用service()方法,之后每次访问都会调用该方法。有该方法时,doGet和doPost失效。 如果没有该方法,会根据请求方式试图调用doGet或doPost,如果没有相应的方法,会出现405状态码,表示请求方式不允许
  4. 在当前servlet所在项目从tomcat中停止时,销毁一次,调用destory()方法

8、使用注解开发Servlet

/*
* 使用注解开发Servlet
* 注解:@特定单词 如@Override
*
* 定义且配置Servlet的注解:@WebServlet("/请求映射")
* */
@WebServlet("/sysAdmin")
public class SysAdminServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
//访问该Servlet时要执行的内容
}
}
//@WebServlet("/sysAdmin")相当于在web.xml中进行配置servlet映射

小结:

1)B/S模式的访问流程

用户通过浏览器发送请求,访问服务器上的某个部署的项目,经过该项目的MVC,得到响应。 框架部分会使用SpringMVC替换现有的Servlet实现MVC的流程。

2)页面提交数据的方式

  • 通过表单提交,可以设置get/post
<form action="地址" method="get/post">
<input type="text" name="参数" >
<input type="submit">
</form>
  • 通过超链接提交,属于get提交
<a href="地址?参数=值&参数=值">xxx</a>
  • 通过ajax提交,可以设置get/post

先导入Jquery

$.ajax({
//请求地址
url:'',
//提交数据
data:{
"参数名":值,
"参数名":值
},
//提交方式
type:"get/post",
//成功回调
success:function(res){
//res为控制层的返回值
},
//失败回调
error:function(){}
});

(三)Jsp

1、定义

Java Server Page的简称,使用Java开发、运行在服务器上的页面。 jsp文件的后缀名为".jsp"。

由于最初由servlet渲染页面,在Java代码中加入大量html的内容,使用极不方便。所以Sun公司推出了 JSP,可以在页面中加入java代码,让页面成为动态页面。

JSP页面的本质是一个java文件(servlet)。

注意:在访问某个jsp页面时,会让该页面重新编译为.java文件-->.class文件,所以第一次访问某个JSP页面时会慢一些。

2、JSP的组成

1)HTML元素

2)脚本(java代码)

<%java代码;%>

3)表达式

用于在页面中嵌入变量的值

<%=变量%>

4)指令

<%@ 指令名 属性="值" %>
  • page指令 用于设置当前页面的属性
  • include指令 用于引入其他页面
  • taglib指令 用于引入其他标签库

5)注释

<%-- jsp注释 --%>

在浏览器中可以查看html的注释,无法查看jsp的注释

6)声明

<%! 定义方法 %>

在中无法定义方法,如果非要在jsp页面中定义方法,需要使用声明。不建议在jsp页面中定义方 法。

7)动作

jsp中定义了一些标签,可以代替某些java代码

<jsp:动作名></jsp:动作名>

(四)跳转

1、页面与页面之间跳转

<a href="另一个页面的地址">超链接</a>
<form action="另一个页面的地址">
<input type="submit">
</form>
<button id="btn">跳转</button>
<script>
$("#btn").click(function(){
location.href="另一个页面的地址";
location.assign("另一个页面的地址");
});
</script>

2、页面跳转至Servlet

<a href="servlet映射名">超链接</a>
<form action="servlet映射名">
<input type="submit">
</form>

3、Servlet跳转到页面或另一个Servlet

1)请求转发(内部跳转)

request.getRequestDispatcher("跳转的地址").forward(request,response);

如A同学问B同学问题,B同学自己去问C同学后得到了答案,将答案告诉给A同学。

  • 跳转到目的地时,浏览器的地址栏中的内容是访问时的地址
  • 如果在某个Servlet做完增删改的操作后,不要使用请求转发。因为当重新刷新页面时,会重复提交
  • 如果在request中保存了数据,只能通过请求转发才能读取request中保存的数据

2)重定向(外部跳转)

response.sendRedirect("跳转的地址");

如A同学问B同学问题,B同学告诉A同学去问C同学,A同学重新问C同学后得到答案。

  • 跳转到目的地时,浏览器的地址栏中的内容是最终的目的路径
  • 在做完增删改的操作后,使用重定向,可以保证最终页面与之前页面无关,刷新时不会重新提交
  • 如果在request中保存了数据,使用重定向,保存的数据就会丢失

4、跳转时传递数据

1)保存

作用域对象.setAttribute(String str,Object obj);
//将一个名为str的对象obj保存到某个作用域中。request就是一个作用域。
List<泛型> 集合 = dao.查询();
//将查询到的集合保存到请求中,命名为list
request.setAttribute("list",集合);

2)获取

Object obj = 作用域对象.getAttribute(String str);
//获取到的数据是Object类型,通常需要转型
List<泛型> list =(List<泛型>) request.getAttribute("list");

(五)分页

1、MySQL分页查询

1)原理

select * from 表;
-- 查询前N条记录
select * from 表 limit N;
-- 从第N条记录开始查询M条记录
select * from 表 limit N,M;
-- 如每页显示8条,第一页
select * from 表 limit 0,8
-- 第二页
select * from 表 limit 8,8
-- 公式 size表示每页显示的数量 page表示页数
select * from 表 limit (page-1)*size,size

2)dao层中分页相关方法

/*
* 查询总记录数
* */
public int getSumCount() {
conn = DBUtil.getConn();
String sql = "select count(book_id) from book_info ";
try {
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
if (rs.next()) {
return rs.getInt(1);
}
} catch (SQLException e) {
System.out.println("查询总记录数异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return 0;
}
/*
* 分页查询
* */
public List<BookInfo> queryByPage(int page, int size) {
ArrayList<BookInfo> list = new ArrayList<>();
conn = DBUtil.getConn();
String sql = "select * from book_info limit ?,?";
try {
pst = conn.prepareStatement(sql);
pst.setInt(1, (page - 1) * size);
pst.setInt(2, size);
rs = pst.executeQuery();
while (rs.next()) {
int bookId = rs.getInt(1);
int typeId = rs.getInt(2);
String bookName = rs.getString(3);
String bookAuthor = rs.getString(4);
int bookPrice = rs.getInt(5);
int bookNum = rs.getInt(6);
String publisherDate = rs.getString(7);
String bookImg = rs.getString(8);
//参数中所需的主表对象实体,需要通过dao对象查询
BookInfo bookInfo = new BookInfo(bookId, typeId, bookName,
bookAuthor, bookPrice, bookNum, publisherDate, bookImg, btDao.findById(typeId));
list.add(bookInfo);
}
} catch (SQLException e) {
System.out.println("分页查询异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return list;
}

3)servlet中加入分页请求判断

package com.hqyj.bookShop.servlet;
import com.hqyj.bookShop.dao.BookInfoDao;
import com.hqyj.bookShop.entity.BookInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/bookInfo")
public class BookInfoServlet extends HttpServlet {
//创建数据访问层对象
BookInfoDao biDao = new BookInfoDao();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String op = req.getParameter("op");
switch (op) {
//分页查询
case "queryByPage":
//得到总记录数
int sumCount = biDao.getSumCount();
//将总记录数保存到请求中
req.setAttribute("sumCount",sumCount);
//初始第一页
int page=1;
int size=8;
//获取要查询的页数
if (req.getParameter("page")!=null) {
page=Integer.parseInt(req.getParameter("page"));
}
//调用分页查询
List<BookInfo> list2 = biDao.queryByPage(page,size);
//将查询的结果保存、跳转
req.setAttribute("list", list2);
req.getRequestDispatcher("./pages/bookList.jsp").forward(req,
resp);
break;
}
}
}

4)页面

<%@ page import="com.hqyj.bookShop.entity.BookInfo" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<%
List<BookInfo> list = (List<BookInfo>) request.getAttribute("list");
%>
<div class="product_list">
<div class="left"></div>
<div class="right">
<%for (BookInfo bookInfo : list) {%>
<div>
<img alt="暂无图片" src="./img/<%=bookInfo.getBookImg()%>">
<p class="title"><%=bookInfo.getBookName()%>
</p>
<p class="desc"><%=bookInfo.getBookType().getTypeName()%>|
<%=bookInfo.getBookAuthor()%>
</p>
<p class="price">¥<%=bookInfo.getBookPrice()%>
</p>
</div>
<% }%>
</div>
</div>
<%
/*pno默认1*/
int pno = 1;
/*从请求中获取当前页数*/
if (request.getParameter("page") != null) {
pno = Integer.parseInt(request.getParameter("page"));
}
/*获取总记录数*/
int sumCount = (Integer) request.getAttribute("sumCount");
//计算最大页数
int maxPage=(int)Math.ceil(sumCount/8.0);
%>
<div class="pageTool">
<%--在请求分页的servlet时,传递page参数表示当前页--%>
<a href="http://localhost:8080/Web03/bookInfo?op=queryByPage&page=<%=(pno1==0)?1:pno-1%>">上一页</a>
<span>第<%=pno%>页</span>
<span>共<%=maxPage%>页</span>
<a href="http://localhost:8080/Web03/bookInfo?op=queryByPage&page=
<%=pno+1>maxPage?maxPage:pno+1%>">下一页</a>
</div>
</body>
</html>

2、条件分页(关键字搜索)

1)原理

select * from 表 where 字段 like concat('%',keyword,'%') limit (page-1)*size,size

2)dao

package com.hqyj.bookShop.dao;
import com.hqyj.bookShop.entity.BookInfo;
import com.hqyj.bookShop.entity.BookType;
import com.hqyj.bookShop.util.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class BookInfoDao {
BookTypeDao btDao = new BookTypeDao();
/*
* 查询所有类型
* */
Connection conn;
PreparedStatement pst;
ResultSet rs;
/*
* 根据关键字查询总记录数
* */
public int getSumCount(String keyword) {
conn = DBUtil.getConn();
String sql = "select count(book_id) from book_info where book_name like
concat('%',?,'%')";
try {
pst = conn.prepareStatement(sql);
pst.setString(1,keyword);
rs = pst.executeQuery();
if (rs.next()) {
return rs.getInt(1);
}
} catch (SQLException e) {
System.out.println("查询总记录数异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return 0;
}
/*
* 条件查询(关键字分页)
* */
public List<BookInfo> queryByCondition(int page,int size,String keyword){
ArrayList<BookInfo> list = new ArrayList<>();
conn = DBUtil.getConn();
String sql = "select * from book_info where book_name like
concat('%',?,'%') limit ?,?";
try {
pst = conn.prepareStatement(sql);
pst.setString(1, keyword);
pst.setInt(2, (page-1)*size);
pst.setInt(3, size);
rs = pst.executeQuery();
while (rs.next()) {
int bookId = rs.getInt(1);
int typeId = rs.getInt(2);
String bookName = rs.getString(3);
String bookAuthor = rs.getString(4);
int bookPrice = rs.getInt(5);
int bookNum = rs.getInt(6);
String publisherDate = rs.getString(7);
String bookImg = rs.getString(8);
//参数中所需的主表对象实体,需要通过dao对象查询
BookInfo bookInfo = new BookInfo(bookId, typeId, bookName,
bookAuthor, bookPrice, bookNum, publisherDate, bookImg, btDao.findById(typeId));
list.add(bookInfo);
}
} catch (SQLException e) {
System.out.println("关键字分页查询异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return list;
}
}

3)servlet

package com.hqyj.bookShop.servlet;
import com.hqyj.bookShop.dao.BookInfoDao;
import com.hqyj.bookShop.entity.BookInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/bookInfo")
public class BookInfoServlet extends HttpServlet {
//创建数据访问层对象
BookInfoDao biDao = new BookInfoDao();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String op = req.getParameter("op");
switch (op) {
case "search":
//获取搜索关键字,第一次访问时没有关键字,使用""查询
String keyword =
req.getParameter("keyword")==null?"":req.getParameter("keyword");
//得到总记录数
int sumCount = biDao.getSumCount(keyword);
//将总记录数保存到请求中
req.setAttribute("sumCount", sumCount);
//初始第一页
int page = 1;
int size = 8;
//获取要查询的页数
if (req.getParameter("page") != null) {
page = Integer.parseInt(req.getParameter("page"));
}
//调用条件查询,保存集合,跳转页面
List<BookInfo> list = biDao.queryByCondition(page, size,
keyword);
req.setAttribute("list",list);
req.getRequestDispatcher("./pages/bookList.jsp").forward(req,
resp);
break;
}
}
}

4)页面

<%@ page import="com.hqyj.bookShop.entity.BookInfo" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #f5f5f5;
}
.product_list {
width: 1240px;
height: 614px;
margin: 0px auto;
}
.product_list > div {
float: left;
}
.left {
width: 234px;
height: 614px;
background-image: url(./img/left.jpg);
background-size: 100%;
}
.right {
width: 992px;
height: 614px;
}
.right > div {
width: 234px;
height: 300px;
background-color: #fff;
float: left;
margin-left: 14px;
margin-bottom: 14px;
position: relative;
transition-duration: 0.2s;
}
.right > div img {
width: 160px;
height: 160px;
display: block;
margin: 20px auto;
}
.right .title {
font-size: 14px;
font-weight: 400;
text-align: center;
color: #333;
}
.right .desc {
width: 214px;
height: 18px;
margin: 2px auto 10px;
font-size: 12px;
color: #b0b0b0;
overflow: hidden;
text-align: center;
}
.right .price {
text-align: center;
color: #ff6700;
font-size: 14px;
}
.right > div:hover {
/* 向上平移2px */
transform: translate(0, -3px);
box-shadow: rgba(0, 0, 0, 0.2) 0 0 20px;
}
.header {
width: 100%;
height: 80px;
border-bottom: 2px solid #eee;
background-color: #fff;
}
.header .logo {
width: 240px;
height: 80px;
float: left;
margin-left: 100px;
background-image: url("./img/logo.png");
background-size: cover;
}
.header .customer {
float: right;
width: 300px;
height: 80px;
text-align: center;
line-height: 80px;
color: deepskyblue;
font-size: 14px;
margin-right: 100px;
}
a {
text-decoration: none;
color: deepskyblue;
}
.search {
width: 600px;
height: 80px;
margin: 0 auto;
}
.search input[type="text"] {
width: 300px;
height: 40px;
margin-top: 20px;
margin-left: 100px;
font-size: 20px;
outline: none;
border: none;
border: 1px solid skyblue;
}
.search input[type="submit"] {
width: 80px;
height: 40px;
border: none;
background-color: #fff;
color: deepskyblue;
font-size: 20px;
}
.pageTool {
width: 200px;
margin: 0 auto 100px;
}
</style>
</head>
<body>
<%
List<BookInfo> list = (List<BookInfo>) request.getAttribute("list");
%>
<div class="header">
<div class="logo"></div>
<div class="customer">
当前客户:xxx
<a href="#">我的购物车</a>
<a href="#">安全退出</a>
</div>
</div>
<div class="search">
<form action="./bookInfo">
<input type="hidden" name="op" value="search">
<input type="text" placeholder="请输入关键字查询" value="
<%=request.getParameter("keyword")==null?"": request.getParameter("keyword")%>"
name="keyword">
<input type="submit" value="搜索">
</form>
</div>
<div class="product_list">
<div class="left"></div>
<div class="right">
<%for (BookInfo bookInfo : list) {%>
<div>
<img alt="暂无图片" src="./img/<%=bookInfo.getBookImg()%>">
<p class="title"><%=bookInfo.getBookName()%>
</p>
<p class="desc"><%=bookInfo.getBookType().getTypeName()%>|
<%=bookInfo.getBookAuthor()%>
</p>
<p class="price">¥<%=bookInfo.getBookPrice()%>
</p>
</div>
<% }%>
</div>
</div>
<%
/*pno默认1*/
int pno = 1;
/*从请求中获取当前页数*/
if (request.getParameter("page") != null) {
pno = Integer.parseInt(request.getParameter("page"));
}
/*获取总记录数*/
int sumCount = (Integer) request.getAttribute("sumCount");
//计算最大页数
int maxPage=(int)Math.ceil(sumCount/8.0);
//获取请求中的关键字,如果没有搜索过,使用空白字符串
String keyword= request.getParameter("keyword")==null?"":
request.getParameter("keyword");
%>
<div class="pageTool">
<%--在请求分页的servlet时,传递page参数表示当前页--%>
<a href="http://localhost:8080/Web03/bookInfo?op=search&keyword=
<%=keyword%>&page=<%=(pno-1==0)?1:pno-1%>">上一页</a>
<span>第<%=pno%>页</span>
<span>共<%=maxPage%>页</span>
<a href="http://localhost:8080/Web03/bookInfo?op=search&keyword=
<%=keyword%>&page=<%=pno+1>maxPage?maxPage:pno+1%>">下一页</a>
</div>
</body>
</html>

5)首页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
/*访问该页面时,跳转至分页查询*/
response.sendRedirect("http://localhost:8080/Web03/bookInfo?op=search");
%>
</body>
</html>

(六)路径

1、绝对路径

例如:

<a href="localhost:8080/system/pages/hello.html">跳转</a>

2、相对路径

  • / 表示根目录,即域名:端口号,如localhost:8080
  • ./ 表示当前目录,如在localhost:8080/Web03/page.html页面中访问./index.html,相当于 localhost:8080/Web03/index.html
  • ../ 表示向上一层目录,如在localhost:8080/Web03/page.html页面中访问../index.html,相当于 localhost:8080/index.html
如有index页面所在路径为
localhost:8080/system/pages/index.html
<a href="/hello.html">跳转</a>
这种方式,从根目录(localhost:8080)出发,会跳转到localhost:8080/hello.html
<a href="./hello.html">跳转</a>
这种方式,从当前位置(localhost:8080/system/pages)出发,会跳转到
localhost:8080/system/pages/hello.html
<a href="../hello.html">跳转</a>
这种方式,从当前位置跳向上一层,会跳转到localhost:8080/system/hello.html
  • 在jsp页面中,可以使用${pageContex.request.contextPath}表示页面上下文路径。

如项目默认上下文访问路径为localhost:8080/system

<a href="${pageContex.request.contextPath}/pages/hello.html">跳转</a>

以上路径相当于/system/pages/hello.html,即从根目录出发localhost:8080/system/pages/hello.html 如果在jsp页面中无法识别${},在中加入isELIgnored="false"——

<%@ page contentType="text/html;charset=UTF-8" language="java"
isELIgnored="false" %>

(七)作用域

1、作用域定义

共享数据的区域

2、四大作用域对象

1)pageContext

当前页面对象。共享数据区域范围为当前页面。 如果不在同一个页面,数据无法读取。

2)request

请求对象。共享数据区域范围为一次请求。 如果跳转中途使用了重定向,数据无法读取。

3)session

会话对象。会话是用户访问服务器时的某个时间段。 共享数据区域范围在这个时间段内,默认30分钟。 如果在指定时间内没有操作或销毁会话时,数据无法读取。

4)application

项目对象。共享数据区域范围为整个项目。

3、作用域范围

application > session > request > pageContext

以上四个作用域对象,都有这几个方法:

//将某个对象obj保存到作用域中,命名为str
作用域对象.setAttribute(String str,Object obj);
//从某个作用域中获取保存的某个对象
Object obj = 作用域对象.getAttribute(String str);
//从某个作用域中移除某个保存的对象
作用域对象.removeAttribute(String str);

4、作用域对象的使用

1)在JSP页面中

p1.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//在jsp中使用pageContext页面上下文对象,跳转到p2时不能使用
pageContext.setAttribute("str","保存在pageContext作用域中的字符串");
//在jsp中使用request请求对象,请求转发到p2时可以使用,重定向到p2时不能使用
request.setAttribute("str","保存在request中的字符串");
//在jsp中使用session会话对象,在默认的30分钟内,没有销毁,哪种跳转都能在p2中使用
session.setAttribute("str","保存在session中的字符串");
//在jsp中使用application应用程序对象,整个项目中任何页面都能使用
application.setAttribute("str","保存在application中的字符串");
//以上四个作用域对象,也是jsp中的内置对象,无需定义
//销毁会话
//session.invalidate();
//使用请求转发跳转到p2.jsp
//request.getRequestDispatcher("p2.jsp").forward(request,response);
//使用重定向跳转到p2.jsp
response.sendRedirect("p2.jsp");
%>
<h1><%=pageContext.getAttribute("str")%></h1>
</body>
</html>

p2.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3><%=pageContext.getAttribute("str")%></h3>
<h3><%=request.getAttribute("str")%></h3>
<h3><%=session.getAttribute("str")%></h3>
<h3><%=application.getAttribute("str")%></h3>
</body>
</html>

2)在servlet中使用

  • pageContext

servlet本身就是一个java类,在类中定义成员变量,就能在当前类中使用。 所以在servlet中不会使用pageContext对象

  • request

使用doGet/doPost/service方法中的HttpServletRequest参数req

  • session
//在servlet中使用session,需要通过请求对象request调用getSession()方法
HttpSession session= req.getSession();
  • application
//通过getServletContext()方法获取的ServletContext类型对象,就是当前项目对象
ServletContext application = getServletContext();

小结:

  • 在jsp页面中使用pageContext保存的数据,只能共享于当前页面
  • 通常在servlet中查询后的数据保存在request中,使用请求转发跳转到其他页面,在对应的页面中 数据数据
  • 通常在登录后,将登录的用户保存在session中,无论用哪种方式跳转,都能从session中获取当时 登录的用户。
  • 在application中保存一些共享于整个项目中的数据

(八)EL

1、定义

Expression Language 表达式语言

是为了使JSP写起来更加简便,替换JSP中的,简化了JSP页面中输出数据的操作。 主要输出保存在某个作用域中的数据。

2、特点

如果通过"某个作用域对象.setAttribute("cus",customer)"方法保存的对象, 在JSP页面中如果用表达式,使用,如果用EL,使用${cus}输出。 会依次从pageContext-->reqeust-->session-->application中获取指定对象, 如果一旦从某个作用域中获取到了指定对象,就不再判断后续作用域。 也可以输出指定作用域中的对象。

  • 只能输出保存在作用域中的对象
  • 减少代码(省去了获取对象、转换的过程)
  • 免去非空判断(如果某个要输出的对象不存在,不会输出null,而是输出空字符串"")

3、使用

1)在页面中输出保存在作用域中的对象

  • 从作用域中依次查询并输出对象
${对象名}
  • 从指定作用域中输出对象

  • 输出对象的属性
${对象名.属性名}
${对象名["属性名"]}
  • 输出对象的方法返回值
${对象名.方法名()}

如在servlet中

Person p = new Person("admin","男",20);
request.setAttribute("p",p);

跳转到某个页面中

<html>
<head></head>
<body>
<%-- 如果不用EL,先获取对象,向下转型 --%>
<% Person p =(Person) request.getAttribute("p");%>
<%-- 如果p为null,会报错,如果name没有赋值,会输出null --%>
<h3>
<%=p.getName()%>;
</h3>
<%--如果使用EL,无需获取对象,无需转型,直接通过保存的对象名.属性名即可--%>
<h3>
${p.name}
</h3>
<%--使用EL输出对象的属性时,该对象必须要有getXX()方法--%>
<%--如果没有在任何作用域中获取到对象p,或对象p没有name属性,不会保存,输出空字符串--
%>
<h3>
${p["name"]}
</h3>
</body>
</html>

2)在页面中获取请求中的参数

用于获取表单提交的数据或超链接?后传递的数据。

使用${param.参数名}替换request.getParameter("参数")。

如有表单或超链接

<form action="page.jsp">
<input type="text" name="username">
<input type="submit">
</form>
<a href="page.jsp?username=admin">跳转</a>

在page.jsp中获取

<html>
<head></head>
<body>
<%-- 传统写法--%>
<% String username = request.getParameter("username");%>
<h3>
<%=username%>;
</h3>
<%--如果使用EL--%>
<h3>
${param.username}
</h3>
</body>
</html>

3)用于获取当前项目上下文(根目录+项目名)路径

如http://localhost:8080/Web03/就是一个项目上下文路径,

在JSP中使用${pageContext.request.contextPath}获取项目上下文路径

<form action="${pageContext.request.contextPath}/servlet映射">
</form>
<a href="${pageContext.request.contextPath}/页面路径">超链接</a>

4、注意

  • web.xml版本在4.0之后,在JSP中使用EL时,默认可以识别。
  • 如果JSP无法识别EL,在指令()中加入 isELIgnored="false"表示不忽略EL。
<%@ page contentType="text/html;charset=UTF-8" language="java"
isELIgnored="false"%>
  • 如果在使用EL过程中,出现PropertyNotFoundException异常,表示未发现指定属性,原因有

    • 缺少指定属性
    • 指定属性没有对应的get方法

(九)JSTL

1、定义

Java Server Page Standarded Tag Library JSP标准标签库

可以使用JSTL中的特定标签,来替换JSP中常见的Java代码。如循环判断等,减少Java代码,提高页面的可读性。

2、使用

1)导入JSTL对应的依赖

https://mvnrepository.com/artifact/javax.servlet/jstl/1.2

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

2)在JSP页面中,加入标签库指令

<%--在当前页面中使用jstl,加入以下指令--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

p.s.这句话可以不写,在使用循环遍历时会自动生成。

3)具体用法

  • 定义变量或给变量赋值
<c:set var="变量名" value="值"></c:set>

<c:set var="num" value="123123"></c:set>
  • if判断
<c:if test="判断条件">
满足条件时的内容
</c:if>

如在servlet中

request.setAttribute("person",new Person("ez","男"));

在Jsp中

<c:if test="${person.sex=='男'}">
<input type="raido" name="sex" checked>男
<input type="raido" name="sex" >女
</c:if>
  • 遍历List集合
<c:forEach items="要遍历的集合" var="遍历出的对象名"></c:forEach>

如servlet中保存了集合

List<BookInfo> list = dao.queryAll();
request.setAttribute("list",list);

在jsp页面中

<%--判断集合为空--%>
<c:if test="${empty list}">
无数据
</c:if>
<c:forEach items="${list}" var="bi">
<tr>
<td>${bi.bookName}</td>
<td>${bi.bookAuthor}</td>
</tr>
</c:forEach>
  • 遍历Map集合
<c:forEach items="要遍历的集合名" var="遍历出的键值对的名称">
${键值对名.key.属性}
${键值对名.value.属性}
</c:forEach>

<%
HashMap<String,String> hm=new HashMap();
hm.put("yyds","永远单身");
hm.put("xswl","吓死我了");
hm.put("pyq","朋友圈");
session.setAttribute("hm",hm);
%>
<c:forEach items="${hm}" var="kv">
<!--遍历键-->
<h3>${kv.key}</h3>
<!--遍历值-->
<h3>${kv.value}</h3>
</c:forEach>

(十)Ajax

1、定义

Asynchronous Javascript And XML 异步JavaScript和XML

一种数据交互方式,请求和响应是异步的。 使用ajax能实现在整个页面不重新加载的情况下,更新局部内容。

2、使用

浏览器都是支持异步提交,原生的JavaScript就能实现ajax,但使用极不方便,所以都是使用jquery封装 后的$.ajax()或$.get() $.post()等函数。

1)在页面中导入jquery文件

<!--使用Ajax,需要导入jquery-->
<script src="jquery文件路径"></script>

2)在script标签中写ajax

<script>
某个节点.事件(function(){
//使用ajax异步提交数据
$.ajax({
//访问的URL地址
url:"servlet映射或具体url",
//提交的数据
data:{
//键:值
"形参":值,
"形参":值
},
//提交方式
type:"get/post/put/delete",
//成功访问URL后的回调函数
success:function(res){//res表示访问URL后返回的数据
},
//访问URL失败时的回调函数
error:function(){
}
});
});
</script>

(十一)JSP内置对象

在jsp页面中有一些对象是已经定义好了可以直接使用的,称为内置对象。

一共有9个内置对象。

  • request 请求作用域对象
  • response 响应对象
  • pageContext 当前页作用域对象
  • session 会话作用域对象
  • page 当前jsp页面对象
  • out 输出对象
  • application 项目作用域对象
  • config 配置对象
  • exception 异常对象

(十二)Session和Cookie

  • 这两个都是用于保存数据的对象。
  • session是一个作用域对象,在servlet中通过request.getSession()获取,在JSP中直接使用内置对象 session获取。
  • cookie是一个对象,也是一个文件,保存在本地。

1、Cookie

cookie通常用于更长时间地保存一些信息,即便关闭浏览器,也能保存。

1)cookie的创建

//创建cookie
Cookie cookie = new Cookie("username", "保存在cookie中的用户名");
//设置有效时长,单位为秒,这里表示7天有效
cookie.setMaxAge(60*60*24*7);
//通过响应对象response保存cookie对象到本地
response.addCookie(cookie);

2)cookie的获取

//读取cookie时是获取当前站点的所有cookie数组
Cookie[] cks = request.getCookies();
//遍历
for(Cookie ck :cks){
System.out.println( ck.getName()+"--"+ck.getValue());
}

2、Session

  • session是一个作用域对象,在访问任意jsp页面时,默认就会创建一个session对象(可以通过设置取消自 动创建)。
  • 通常使用session保存一些信息,用于在同一站点的各个页面之间共享数据。

1)原理

  • 当访问的jsp页面或servlet中使用了session,会创建一个JSESSIONID(session编号),这是一个字 符串,保存在一个cookie中。
  • 再次访问该页面时,会查询该JSESSIONID是否存在,如果存在,直接使用,如果不存在,创建新 的JSESSIONID
  • 保存该JSESSIONID的cookie会随着浏览器的关闭自动销毁,所以关闭浏览器,session就会失效。

 补充:

  • 通常用session保存登录时的用户信息,实现在各个页面中共享信息或防止未登录的情况下访问。
  • 使用session时,会创建一个JSESSIONID,保存在cookie中,在浏览器开启状态下,该JSESSIONID默认 会有30分钟的有效期,
  • 如果在30分钟内没有对session进行操作或关闭浏览器,该cookie就会销毁,对应的session就会失效

2)session对象的常用方法

3)设置全局session有效时长

在指定时间内,打开浏览器但对session无操作,就会自动销毁session。

  • 通过session.setMaxInactiveInterval(int seconds)设置有效秒数
  • 在web.xml中配置
<!--设置全局session配置-->
<session-config>
<!--session有效时长,单位为分钟-->
<session-timeout>15</session-timeout>
</session-config>

3、Session和Cookie对比

  • session中保存的是对象Object,cookie中保存的是字符串String,都以键值对的形式保存
  • session保存在浏览器和服务器端,cookie保存在浏览器
  • session保存的数据没有大小限制,cookie保存的数据有大小限制,不超过3KB
  • session在30分钟内没有访问或随着浏览器的关闭而销毁,cookie可以设置销毁时间

(十三)监听器

对于项目的某个操作进行监听,这个操作可以是创建或销毁application、session,发送请求、得到响应。

用于在执行某个操作时,通过监听器同时再执行其他操作,如记录日志、统计站点人数等。

1、常用的三个监听器接口

ServletContextListener application监听器
HttpSessionListener session监听器
ServletRequestListener request监听器

2、实现一个监听器

  • 创建一个类,实现某个监听器接口
  • 重写某个监听器接口中方法 初始化的方法 销毁的方法
  • 在web.xml中配置监听器或通过注解配置

(十四)过滤器Filter

1、使用

  • 创建一个类,继承HttpFilter
  • 重写其中受保护的doFilter的方法
  • 在web.xml中配置过滤器或使用注解配置

2、在web.xml中配置的话

<!--声明过滤器-->
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.hqyj.filter.MyFilter</filter-class>
</filter>
<!--设置什么请求要经过该过滤器,通常过滤所有请求-->
<filter-mapping>
<filter-name>myFilter</filter-name>
<!--/*表示过滤所有请求-->
<url-pattern>/*</url-pattern>
</filter-mapping>

3、使用@WebFilter("/*")注解配置的话

package com.hqyj.filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* 自定义一个过滤器
* 1.继承HttpFilter
* 2.重写受保护的doFilter方法
* 3.web.xml中配置该过滤器
* */
//@WebFilter("/*")
public class MyFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest req, HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
//由于设置了过滤所有请求,所以在这里设置请求的编码格式
req.setCharacterEncoding("utf-8");
//获取请求的地址后,决定是否放行
String uri = req.getRequestURI();
System.out.println(uri+"试图访问");
//判断地址中是否包含登录页或登录页相关的servlet映射或资源路径
if (uri.contains("login")||
uri.contains("customer")||uri.contains("jquery")) {
//允许放行
chain.doFilter(req,res);
return;
}
//如果登录成功,会在session中保存customer,所以在这里判断session中是否存在
customer,如果存在,放行一切请求
if(req.getSession().getAttribute("customer")==null){
res.sendRedirect("http://localhost:8080/Web03/pages/login.html");
}else{
//允许放行
chain.doFilter(req,res);
}
}
}

(十五)Web项目开发模式

1、Model1

SP+JavaBean模式。

JSP负责渲染数据和处理页面。

JavaBean是一个满足以下条件的类

  • 被public修饰
  • 其中的属性进行封装
    • 用private修饰属性
    • 提供get/set方法
  • 有无参数的构造方法

这种模式,不适合复杂项目的开发。 jsp既要显示内容,又要处理数据,后期维护扩展不方便。

2、Model2(MVC)

MVC模式:模型-视图-控制器模式。

M:Model模型 用于封装数据处理数据,对应业务逻辑类、数据访问类、实体类

V:View视图 用于渲染数据,对应页面(jsp或html)

C:Controller控制器 用户调度用户请求,对应servlet

这种模式适合复杂项目的开发。 每个模块各司其职,耦合性低。 对于后期维护和扩展较为方便。

华清远见-重庆中心-数据库阶段技术总结/知识点梳理/个人总结/面试题解析相关推荐

  1. 华清远见-重庆中心-数据库阶段技术总结/知识点梳理/个人总结/关于JavaWeb技术的解析(看法)

    JavaWeb 使用Java开发Web服务的技术,统称为JavaWeb. B/S与C/S模式 B/S:Browser/Server 浏览器/服务器模式 用户只需要一个浏览器即可访问服务器 C/S:Cl ...

  2. 华清远见-重庆中心-数据库阶段技术总结/个人总结

    数据的基本概念 Data数据 任何描述事物的文字和符号的都可以称为数据. (软件开发就是为了收集数据,从中筛选出有用的信息.) Infomation信息 数据经过处理之后得到的内容称为信息. 保存数据 ...

  3. 华清远见-重庆中心-数据库阶段技术总结

    JavaWeb 使用Java开发Web服务的技术,统称为JavaWeb. B/S与C/S模式 B/S:Browser/Server 浏览器/服务器模式 用户只需要一个浏览器即可访问服务器 C/S:Cl ...

  4. 华清远见-重庆中心-数据库阶段技术总结/知识点梳理/个人总结

    文章目录 前端.后端.数据库 数据和信息 数据库 数据库管理系统 总结 常见的数据库管理系统 关系型数据库 非关系型数据库 MySQL8.x的安装和使用 1.下载 2.卸载 3.安装 MySQL控制台 ...

  5. 华清远见-重庆中心-数据库阶段技术总结:

    绝对路径 <a href="localhost:8080/system/pages/hello.html">跳转</a> 相对路径问题 / 表示从根目录(域 ...

  6. 华清远见-重庆中心-数据库阶段整理

    文章目录 Day1 数据和信息 数据库 数据库管理系统 总结 常见的数据库管理系统 关系型数据库 非关系型数据库 MySQL控制台常用命令 数据库管理系统图形化管理工具 修改数据表 SQL 操作数据库 ...

  7. 华清远见-重庆中心-框架阶段技术总结/知识点梳理

    文章目录 华清远见-重庆中心-框架阶段技术总结/知识点梳理/个人总结 框架 Java主流框架 Spring 概念 组成 名词解释 IOC DI Spring控制台应用 1.创建一个普通的Maven项目 ...

  8. 华清远见-重庆中心-前端阶段技术总结

    华清远见-重庆中心-前端阶段技术总结 HTML Hyper Text Markup Language 超文本标记语言 超文本:超级文本/超链接文本,超越了文本的限制,如多媒体文件.超链接等. 标记:也 ...

  9. 华清远见-重庆中心-框架阶段技术总结

    框架 一套规范. 实际是他人实现的一系列接口和类的集合.通入导入对应框架的jar文件(maven项目导入对应的依赖),进行适当的配置,就能使用其中的所有内容. 开发者可以省去很多模板代码,如dao中的 ...

最新文章

  1. 信而泰推出100G多速率测试模块:填补中国通信产业链短板
  2. html video标签问题,用HTML5 video标签的一系列问题
  3. Android 线性布局(LinearLayout)相关官方文档 - 布局參数部分
  4. IAR环境下STM32+IAP方案的实现(转)
  5. SQL Server 装载 msxmlsql.dll 失败的解决办法
  6. SQL Server2000 未公开的存储过程
  7. Bootstrap4+MySQL前后端综合实训-Day10-AM【实训汇报-下午返校、项目代码(7个包+7个Html页面)】
  8. Python编程专属骚技巧2
  9. [html] 写一个水平竖直居中的弹窗,带遮罩层的布局
  10. LeetCode 389. Find the Difference
  11. [转] 应聘Java笔试时可能出现问题及其答案(第五部分)
  12. 需要用sq语句 修改大批量用户的密码_网站文章seo优化及修改已收录文章建议
  13. 反序列化对象列表发生异常_Apache Thrift系列详解:序列化机制
  14. CCRD_TOC_2008年第4期
  15. jieba(结巴)—— Python 中文分词
  16. 苏宁易购关键词搜索商品方法
  17. 软件工程:数据流图和结构图怎么画?
  18. 我在飞机上,飞机在哪里?浅谈飞行模式与GPS定位
  19. Shiro框架Given final block not properly padded问题解决
  20. 项目经理如何处理中途接手的项目

热门文章

  1. 2014全球可穿戴设备产业链报告分析
  2. ABLIC推出车载用S-19914/5系列低EMI超小型降压开关稳压器,可将传导噪音降至原先水平的1/3
  3. 凯斯西储大学轴承故障数据集解读(新手版)
  4. 如何在Linux中查看mac地址
  5. IM3、IIP3、OIP3等的计算
  6. webAPI第一弹---JS
  7. 大屏超清双摄强机,OPPO R11 Plus开启0元预约
  8. 数影周报:据传国内45亿条快递数据泄露,聆心智能完成Pre-A轮融资
  9. vxWorks PCIE控制器驱动解读
  10. DALI生产测试工具说明书