Servlet进阶
1.Servlet与表单
- Servlet获取表单的请求的参数有两种方式:
(1) String name = request.getParameter("name");
(2) String[] hobbies = request.getParameterValues("hobby");
2.get和post请求方式的区别
Get与POST --- HTTP协议中的两种发送请求的方法,是向服务器提交数据有两种方式
-
功能差异:
Get: 一般用于获取/查询资源信息
Post: 一般用于发送/更新资源信息 -
长度限制差异
Get:请求长度最多1024kb,post对请求数据没有限制 -
安全性差异
get提交的数据是明文显示慧URL上的,格式为:
hello?name=张三&age=24&hobby=音乐&hobby=学习
不适合提交敏感数据
post 在浏览器后台递交服务器,数据不显示,相对安全一些
补充细节:
如果表单为get方式请求,则action="hello?opr=goto" 附带的参数opr为null
但是,如果表单为post方式请求,则action="hello?opr=goto" 附带的参数opr可以获取到
不过,建议统一使用隐藏文本域来传递附带参数
<form action="hello" method="get">
<%--隐藏文本域--%>
<input type="hidden" name="opr" value="goto" />
...
</form>
3.页面的跳转
在Servlet处理完请求后,在输出响应时,可以直接进行页面的跳转,可以避免使用PrintWriter对象输出HTML文本标签信息.
- 跳转方式有两种:
(1)服务器端跳转 --别名: 请求转发
//获取请求分发器,与页面绑定
RequestDispatcher dispatcher = request.getRequestDispatcher("/show.jsp");
//使用请求分发器调用方法forward()进行跳转
dispatcher.forward(request,response);
一般一行代码:
request.getRequestDispatcher("/show.jsp").forward(request,response);
(2)客户端跳转 --别名: 请求重定向Redirect
//客户端跳转 -因为是通过客户端请求进行跳转,所以不能使用/开头,否则会转到localhost/show.jsp,即使用相对路径
response.sendRedirect("show.jsp");
- 两种跳转的区别:
(1) 地址栏区别:
请求转发地址栏依然显示的是请求servlet的url-pattern
重定向地址栏依然显示的是请求重定向跳转之后的页面的地址
(2) 请求转发到的页面中可以共享请求作用域中的数据
重定向到的页面中不能共享请求作用域数据
(3) 请求转发只能在当前 web应用内部进行转发
重定向跳转的页面不受限制(可以跳到baidu)
(4) 应用场合:
请求转发 --用户登录系统后,进行内部模块之间转发
重定向 --用户注销,退出系统时,回到首页,或跳转至外部其他的网站时使用
4.Servlet生命周期
- servlet的生命周期由servlet容器控制(如: Tomcat)控制
构建 --构造方法
初始化 --init()
服务 -- service()
|- 根据请求的方式调用doGet()或 doPost()
销毁 -- destroy()
- 自定义的servlet类的继承体系
<<javax.servlet.Servlet>>接口 --关于生命周期的方法声明
|
javax.servlet.GenericServlet 抽象类
|
javax.servlet.http.HttpServlet - 抽象类
|
自定义 Servlet类 - 重定doGet()与doPost()
- servlet的工作方式是单例多线程设计的
//关键:loadOnStartup属性,
//loadOnStartup 指定在Tomcat服务器启动时就会创建Servlet实例并调用初始化init()方法
@WebServlet(value="/life",loadOnStartup=1)
public class LifeCycleServlet extends HttpServlet {
public LifeCycleServlet() {
System.out.println("1.构造器执行了....");
}
@Override
public void init() throws ServletException {
System.out.println("2.初始化init()...");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("3.服务service()....");
super.service(req,resp); //调用父类被重写的service()
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost()执行了....");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet()执行了....");
}
@Override
public void destroy() {
System.out.println("4.销毁destroy().....");
}
}
Servlet生命周期小结
当第一次开始调用某个Servlet的时候,系统就会为它创建一个实例,然后调用init()方法,主要是进行对该Servlet的一些初始化,如果此时服务器中已存在了这个实例,那么就省去了第一步的过程,直接使用该实例,只不过会创建一个新的线程,每一个线程在创建的同时会调用service()方法来根据用户的请求类型决定调用doGet()或doPost()或是其它方法进行处理,当所有的工作都做完,Servlet需要被从服务器中删除的时候,服务器则会调用destory()方法进行一些清理工作,如释放数据库连接,关闭打开的文件等等,之后将实例删除。
5.理解作用域
- 作用域:Scope
变量,对象起作用的范围
Servlet和JSP组件都能访问作用域:来自服务器管理内存中的一段空间
- 不管哪个作用域,操作作用域方法
void setAttribute("name",Object);
Object getAttribute("name");
void removeAttribute("name");
5-1 Servlet环境下的作用域
请求作用域 -- 仅在一次请求过程中有效
会话作用域 -- 包含多次请求与响应都能访问,不同会话之间不能共享
全局作用域 -- 服务器一次启动有效,多个会话可以共享
- 示例代码
@WebServlet("/scope")
public class ScopeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
request.setAttribute("req_name","request数据");
//获取会话对象
HttpSession session = request.getSession();
session.setAttribute("ses_name","session数据");
//全局作用域
//获取全局对象--ServletContext Servlet上下文对象 --代表当前整个web应用程序
ServletContext ctx = request.getServletContext();
System.out.println(session.getServletContext() == request.getServletContext());
ctx.setAttribute("ctx_name","ServletContext全局数据");
request.getRequestDispatcher("/scope.jsp").forward(request,response);
}
}
jsp页面,显示作用域:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>这是scope.jsp</h2>
访问作用域:<hr>
请求作用域:<%=request.getAttribute("req_name")%><br>
会话作用域:<%=session.getAttribute("ses_name")%><br>
全局作用域:<%=application.getAttribute("ctx_name")%><br>
</body>
</html>
5-2 JSP下的作用域
共有四个作用域:
pageContext 页的上下文 -代表当前jsp页面 --仅在当前页面中可以访问
request 请求作用域 --仅在一次请求过程中有效
session 会话作用域 --包含多次请求与响应都能访问,不同会话之间不能共享
appication 全局作用域 --服务器一次启动有效,多个会话可以共享
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>这是scope.jsp</h2>
<%
pageContext.setAttribute("page_name","pageContext数据");
request.setAttribute("req_name","request数据");
session.setAttribute("ses_name","session数据");
application.setAttribute("ctx_name","application全局数据");
%>
<a href="scope02.jsp">请求scope02.jsp</a>
<%--<%--%>
<%-- //请求转发--%>
<%-- request.getRequestDispatcher("/scope02.jsp").forward(request,response);--%>
<%--%>--%>
</body>
</html>
---------------------------------------------------------
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2> 这是scope02.jsp</h2>
访问作用域:<hr>
页面作用域:<%=pageContext.getAttribute("page_name")%><br>
请求作用域:<%=request.getAttribute("req_name")%><br>
会话作用域:<%=session.getAttribute("ses_name")%><br>
全局作用域:<%=application.getAttribute("ctx_name")%><br>
</body>
</html>
6.EL与JSTL
其作用:取代jsp页面中的脚本元素
6-1 EL
- 什么是EL
EL - Expression Language 表达式语言
其作用是: 可以简化对变量或对象的访问
主要用于取代: 脚本元素中的表达式 <%=%>
EL表达式的语法:
${变量或对象}
注意:访问变量或对象必须是存放于四种作用域中的一种
示例:
<body>
<%
String name = "张三";
pageContext.setAttribute("name",name);
request.setAttribute("name","李四");
session.setAttribute("name","王五");
application.setAttribute("name","刘六");
%>
姓名: ${applicationScope.name} <br>
</body>
注意:如果EL访问时没有指定作用域范围, 则默认会从小至大范围进行搜索该名字,先到为止
pageScope --> requestScope -->sessionScope -->applicationScope
2. 表达式使用的情形
可用输出静态文本
EL与JSTL一起配合使用
EL不能在脚本元素中使用.
EL中如果访问对象属性值--${对象.属性} 注意区分大小写
|- 原理是getter访问器
- jsp页面中关于EL的禁用
<%@ page isELIgnored="true" %>
默认为false
- EL中的运算符
(1)EL中的算术运算:${3+"8"} --自动转换为数字
+,-,*,
/ 或 div
% 或 mod
(2)关系运算符:
> 或 gt great than
< 或 lt less than
>= 或 ge great equal
<= 或 le
== 或 eq equals
!= 或 ne not equals
逻辑运算:
&& || !
或
and or not
empty运算符: 判空
- EL中隐式对象
在El表达式中可以直接使用的对象,共有11个
(1) 与作用域范围有关 pageScope,requestScope,sessionScope,applicationScope
(2) 与输入有关 param ,paramValues
与param等同的代码:String request.getParameter();
paramValues : String[] request.getParameterValues()
6-2 JSTL
- 什么是JSTL
J - JSP [java server page]
S - standard 标准
T - tag 标签
L - library 库
|-JSP标准标签库
每个标签都是一段Java代码的实现
在web开发中,有许多功能都是开发人员经常要用到的,JSTL就是定义的一套标准的标签库.
JSTL的目标是为了简化jsp页面的设计,为页面设计人员和程序开发人员的分工协作提供了便利
- JSTL分类
JSTL core 核心标签库
|-重点
JSTL fmt 格式化标签-[国际化]
JSTL sql 访问数据库标签 - 适用于小微型项目
JSTL XML 操作XML文档
JSTL functions 工具函数
- 核心标签库的分类
通用标签
|- set,out,remove,catch
条件标签
|-if
|-choose 互斥条件
when
when
otherwise
迭代标签
|-forEach -- >增强for
|-forTokens
JSTL使用步骤:
步骤1:添加jstl.jar文件 pom.xml依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
步骤2: 在需要使用的页面中使用指令引入jstl
<%--引入jstl标签库--%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
步骤3:引用标签库中的标签
<c:set var="name" value="张三" />
- 通用标签
<c:set var="name" value="张三" />
<%
//等价Java代码
pageContext.setAttribute("name","张三");
%>
<c:out value="${pageScope.name1}" default="佚名"/>
<c:catch var="e">
<%
int i=3/0;
%>
</c:catch>
<br>
出错了:${e.message}
- 条件标签
<c:if test="${3 lt 5}">
真
</c:if>
<hr>
<c:choose>
<c:when test="${ param.score ge 90 }">
优
</c:when>
<c:when test="${ param.score ge 80 }">
良
</c:when>
<c:when test="${ param.score ge 70 }">
中
</c:when>
<c:when test="${ param.score ge 60 }">
及格
</c:when>
<c:otherwise>
差
</c:otherwise>
</c:choose>
- 迭代标签
forEach属性说明:
var –单个变量的名
items – 作用域中的集合或数组对象
begin -起始下标
end -截止下标
step –步长 默认为1
varStatus – 当前取出单个变量的状态信息.
|_ index -- 下标从0开始
Count -- 从1 开始计数
first --当前取出的变量是否是第一个,如果是则为true
last --当前取出的变量是否是最后一个,如果是则为true
<%
String[] arr = {"aaa","bbb","ccc","ddd","eee"};
request.setAttribute("arr",arr);
//for(String s : arr){}
%>
<c:forEach var="s" items="${arr}" varStatus="vs">
${vs.index} - ${vs.count} : ${s} - ${vs.first} - ${vs.last}<br>
</c:forEach>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~