初识Servlet
Servlet是一种服务器端的Java应用程序,只有当一个服务器端的程序使用了Servlet API的时候,这个服务端的程序才能称之为Servlet。
Servlet本身不做任何业务处理,只是接收请求并决定调用哪个JavaBean去处理请求,确定用哪个页面来显示处理返回的数据
Servlet的工作模式
-
客户端发送请求至服务器
-
服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
-
服务器将响应返回客户端
JSP与Servlet之间的关系
Servlet API
1.实现Servlet接口
javax.servlet.Servlet接口:所有Java Servlet的基础接口类,规定了必须由Servlet具体类实现的方法集
2.继承GenericServlet类
javax.servlet.GenericServlet类:是Servlet的通用版本,是一种与协议无关的Servlet
3.继承HttpServlet类
javax.servlet.http.HttpServlet类:在GenericServlet基础上扩展的基于Http协议的Servlet
Servlet的使用
Servlet接口中定义的主要方法
-
init():Servlet的初始化方法,仅仅会执行一次
-
service():处理请求和生成响应
-
destroy():在服务器停止并且程序中的Servlet对象不再使用的时候调用,只执行一次
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
init( )、service( )、destroy( )是Servlet生命周期的方法,代表了Servlet从出生到工作再到死亡的过程。
Servlet生命周期各个阶段
-
加载和实例化
-
初始化
-
处理请求
-
销毁
生命周期 | 谁来做 | 何时做 |
---|---|---|
实例化 | Servlet 容器 | 当Servlet容器启动或者容器检测到客户端请求时 |
初始化 | Servlet 容器 | 实例化后,容器调用Servlet的init()初始化对象 |
处理请求 | Servlet 容器 | 得到客户端请求并做出处理时 |
销毁 | Servlet 容器 | 当程序中的Servlet对象不再使用的时候,或者Web服务器停止运行的时候 |
ServletRequest
-
封装客户的请求信息
-
作用相当于JSP内置对象request
public interface ServletRequest {
int getContentLength();//返回请求主体的字节数
String getContentType();//返回主体的MIME类型
String getParameter(String var1);//返回请求参数的值
}
ServletResponse
-
创建响应信息,将处理结果返回给客户端
-
作用相当于JSP内置对象
responseServletConfig
-
包含了Servlet的初始化参数信息
部署运行Servlet
配置Servlet:
配置<servlet>元素:把Servlet内部名映射到一个Servlet类名
<servlet>
<servlet-name>UserLogin</servlet-name>
<servlet-class>com.mhl.servlet.UserLoginServlet</servlet-class>
</servlet>
配置<servlet-mapping>元素:把用户访问的URL映射到Servlet的内部名
<servlet-mapping>
<servlet-name>myServlet3</servlet-name>
<url-pattern>/myServlet3</url-pattern>
</servlet-mapping>
注意:<servlet-mapping>与<servlet>中的<servlet-name>必须一致
初始化参数设置:
配置<init-param>元素:修改字符编码为utf-8
<servlet>
……
<init-param>
<param-name>charSet</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
使用继承HttpServlet创建servlet类:
public class UserLoginServlet extends HttpServlet {
String charSetContent = null;
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("这是init");
charSetContent = config.getInitParameter("charSetContent");
super.init();
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是service");
super.service(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是doGet");
req.setCharacterEncoding(charSetContent);
String name =req.getParameter("name");
System.out.println("name==" + name);
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是doPost");
super.doPost(req, resp);
}
@Override
public void destroy() {
super.destroy();
}
}
过滤器
-
过滤器是向Web应用程序的请求和响应添加功能的Web服务组件
-
过滤器可以统一地集中处理请求和响应
-
使用过滤器技术实现对请求数据的过滤
过滤器原理
使用过滤器时,过滤器会对游览器的请求进行过滤,过滤器可以动态的分为3个部分,1.放行之前的代码,2.放行,3.放行后的代码,这3个部分分别会发挥不同作用。
-
第一部分代码会对游览器请求进行第一次过滤,然后继续执行
-
第二部分代码就是将游览器请求放行,如果还有过滤器,那么就继续交给下一个过滤器
-
第三部分代码就是对返回的Web资源再次进行过滤处理
过滤器的使用步骤
建立实现javax.servlet.Filter接口的类,实现过滤行为
doFilter(...) {
//过滤请求
chain.doFilter(request, response); //调用下一个过滤器或Web资源
//过滤响应
}
在web.xml中配置过滤器
<filter>
<filter-name>过滤器名</filter-name>
<filter-class>过滤器的完全限定名</filter-class>
</filter>
<filter-mapping>
<filter-name>过滤器名</filter-name>
<url-pattern>过滤器映射的Web资源</url-pattern>
</filter-mapping>
过滤器的生命周期
-
初始化:init()
-
过滤:doFilter()
-
销毁:destroy()
初始化参数:
1.配置<init-param>元素
<filter>
<init-param>
<param-name>Encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
2.读取过滤器的初始化参数
init(FilterConfig fConfig) {
String encoding=fConfig.getInitParameter("Encoding");
}
多个过滤器会形成过滤器链,根据过滤器的配置,按照先后顺序执行。
如果没有配置,则按照过滤器名称的字符a-z顺序执行。
过滤器将所有的接收字符串转换为utf-8类型示例如下:
@WebFilter("/api/*")
public class SetCharacter implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("this is init");
}
public void destroy() {
System.out.println("this is destroy");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//放行
chain.doFilter(request, response);
}
}
WebFilter("/*")表示对所有请求进行过滤。
完全匹配:/index.jsp 目录匹配:/admin/* 扩展名匹配:*.do 全部匹配:/*
request.setCharacterEncoding("utf-8")
在放行前,对所有的request请求进行字符串类型转换。
登录过滤示例:(注意登录的jsp页面和servlet种无需进行过滤)
@WebFilter(urlPatterns = {"/api/*","/pages/*"})
public class LoginFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request1 = (HttpServletRequest) request;
HttpSession session = request1.getSession();
HttpServletResponse response1 = (HttpServletResponse) response;
if(session.getAttribute("user")!=null){
//放行
chain.doFilter(request, response);
}else {
response1.sendRedirect("/login.jsp");
}
}
public void destroy() {
}
}
注意:request和response要强转为HttpServlet的。当获取用户为空时,重定向到登录页面。
过滤器的应用场合
-
对请求和响应进行统一处理
-
对请求进行日志记录和审核
-
对数据进行屏蔽和替换
-
对数据进行加密和解密
EL与JSTL
EL表达式优化页面,JSTL标签优化页面
EL表达式
<table >
<c:forEach var="news" items="${list}">
<tr><td><c:out value="${news.title}" /></td></tr> </c:forEach>
</table>
语法:${表达式} 例如:${username}
<body>
<%
request.setAttribute("key","值");
%>
表达式脚本输出 key 的值是:
<%=request.getAttribute("key1")==null?"":request.getAttribute("key1")%><br/>
EL 表达式输出 key 的值是:${key1}
</body>
EL操作符
操作符“.”
-
获取对象的属性,例如:${news.title}
操作符“[]”
-
获取对象的属性,例如:${news["title"]}
-
获取数组或集合中的对象,例如:${newsList[0]}
EL运算符
运算符 | 说明 |
---|---|
( ) | 改变执行的优先级,例如${3(4+5)} |
+,-,*,/,% | 算术运算符,例如${3+2} |
==,!=,>,>=,<,<= | 关系运算符,例如${a==b}或${a eq b} |
&&,||,! | 逻辑运算符,例如${true&&false} |
?: | 条件运算符,例如${a>b?1:2} |
empty | 用于检测变量名是否为空,是否等于NULL,例如${empty name} |
为了避免JSP混淆运算符和页面关键字,有替代写法:
关系运算符 | 范例 | 结果 |
---|---|---|
== 或 eq | ${5 == 5}或${5 eq 5} | true |
!= 或 ne | ${5 != 5}或${5 ne 5} | false |
< 或 lt | ${3 < 5}或${3 lt 5} | true |
> 或 gt | ${3 > 5}或{3 gt 5} | false |
<= 或 le | ${3 <= 5}或${3 le 5} | true |
>= 或 ge | ${3 >= 5}或${3 ge 5} | false |
EL功能
-
取得JavaBean对象的属性
${news.title}
-
取得数组、List、Map类型对象的元素
${list[0]}
-
使用各类运算符对原始数据进行简单处理
${totalRecordCount/pageSize}
-
屏蔽一些常见的异常
${username}
-
能实现简单的自动类型转换
${news}相当于(News)request.getAttribute("news")
EL访问作用域
request.setAttribute("news", news);
两种方式取数据:
使用Java小脚本:request.getAttribute("news");
使用EL表达式: ${ news } 或者 ${ requestScope.news }
作用域 | JAVA代码取值 | EL取值 |
---|---|---|
请求作用域 | request.getAttribute("news"); | ${ requestScope.news } |
会话作用域 | session.getAttribute("username"); | ${ sessionScope.username } |
程序作用域 | application.getAttribute("count"); | ${ applicationScope.count } |
页面作用域 | pageContext.getAttribute("userNum"); | ${ pageScope.userNum } |
表达式搜索域数据的顺序
当四个域中都有相同的 key 的数据的时候,EL 表达式会按照四个域的从小到大的顺序去进行搜索
jsp页面:
<body>
<%
//往四个域中都保存了相同的 key 的数据。
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
pageContext.setAttribute("key", "pageContext");
%>
${ key }
</body>
servlet:
//传一般字符串(此处使用request传递)
String username = "zhangsan";
request.setAttribute("zhangsan",username);
//传对象(此处使用session传递)
Provider pro = new Provider();
pro.setProName("lisi_te");
request.getSession().setAttribute("lisi_te",pro);
//传集合(此处使用application传递)
List<Provider> list = new ArrayList<>();
Provider provider = new Provider();
provider.setProName("ww");
list.add(provider);
this.getServletContext().setAttribute("ww",list);
JSTL表达式
实现JSP页面中的逻辑控制
使用步骤
1.下载jstl.jar和standard.jar包
Index of /dist/jakarta/taglibs/standard/binaries
2.将这两个包复制到WEB-INF\lib目录
3.在JSP页面中添加指令
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
JSTL标签
标签库
标签库名称 | 资源标示符(URI) | 前缀 |
---|---|---|
核心标签库 | Oracle Java Technologies | Oracle | c |
国际化/格式化标签库 | Oracle Java Technologies | Oracle | fmt |
XML标签库 | Oracle Java Technologies | Oracle | x |
数据库标签库 | Oracle Java Technologies | Oracle | sql |
函数标签库 | Oracle Java Technologies | Oracle | fn |
核心标签库
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
国际化/格式化标签库
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
标签
<c:out/>标签
<c:out value="value" default="default" escapeXml="true|false "/>
value:需要输出显示的表达式
default:默认输出显示的值
escapeXml:是否对输出的内容进行转义
<c:set/>标签
作用:set 标签可以往域中保存数据 域对象.setAttribute(key,value); scope 属性设置保存到哪个域 page 表示 PageContext 域(默认值) request 表示 Request 域 session 表示 Session 域 application 表示 ServletContext 域 var 属性设置 key 是多少 value 属性设置值
<c:set var="name" value= "value" scope="域" />
保存之前:${ sessionScope.abc } <br>
<c:set scope="session" var="abc" value="abcValue"/>
保存之后:${ sessionScope.abc } <br>
<c:forEach/>标签
迭代标签,实现对集合的遍历
<c:forEach var="varName" items="items" varStatus="varStatus">
……
</c:forEach>
varName:集合中元素的名称
items:集合对象
varStatus:当前循环的状态信息,例如循环的索引号
for (int i = 1; i < 10; i++)
<table border="1">
<c:forEach begin="1" end="10" var="i">
<tr>
<td>第${i}行</td>
</tr>
</c:forEach>
</table>
begin 属性设置开始的索引
end 属性设置结束的索引
var 属性表示循环的变量(也是当前正在遍历到的数据)
<c:if/>标签
if 标签用来做 if 判断。 test 属性表示判断的条件(使用 EL 表达式输出)
<c:if test="condition" var="varName" scope="scope">
……
</c:if>
<c:if test="${ 12 == 12 }">
<h1>12 等于 12</h1>
</c:if>
<c:if test="${ 12 != 12 }">
<h1>12 不等于 12</h1>
</c:if>
varName:判断的结果
scope:判断结果存放的作用域
<c:url/>超链接标签
<c:url value="url" />
<c:param/>参数标签
<c:param name="name" value="value"/>
<c:import/>导入标签
<c:import url="URL" />
<fmt:formatDate/>格式化标签
实现格式化的日期和时间显示
<fmt:formatDate value="date" pattern="yyyy-MM-dd HH:mm:ss"/>
标签名称 | 作用 |
---|---|
<c:out /> | 输出文本内容到out对象,常用于显示特殊字符 |
<c:set/> | 在作用域中设置变量或对象属性的值 |
<c:remove/> | 在作用域中移除变量的值 |
<c:if/> | 实现条件判断结构 |
<c:forEach/> | 实现循环结构 |
<c:url/> | 构造url地址 |
<c:param/> | 在url后附加参数 |
<c:import/> | 在页面中嵌入另一个资源内容 |
<fmt:formatDate/> | 格式化时间 |
<fmt:formatNumber/> | 格式化数字 |
分页查询
每次翻页的时候只从数据库里检索出本页需要的数据
步骤
-
计算显示数据的总数量
-
确定每页显示的数据量
-
计算显示的页数
页数=总数量/每页显示的数据量[+1]
-
编写分页查询SQL语句
-
实现分页查询
关键点
页数:总记录数/每页显示的记录数
整除:总页数=总记录数/每页显示记录数
不能整除:总页数=总记录数/每页显示记录数+1
编写分页查询SQL语句(limit)
select * from tableName where 查询条件
limit (当前页码-1)*页面容量, 页面容量
分页显示
-
确定当前页
-
设置首页、上一页、下一页、末页的页码
还要对可能出现的异常进行控制
-
首页与末页的控制
limit count(*) from smbms;
查找一共条数
-- 分页查询语法 -- 参数1:起始索引=(页码 - 1)*每页展示记录数 -- 参数2:查询返回记录数 = 每页展示记录数 select * from student limit 0,5; -- 查询第一页数据,每页展示5条数据 select * from student limit 0,5; -- 查询第二页数据,每页展示5条数据 select * from student limit 5,5; -- 查询第三页数据,每页展示5条数据 select * from student limit 10,5
已经读到这里了,大佬点点关注喵~