Servlet进阶

1.Servlet与表单

  • Servlet获取表单的请求的参数有两种方式:
(1) String name =  request.getParameter("name");

(2)  String[] hobbies = request.getParameterValues("hobby");

2.get和post请求方式的区别

Get与POST --- HTTP协议中的两种发送请求的方法,是向服务器提交数据有两种方式

  1. 功能差异:
    Get: 一般用于获取/查询资源信息
    Post: 一般用于发送/更新资源信息

  2. 长度限制差异
    Get:请求长度最多1024kb,post对请求数据没有限制

  3. 安全性差异
    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

  1. 什么是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访问器    
  1. jsp页面中关于EL的禁用
<%@ page isELIgnored="true" %>

默认为false
  1. 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运算符:  判空 
  1. EL中隐式对象
    在El表达式中可以直接使用的对象,共有11个
(1) 与作用域范围有关   pageScope,requestScope,sessionScope,applicationScope
(2) 与输入有关 param ,paramValues
      与param等同的代码:String request.getParameter();
      paramValues  : String[] request.getParameterValues()

6-2 JSTL

  1. 什么是JSTL
J - JSP [java server page]
S - standard  标准
T  - tag  标签
L - library 库

  |-JSP标准标签库
每个标签都是一段Java代码的实现
在web开发中,有许多功能都是开发人员经常要用到的,JSTL就是定义的一套标准的标签库.
	JSTL的目标是为了简化jsp页面的设计,为页面设计人员和程序开发人员的分工协作提供了便利
  1. JSTL分类
JSTL core 核心标签库  
       |-重点

JSTL fmt  格式化标签-[国际化]
JSTL sql 访问数据库标签  - 适用于小微型项目
JSTL XML 操作XML文档
JSTL functions 工具函数
  1. 核心标签库的分类
通用标签
  |- 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="张三" />
  1. 通用标签
<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}
  1. 条件标签
<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>
  1. 迭代标签
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>
posted @   TerrenceGee  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示