Servlet & JSP & Filter

时间:2019-09-27
本文章向大家介绍Servlet & JSP & Filter,主要包括Servlet & JSP & Filter使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Servlet & JSP & Filter

graph TB B[Servlet] C[JSP] B --> D[基本原理与执行流程<br>init/service/do.] B --> H[service&反射] B --> I[单例] C --> E[隐式对象] C --> F[JSTL&EL] C --> G[session<br>JavaBean]

Servlet

Servlet 是运行在服务器端的一个对象,web 服务器(如 Tomcat)会根据用户的访问链接将请求路由到不同的 Servlet 中并由其处理与返回响应,路由配置一般在 web.xml 中,当然也可以使用注解的形式。

特点

  • 单例
  • Servlet 请求时实例化与初始化

基本原理

下面是 HTML & servlet & web.xml 的一个示例

HTML(注意 action 和 method 的取值):

...
<form action="login" method="post">
账号: <input type="text" name="name"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit" value="登录">
</form>
...

web.xml(注意 Servlet 和 url 路径的映射关系):

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>LoginServlet</servlet-class>
        <load-on-startup>10</load-on-startup> 
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>  
</web-app>

Servlet:

public class LoginServlet extends HttpServlet{
    // @Override // 当前函数的作用见下
    // public void service(HttpServletRequest request, HttpServletResponse response){...}
    // public void init(ServletConfig config) {...} // 继承于父类,Servlet 的构造函数执行后会自动执行此函数,只会执行一次
 	// 处理 GET 请求
    public void doGet(HttpServletRequest request, HttpServletResponse response){
        try {
            response.getWriter().println("<h1>Hello Servlet!</h1>");
            response.getWriter().println(new Date().toLocaleString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 处理 POST 请求
    public void doPost(HttpServletRequest request, HttpServletResponse response){
        try{
            String name = request.getParameter("name");
        	String password = request.getParameter("password");
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}

每一个 Servlet 都需要继承 HttpServlet。HttpServlet 中有一个 service 成员函数,默认的 service 会判断请求中的方法,并根据方法(GET or POST)来调用当前函数下的 doGet 或者 doPost 方法。结合 Filter & 重写service & 反射可以实现一个 servlet 处理不同的请求,如下所示:

使用 Filter 拆分用户的请求,下面代码截取自一段 Filter 对象:

// 假设请求的方法是 ***/admin_category_list
if(uri.startsWith("/admin_")){		
	String servletPath = StringUtils.substringBetween(uri,"_", "_") + "Servlet"; // 确定 Servlet
	String method = StringUtils.substringAfterLast(uri,"_" );
	request.setAttribute("method", method); // 确定方法
	req.getRequestDispatcher("/" + servletPath).forward(request, response); // 执行 Servlet
	return;
}

重写 service 函数并使用反射选择与执行 Servlet 中的方法(此时不需要 doGet 和 doPost):

@Override
public void service(HttpServletRequest request, HttpServletResponse response) {
    ...
    try {
        /*借助反射,调用对应的方法*/
        String method = (String) request.getAttribute("method");
        Method m = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class,
                                             javax.servlet.http.HttpServletResponse.class,Page.class);
        String redirect = m.invoke(this,request, response,page).toString();
    }
    ...
}

常见方法

  • 跳转
    • 服务端跳转(返回跳转响应内容但不改变浏览器地址):request.getRequestDispatcher("success.html").forward(request, response);
    • 客户端跳转(服务端向客户端发送重定向地址):response.sendRedirect("fail.html");
  • Servlet 自启动
    • 在 web.xml 中配置 <load-on-startup>10</load-on-startup> ,可以实现 Servlet 的自启动

JSP

JSP,一个可以直接在类 HTML 中写 Java 代码的技术,JSP 最终将会被翻译为 Servlet 。JSP 继承于 HttpJspBase,而后者继承自 HttpServlet。

JSP 示例

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
<%
    List<String> words = new ArrayList<String>();
    words.add("today");
    words.add("is");
    words.add("great");
%>
<table width="200px" align="center" border="1" cellspacing="0">
<%for (String word : words) {%>
<tr>
    <td><%=word%></td>
</tr>
<%}%>
</table>

网页中输出如下:

today
is
great

JSP 组成

JSP 由这些页面元素组成:

  1. 静态内容,html、css、javascript 等内容
  2. 指令,以<%@开始 %> 结尾,比如 <%@page import="java.util.*"%>
  3. 表达式 <%=%>,用于输出一段html,<%="hello jsp"%> 类似于 <%out.println("hello jsp");%>
  4. Scriptlet,在 <%%> 之间,可以写任何 java 代码
  5. 声明,在<%!%> 之间可以声明字段或者方法。但是不建议这么做。
  6. 动作,<jsp:include page="Filename" >jsp 页面中包含另一个页面。
  7. 注释 <%-- -- %>,不同于 html 的注释<!-- --> 通过 jsp 的注释,浏览器也看不到相应的代码,相当于在servlet中注释掉了

隐式对象

不需要显式定义就可以使用的对象。JSP 一共有 9 个隐式对象,分别为:

  • request、response、out,out 为输出
  • pageContext、session、application,分别代表当前页,会话,全局作用域对象
  • JSP 会被编译为一个 Servlet 类 ,运行的时候是一个 Servlet 实例。 page 即代表this
  • config,config 可以获取一些在 web.xml 中初始化的参数
  • exception,异常对象,指定的异常处理页面才可使用

JSTL

JSTL JSP Standard Tag Library,JSTL允许开人员可以像使用 HTML 标签那样在 JSP 中开发 Java 功能。

常见函数标签:fmt、fn

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%-- 指明后续的标签使用都会以<c: 开头 --%>

<c:set var="name" value="${'gareen'}" scope="request" />
通过标签获取name: <c:out value="${name}" /> <br> <%-- 类似<%=request.getAttribute("name")%> --%>

<c:remove var="name" scope="request" /> <br>
通过标签获取name: <c:out value="${name}" /> <br>

<c:set var="hp" value="${3}" scope="request" /> <%-- 循环示例 --%>
<c:choose>
    <c:when test="${hp<5}">
        <p>这个英雄要挂了</p>
    </c:when>
    <c:otherwise>
        <p>这个英雄觉得自己还可以再抢救抢救</p>
    </c:otherwise>
</c:choose>

EL 表达式

EL表达式可以从 pageContext、request、session、application四个作用域中取到值,如果 4 个作用域都有相同属性,EL会按照从高到低的优先级顺序获取:pageContext > request > session > application

JSP 常见用法

  • include
    • 指令 include:<%@include file="footer.jsp" %>,当前 JSP 将插入到命令行位置
    • 动作 include:<jsp:include page="footer.jsp" />,footer.jsp 会被转化未 footer_jsp.java 以 Servlet 的形式存在,footer_jsp.java 的执行结果会插入到命令位置
  • 跳转
    • 客户端跳转:<%response.sendRedirect("hello.jsp");%>
    • 服务端跳转:<jsp:forward page = "hello.jsp"/>

JavaBean

JavaBean 的标准

  1. 提供无参 public 的构造方法(默认提供)
  2. 每个属性,都有 public 的 getter 和 setter
  3. 如果属性是 boolean,那么就对应 is 和 setter 方法

Session

Session 就是是会话。会话指的是从用户打开浏览器访问一个网站开始,无论在这个网站中访问了多少页面,点击了多少链接,都属于同一个会话,直到该用户关闭浏览器为止。

Servlet + JSP \(\approx\) MVC

Servlet 方便写 Java 代码,JSP 方便写页面代码,结合二者的特点,使用 Servlet 写业务相关代码,使用 JSP 进行展示。

Servlet,将数据保存到隐式对象

public class HeroEditServlet extends HttpServlet {
 
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        int id = Integer.parseInt(request.getParameter("id"));
        Hero hero = new HeroDAO().get(id);
        request.setAttribute("hero", hero); // 设置属性后 JSP 使用 EL 语言 ${hero.id},获得数据
        request.getRequestDispatcher("editHero.jsp").forward(request, response);
    }
}

JSP,从隐式对象中获得数据

<form action='updateHero' method='post'>
    名字 : <input type='text' name='name' value='${hero.name}'> <br>
    血量 :<input type='text' name='hp' value='${hero.hp}'> <br>
    伤害: <input type='text' name='damage' value='${hero.damage}'> <br>
    <input type='hidden' name='id' value='${hero.id}'>
    <input type='submit' value='更新'>
</form>

应用举例

  • 使用分页技术显示部分数据
    • 后台返回在指定范围内的数据,前端显示

Filter

Filter 就像一个一个哨卡,用户的请求需要经过 Filter,可以设置多个 Filter

graph LR A[用户访问] A --> B((Filter 1)) B --> C((Filter 2)) C --> D((Filter ..)) D --> E[Servlet]

原文地址:https://www.cnblogs.com/jiahu-Blog/p/11596259.html