• Java Web、Tomcat、Servlet、JSP



    Web服务器

    WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源。

    Internet上供外界访问的Web资源分为:

    • 静态资源:html页面
      • 实现:HTML
    • 动态资源:由程序产生,会经过程序实时处理
      • 实现:JSP/Servlet、ASP、PHP、ruby、python

    在Java中,动态web资源开发技术统称为Java Web

    主要服务器

    服务器是一种被动程序:只有当Internet上运行在其他计算机中的浏览器发出请求时,服务器才会响应。

    • weblogic :BEA公司产品,被Oracle收购,全面支持JavaEE规范,收费软件,企业中非常主流的服务器、网络上文档非常全面
    • WebSphere :文档非常少,IBM公司产品,价格昂贵,全面支持JavaEE 规范
    • Tomcat :开源小型web服务器 ,完全免费,主要用于中小型web项目,只支持Servlet和JSP 等少量javaee规范 ,Apache公司jakarta 一个子项目
    • Jboss :hibernate公司开发。不是开源免费。J2EE容器

    这里重点说广泛使用的Tomcat

    Apache Tomcat是用Java语言编写的一个开源的Serlvet容器。
    由于Tomcat本身也内含了HTTP服务器,因此也可以视作单独的Web服务器。
    截至至2016年,Tomcat的市场占有率为58.22%,高出第二名近三倍

    值得注意的是,Tomcat并不是严格意义上的服务器,只是个运行在物理服务器上的容器程序,是一个Servlet容器。

    容器和服务器的联系:
    容器和服务器的联系

    容器是位于组件和服务器平台之间的接口集合,使得组件可以方便部署到服务器上运行。

    更多关于各种容器与服务器的区别与联系参考这篇大佬的文章-> Servlet容器、WEB容器、Java EE容器、应用服务器、WEB服务器、Java EE服务器 的区别与联系

    配置Tomcat

    1. 从官网 tomcat.apache.org 中下载tomcat安装程序。
    2. 解压安装,注意路径中不要包含空格与中文。
    3. 配置环境变量
      1. 确保有 JAVA_HOME 变量
      2. 新建 CATALINA_HOME 变量,值为Tomcat的根路径
      3. 新建 CATALINA_BASE 变量,值为Tomcat的根路径
    4. 双击tomcat/bin/startup.bat启动,如果在浏览器中访问 localhost:8080 能正确打开tomcat网页,则代表没问题了。
    5. 以下针对 InteliJ IDEA 配置Tomcat:
      1. "Run" -> "Edit Configurations" -> "+" -> "Tomcat Server";
      2. 配置路径与版本;
      3. "Deployment" -> "+" -> "Artifact...";

    具体参考 IntelliJ IDEA配置Tomcat

    Tomcat基本框架

    Tomcat基本框架

    • Server :整个Servlet容器组件,是最顶层元素,包含多个Service元素
    • Service :一个Engine元素以及多个Connector元素
    • Connector :和客户端程序交互的组件,负责接收客户端请求和向客户端返回响应
    • Engine: :可以包含多个Host,Host表示一个虚拟主机,他可以包含多个web应用
    • Context: :运行在虚拟主机上的单个web应用
    Tomcat目录结构

    |--bin —— 它里面装入的是可执行的命令 如 startup.bat。
    |--conf —— 它里面是一个相关的配置文件,我们可以在里面进行例如端口、用户信息的配置。
    |--lib —— tomcat类库。
    |--logs —— tomcat 日志文件
    |--temp —— 临时文件
    |--webapps —— 它里面放的是的 web site(web项目)
    |--work —— 存放的是页面(例如 jsp)转换成的.class文件。

    Tomcat配置文件

    关于conf目录下的配置文件解析

    Server.xml

    server.xml 是Tomcat中最重要的配置文件
    server.xml 的每一个元素都对应了Tomcat中的一个组件
    因此可以通过对xml文件元素的配置,实现对Tomcat中各个组件的控制

    正因为xml的结构与Tomcat的框架结构所对应,所以server.xml整体核心结构如下:

    <Server> 	——代表整个Tomcat容器,必须唯一
        <Service>	——可以多个
            <Connector />	——可以多个
            <Connector />
            <Engine>	——一个service只能有一个组件
                <Host>	——可以多个,代表Engine的虚拟主机
                    <Context />	——现在常常使用自动部署,强烈不推荐配置Context元素
                </Host>
            </Engine>
        </Service>
    </Server>
    

    Web.xml

    启动web项目容器时,首先去读取的配置文件,但web.xml不是必须的

    <?xml version="1.0" encoding="UTF-8"?> 
    <web-app>	——根
        <welcome-file-list>	——项目打开的第一个页面
    		<welcome-file>index.jsp</welcome-file>	——可以多个,按顺序查找
    	</welcome-file-list>
            <servlet>	——servlet
    		    <servlet-name>Servlet</servlet-name>
    		    <servlet-class>com.zohn.servlet</servlet-class>
            </servlet>
     	<servlet-mapping>	——servlet映射
     		<servlet-name>Servlet</servlet-name>
    		<url-pattern>/servlet</url-pattern>
     	</servlet-mapping>
    	………………
    </web-app>
    

    Servlet

    JavaWeb中有三大组件:ServletFilterListener
    其中Servlet是最重要的组件.

    Servlet主要功能在于交互式地浏览和修改数据,生成动态Web内容。

    SUN公司定义了两个默认实现类,分别为:

    • GenericServlet(代理了ServletConfig的所有功能)
    • HttpServlet

    而HttpServlet是能够处理Http请求的Servlet,在原有Servlet接口上添加了一些Http协议处理方法。

    狭义的Servlet就是一个接口,全名Servlet.class,位于Servlet-api.jar包里的javax.servlet包内。
    广义的Servlet是指任何实现了这个Servlet接口的类。一般情况下,人们将Servlet理解为后者。

    Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

    那servlet可以直接处理请求吗?
    那是不可以的,相信我,你从来不会在servlet中写什么监听8080端口的代码,servlet不会直接和客户端打交道。

    那请求怎么来到servlet呢?答案是上面已经提到过的,servlet的容器,比如Tomcat。

    tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据url信息和web.xml配置文件匹配,
    确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,
    tomcat再把这个response返回给客户端

    工作机制图解如下:

    Servlet的生命周期

    Servlet的生命周期

    1. (启动)Tomcat在加载Web应用时,就会把相应的web.xml文件中的数据读入到内存中。
    2. 客户端向服务器发送请求数据。
    3. 服务器将获取到的url与内存中的xml映射数据进行匹配。
    4. 匹配到后根据映射名称找到相对应的Servlet路径。
    5. 服务器先检查要访问的servlet是否已经装载并创建了Servlet对象。
    6. 如果没有则创建该Servlet的实例对象(先执行构造方法,再执行init初始化方法)。
      ++注意:Servlet属于单例模式,初始化和实例化只执行一次++
    7. 调用service方法,一般根据父类已重写的方法来判断请求的类型。
    8. 执行相对应请求的doGet、doPost方法
      服务器向客户端响应数据。
    9. 当web容器退出,servlet销毁的时候,destroy方法执行。
      ++只会消亡(destroy)一次++
    Servlet单实例多线程的特点
    1. Servlet单实例,减少了产生servlet的开销;
    2. 通过线程池来响应多个请求,减少了请求的响应时间;
    3. Servlet容器并不关心到达的Servlet请求访问的是否是同一个Servlet还是另一个Servlet,直接分配给它一个新的线程;如果是同一个Servlet的多个请求,那么Servlet的service方法将在多线程中并发的执行,因此,它也是线程不安全的

    Servlet内对象的作用域

    作用域就是一个存储信息的空间,并且可以在范围内访问信息。

    ServletContext(Application)

    ServletContext被称之为Servlet上下文对象,也就是对每一个servelt提供一个配置信息的环境,让每一个servlet都能够在它的背景之下。

    ServletContext是全项目性的,随着服务器的创建而创建,随着服务器的消亡而消亡

    生命周期:从web应用加载进容器时,到服务器关闭或web应用被移除时。

    作用范围:整个web应用(相当于整个服务器)

    作用

    1. 作为作用域进行存取值,这是servletContext最重要的作用。
    2. 获取服务器的信息
    3. 相对路径转绝对路径
    4. 获取全局初始化参数(在所在项目的web.xml配置文件中,我们可以给整个项目配置参数)

    常用方法

    public class ContextServlet1 extends HttpServlet {
     
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		ServletContext sc = this.getServletContext();
    		
    		/*
    		 * 作用1:获取全局初始化参数
    		 * 在web.xml文件中进行全局初始化参数配置,然后通过配置名来获取
    		 * 
    		 *  <context-param>
    			<param-name>path</param-name>
    			<param-value>D:/</param-value>
    			</context-param>
    		 */
    		String path = sc.getInitParameter("path");
    		System.out.println(path);
    		
    		/*
    		 * 作用2:获取服务器的信息
    		 */
    		System.out.println("服务器信息:"+sc.getServerInfo());
    		
    		/*
    		 * 作用3:相对路径转绝对路径
    		 */
    		String realPath = sc.getRealPath("upload");
    		System.out.println(realPath);
    		
    		/*
    		 * 作用4:作为作用域进行存值取值
    		 * 以键值对的形式进行存储,前面为键,后面为值,获取值时,通过key值来进行获取
    		 * 这个是一个范围比较大的作用域,作用范围是整个项目,所以上面获取的时候也是通过this对象来进行获取
    		 * 在这个项目的所有servlet中都可以获取到这个作用域中的值。不过需要先进行获取,然后再去调用取值的servelt,
    		 * 否则会报空指针异常
    		 * 取得参数也是全局初始化参数
    		 */
    		sc.setAttribute("lufei", "xiangjiao");
    		sc.setAttribute("suolong", "hedaoyiwenzi");
    		List<String> list = new ArrayList();
    		list.add("lufei");
    		list.add("suolong");
    		list.add("shanzhi");
    		
    		sc.setAttribute("caomao", list);
    		
    		String lufei = (String)sc.getAttribute("lufei");
    		System.out.println(lufei);
    		
    		List caomao = (List) sc.getAttribute("caomao");
    		for(String s : list ) {
    			System.out.println(s);
    		}
    		
    	}
     
    }
    

    注意:ServletContext其实就是application
    区别只是:application用在jsp中,servletContext用在servlet中

    Session

    生命周期:从第一次调用getSession()方法时,到默认时间(30分钟)或服务器非正常关闭

    作用范围:一次会话中

    常用方法

    设置:setAttribute( String , Object );
    获取:getAttribute( String );
    移除:removeAttribute( String );

    Session信息

    返回Session的ID:getId()
    返回Session的创建日期:getCreationTime()
    返回Session的最后活跃时间:getLastAccessedTime()
    返回Session的超时时间:getMaxInactiveInterval()
    设置Session的超时时间:setMaxInactiveInterval()

    注意

    • 当要创建一个session时,服务器先检查这个请求中是否已包含一个sessionId的cookie。
      如果已经有了,就用这个id检索session出来使用。
      如果不包含才会创建一个session,因此id值是一个不会重复,也不易找规律的字符串。
    • 如果浏览器禁用了cookie,session也不能起作用。

    生命周期:从设置Cookie开始,到设定时间结束(不设定时间则为关闭会话时)

    作用范围:在设定时间内

    常用方法

    构造方法(名,值):new Cookie( String , String );
    设置最大时间(秒):cookie.setMaxAge( int )

    如果设置的时间为负数,则代表有效时间是当前会话结束

    注意

    • 一个站点最多存放20个Cookie,每个Cookie大小最多只能4kb
    • 设置的最大时间如果是负数,则代表是当前会话结束,如果是0,则删除
    • 删除Cookie时,path必须一致
    • Cookie的效率会比Session高,但安全性就会低

    Response

    生命周期:从客户端发送请求开始,到得到服务器结果反馈

    作用范围:一次请求响应

    常用方法

    设置头信息:response.setHeader( 内容 , 参数 );
    刷新:response.setHeader( "refresh" , "1" );
    按时跳转:response.setHeader( "refresh" , "2;url=?" );
    添加Cookie给客户端:response.addCookie( Cookie );
    向客户端打印数据:response.getWriter().write( String );
    将请求重定向给别的资源:response.sendRedirect( String );

    Request

    生命周期:从客户端发送请求开始,到一个请求结束(转发将会继续用该请求链)

    作用范围:整个请求链

    常用方法

    将数据作为属性放到request对象中:request.setAttribute( String , Object );
    根据参数获取存放在request对象的属性值:request.getAttribute( String );
    移除存放在request对象中参数所对应的属性值:request.removeAttribute( String );

    从客户端请求中获取属性对应的值:request.getParameter( String );
    从客户端请求中获取属性对应的数组值:request.getParameterValues( String );

    将请求转发给别的资源:request.getRequestDispatcher( String ).forward( request , response );

    获得客户端信息

    客户端发出请求时的完整URL:getRequestURL
    请求行中的资源名部分:getRequestURI
    请求行中的参数部分:getQueryString
    发出请求的客户机的IP地址:getRemoteAddr
    发出请求的客户机的完整主机名:getRemoteHost
    客户机所使用的网络端口号:getRemotePort
    WEB服务器的IP地址:getLocalAddr
    WEB服务器的主机名:getLocalName
    客户机请求方式:getMethod

    PageContext

    生命周期:从对JSP请求时开始,到响应结束时销毁

    作用范围:仅在JSP页面内

    作用范围最小,很少使用。

    总结

    作用域能用小的,尽量用小的,不用大的,可以节约服务器的内存

    JSP & EL & JSTL

    JSP是用java做页面的一种常用方式。

    (不过,大人,时代变了,由于各种原因已经逐渐被舍弃了,所以下面也是随便说说)

    顺带一提,JSP实际上经过编译处理后还是Servlet。

    JSP表达式

    名称 语法 说明
    JSP脚本表达式 <%= 变量或表达式 %> 里面不需要分号
    JSP脚本片段 <% 多行Java代码 %> 里面必须遵循Java语法
    JSP声明 <%! Java代码 %> 将默认翻译到service方法中的代码翻译到方法外面
    JSP注释 <%-- 注释信息 --%> 翻译成Servlet程序时,忽略JSP注释中的内容
    JSP指令 <%@ 指令 属性名="值" %> 为JSP引擎而设计告诉引擎如何处理JSP其余部分
    <!--page指令:用于定义JSP页面的各种属性,作用整个页面,一般习惯应该放页面起始位置-->
    <%@ page import="java.util.Date,java.sql.*,java.io.*"%>
    
    <!--include指令:用于引入其他JSP页面,引擎会把这两个JSP翻译到一个Servlet,即静态引入-->
    <%@ include file=“被包含页面的绝对URL或相对URL"%>
        
    <!--taglib指令:用于在JSP页面中导入标签库-->
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    

    常用JSP标签

    标签 语法 说明
    include <jsp:include page=" " /> 把一个资源内容插入当前页面内容中即动态引入
    forward <jsp:forward page=" " /> 把请求转发给另一个资源
    param <jsp:include page=" "> <jsp:param name=" " value=" " /> </jsp:include> 在上面两个标签引入或转发时可以向资源传递参数

    EL表达式

    EL表达式语言(expression language)并不是一种开发语言,而是JSP中获取数据的一种规范

    获取数据
    • 获取数据语法: ${ 标识符 }
      • 当语句执行时,会调用pageContext.findAttribute方法寻找标识符对应的对象
      • 寻找顺序是 page、request、session、application 四个域
      • 也可以指定一个域里查找,如:${ requestScope.标识符 }
        注意:找到则返回对象,找不到是返回 "" (不是null)
      • 也可以获取存储的对象的属性值,如:${ 对象.属性值 }
        注意:EL表达式在访问对象时依靠的是重写的get方法,它会先将写在里面的属性首字符大写,再拼接成getXX()方法,利用反射将对象构建出来,再执行getXX()方法。
        如果没有重写get属性的方法的话,EL表达式不能找到属性并报500错误
      • EL 有 11 个保留标识符,对应于 11个EL隐式对象
    执行运算

    EL表达式支持多种运算写法

    中文 符号 英文
    除以 ${ 6 / 3 } ${ 6 div 3 }
    取模 ${ 5 % 3 } ${ 6 mod 3 }
    相等 ${ 5 == 5 } ${ 5 eq 5 }
    不等 ${ 5 != 5 } ${ 5 ne 5 }
    小于 ${ 3 < 5 } ${ 3 lt 5 }
    大于 ${ 3 > 5 } ${ 3 gt 5 }
    小于等于 ${ 3 <= 5 } ${ 3 le 5 }
    大于等于 ${ 3 >= 5 } ${ 3 ge 5 }
    逻辑与 ${ A && B } ${ A and B }
    逻辑或 ${ A || B } ${ A or B }
    ${ ! A } ${ not A }
    判断是否为 null 或 "" ${ empty Obj }
    三目运算符 ${ user != null ? X : Y }
    其他 . 、[ ]、()、+、-、*

    在EL表达式里,+运算符为单纯相加,不支持拼接

    JSTL库

    JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。

    核心标签
    <!--需导入:-->
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
    标签 描述
    <c:out> 用于在JSP中显示数据,就像<%= ... >
    <c:set> 用于保存数据
    <c:remove> 用于删除数据
    <c:catch> 用来处理产生错误的异常状况,并且将错误信息储存起来
    <c:if> 与我们在一般程序中用的if一样
    <c:choose> 本身只当做<c:when>和<c:otherwise>的父标签
    <c:when> <c:choose>的子标签,用来判断条件是否成立
    <c:otherwise> <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
    <c:import> 检索一个绝对或相对 URL,然后将其内容暴露给页面
    <c:forEach> 基础迭代标签,接受多种集合类型
    <c:forTokens> 根据指定的分隔符来分隔内容并迭代输出
    <c:param> 用来给包含或重定向的页面传递参数
    <c:redirect> 重定向至一个新的URL.
    <c:url> 使用可选的查询参数来创造一个URL
    函数标签
    <!--需导入:-->
    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
    
    函数 描述
    fn:contains() 测试输入的字符串是否包含指定的子串
    fn:containsIgnoreCase() 测试输入的字符串是否包含指定的子串,大小写不敏感
    fn:endsWith() 测试输入的字符串是否以指定的后缀结尾
    fn:escapeXml() 跳过可以作为XML标记的字符
    fn:indexOf() 返回指定字符串在输入字符串中出现的位置
    fn:join() 将数组中的元素合成一个字符串然后输出
    fn:length() 返回字符串长度
    fn:replace() 将输入字符串中指定的位置替换为指定的字符串然后返回
    fn:split() 将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回
    fn:startsWith() 测试输入字符串是否以指定的前缀开始
    fn:substring() 返回字符串的子集
    fn:substringAfter() 返回字符串在指定子串之后的子集
    fn:substringBefore() 返回字符串在指定子串之前的子集
    fn:toLowerCase() 将字符串中的字符转为小写
    fn:toUpperCase() 将字符串中的字符转为大写
    fn:trim() 移除首位的空白符
    其他标签
    • 格式化标签
    • SQL 标签
    • XML 标签

    更详细的内容参考:

  • 相关阅读:
    DLinq[新特性]
    破解 iPod Touch[转]
    iPod Touch Online
    谈到Model View Presenter模式之后的随笔[讨论版]
    各家银行买"基金"如何省钱
    WF随笔系列之二 架构、编译、序列化
    JavaScript AppendChild 引发的思考
    IEquatable接口
    DLinq查询
    基金小窍门:如何判断基金的赚与赔
  • 原文地址:https://www.cnblogs.com/zohnn/p/13849433.html
Copyright © 2020-2023  润新知