Java EE day13学习总结

今天主要学习Tomcat和Servlet

思维导图:

一.Tomcat

我们一直说,自己的电脑也可以是一台服务器,那么也就意味我们的电脑也可以提供外部访问的能力,可以的,只不过我需要依靠一个服务器软件进行帮助。

1.WEB服务器:

(1)IIS:Windows电脑自带的,一般用于微软开发的系列软件或者服务会使用IIS(特别是微软提供Windows Server)

(2)Weblogic:这个是BEA公司公司开发的,支持了javaee的所有规范(接口)。不过这个几乎没人用,因为收费。

(3)Tomcat:是Apache公司开发的一个完全基于java的服务器软件,支持sevlet、jsp等相关规范(但是不支持ejb),开源且免费的玩意

(4)JBoss:是Radhat公司开发的一个中间件,支持所有的JAVAEE规范,软件免费 但是呢,服务收费,而且只支持Linux.

 

2.下载安装Tomcat:

官网地址:https://tomcat.apache.org/

因为Tomcat本身是一个基于java开发的程序,所以他是一个完全跨平台的软件;下载的时候不需要指定Windows、linux、mac os等平台分别下载,直接下载zip就可以了;下载后也不需要进行安装,直接解压即可,但是一定要保证你的JAVA_HOME相关的环境变量是设置正确的,因为tomcat强烈依赖于jre运行。

 

3.Tomcat的目录分析:

bin:存放脚本的目录,所有的启动(startup)、停止(shutdown)、监控等脚本都在这个目录当中

conf:是tomcat的核心配置目录(server.xml/web.xml)

lib:存放是tomcat运行的依赖的jar包(其实也包括servlet和jsp的实现)

logs:存放的是日志文件(tomcat的运行状态、异常状态的日志都是存在这个目录)

temp:存放的是临时文件

webapps:存放我们的web项目的位置

work:处理我们的class和jsp文件的

 

4.如何启动Tomcat

(1)所有的启动相关的操作全部是在bin目录

开启:

startup.bat(Windows)

startup.sh(Linux)

关闭:

shutdown.bat

shutdown.sh

(2)注意:

Tomcat的启动会默认占用一个8080的端口,在启动之前一定要先确保这个端口

不要被其他程序占用(一般被占用无非也就是同时开启了两个同端口的tomcat)

 

5.Tomcat的常见异常:

java.net.BindException: Address already in use (Bind failed):因为端口被占用

 

6.Tomcat的server.xml(Tomcat的核心配置)

端口号的修改:

 <Connector port="8080" protocol="HTTP/1.1"

               connectionTimeout="20000"

          redirectPort="8443" />

为何tomcat会默认的运行webapps的项目呢? 

 <Host name="localhost"  appBase="webapps"

            unpackWARs="true" autoDeploy="true">     

 

7.Tomcat的web.xml(项目的配置)

为什么不输入文件名就能直接方法index的文件?

welcome-file-list:默认加载指定的页面

 <welcome-file-list>

       <welcome-file>index.html</welcome-file>

       <welcome-file>index.htm</welcome-file>

       <welcome-file>index.jsp</welcome-file>

 </welcome-file-list>            

 

8.为何能找到webapps的ROOT项目

(1)先加载mapping,决定运行那个servlet

 <servlet-mapping>

       <servlet-name>default</servlet-name>

       <url-pattern>/</url-pattern>

  </servlet-mapping>

 

(2)找到servlet后,servlet决定执行和加载哪一些文件  

 <servlet>

        <servlet-name>default</servlet-name>

        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>

        <init-param>

            <param-name>debug</param-name>

            <param-value>0</param-value>

        </init-param>

        <init-param>

            <param-name>listings</param-name>

            <param-value>false</param-value>

        </init-param>

        <load-on-startup>1</load-on-startup>

    </servlet>

 

9.Tomcat的手动部署方式:

(1)默认部署

其实所谓的默认部署就是将我们的web资源存放到webapps下面,在不修改 server.xml下面的Connector的配置的情况下,默认就是访问webapps。我们只需要将项目存在这个目录下面就可以进行访问,并且输入对应的项目名(目录名)就可以进行访问。

特点:

将我们的项目和tomcat进行了紧密的关联

 

(2)通过server.xml进行虚拟配置(新增一个指定路径)

在Host配置项里面新增一个Context的配置项

docBase:是存放你web资源的具体目录位置(绝对路径)

path:这个path不是真正的路径,只是一个虚拟路径 可以任意写

<Host name="localhost"  appBase="webapps"

            unpackWARs="true" autoDeploy="true">

     <Context docBase="/Users/toobug/Documents/HBuilderProjects/day03" path="/hello/"/>      

    </Host>

特点:

<1>可以自定义任何目录,就实现了tomcat和项目的完全分离   

<2>但是需要频繁的去修改server.xml,一般不太建议 因为server.xml是核心配置项

能少动则少动。

 

(3)通过conf/Catalina/localhost/的目录进行配置

<1>在这个目录创建一个xml文件

<2>在这个文件里面编写代码

<?xml version="1.0" encoding="UTF-8"?>

  <Context docBase="/Users/toobug/Documents/HBuilderProjects/day03" /> 

  <3>这种方式不用去指定一个path的虚拟路径,xml的名字其实就是路径名

 特点:

 <1>可以自定义任何目录,就实现了tomcat和项目的完全分离 

 <2>无需修改server.xml 保证了业务的安全性  

 

10.JAVAEE的项目结构

 项目名称

 |-- src (存放的是所有的java代码)

 |-- web

 |-- WEB-INF(这里的所有内容,用户是不能通过浏览器访问的,一般放配置文件)

 |-- web.xml(当前项目的配置文件,servlet的配置、访问页配置、拦截器等等等)

 |-- lib(当前项目的所需的一些jar包)

 |-- classes(存放是其实就是java编译后的class文件,这个文件需要给项目运行)

|-- static(存放是一些静态资源文件,比如图片、css、js)

 

11.Web概述:

12.Tomcat生命周期

Lifecycle接口统一管理Tomcat生命周期。一共做了4件事:

  1. 定义13个string类型常量,用于LifecycleEvent时间的type属性中,用于区分组件发出的LifecycleEvent事件时的状态。
  2. 定义三个管理监听器的方法,addLifecycleListener、findLifecycleListeners、removeLifecycleListener。
  3. 定义4个生命周期的方法,init、start、stop、destory,用于执行生命周期的各个阶段的操作。
  4. 定义了获取当前状态的两个方法,getState、getStateName、用于获取当前的状态。

 

二.Servlet

1.概念:

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

2.Servlet 的优势:

Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

(1)性能明显更好。

(2)Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。

(3)Servlet 是独立于平台的,因为它们是用 Java 编写的。

(4)服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。

(5)Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

3.Servlet 执行以下主要任务:

(1)读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。

(2)读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。

(3)处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。

(4)发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。

(5)发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

4.Servlet有三种创建方式:

(1)实现 Servlet 接口

(2)继承 GenericServlet 类

(3)继承 HttpServlet 方法

5.Servlet 生命周期:(可被定义为从创建直到毁灭的整个过程

(1)Servlet 通过调用 init () 方法进行初始化。

(2)Servlet 调用 service() 方法来处理客户端的请求。

(3)Servlet 通过调用 destroy() 方法终止(结束)。

(4)最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的

6.关于servlet的路径映射的问题:

(1)精确匹配

  <url-pattern>/demo</url-pattern>

  <url-pattern>/demo/mp4</url-pattern>

(2)模糊匹配   

  <1> /*  (http://localhost:8080/servlet/任意映射路径)

  <2>/demo/* (http://localhost:8080/servlet/demo/任意映射路径)

  <3> *.do (http://localhost:8080/servlet/任意映射路径.do)

  <4> *.* (http://localhost:8080/servlet/任意路径.任意后缀)

  <5> /demo/*/*.do (http://localhost:8080/servlet/demo/任意路径/任意路径.do)[不要用]

 <6>注意:

  在任何情况下,精确匹配的优先级永远大于模糊匹配

  (/demo = /demo) > (/*  = /demo)

  在任何情况下,动态资源的优先级永远大于静态资源

  (*.html = reg.html) > (web/reg.html)

  在url-pattern当中,* 和 / 在一定程度上是冲突的(一般要么/开头,要么是*开头,最好不要两着冲突)

比如一下都是错误的:

*/.html

*/ 

/*/*

7.我们在实际的开发当中,从前端请求过来的参数,肯定不是用户手动的写在url里面的

所以需要准备一个表单,这个表单就可以让用户直接输入数据(这个界面一般也不是我们处理,一般是前端);

(1)前端提交数据的方式无非也就两个:get/post (这个提交方式也是前端决定)

(2)tomcat本质上就会根据前端提交的参数类型,从而决定调用哪个一个方法(doGet、doPost)

举例:

package com.servlet.demo02;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
   
public class RegServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doget----");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("账号:"+username+"--密码:"+password);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("dopost----");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("账号:"+username+"--密码:"+password);
    }
}

8.在servlet3.0的版本提供了一个注解的方式,其中就一个注解是可以快速和简化配置Servlet
@WebServlet:(这个注解必须写在类名上面)
1可以完全省略web.xml的配置
2可以完全的支持多线程
3可以支持可插性的特性(你编写的代码,生成的class 文件可以实现自动部署,自动加载,自动执行)
name = "ServletDemo"(就是一个servlet类的名称:<servlet-name>ServletDemo</servlet-name> )
    urlPatterns = "/zhujie" (就是一个用户范围servlet的一个名称 <url-pattern>/hello</url-pattern>)

举例:

package com.servlet.demo02;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletDemo",urlPatterns = "/zhujie")
public class ZhuJieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("我被访问了");
    }
}

9.配置环境变量:
(1)将所有需要的配置文件存放到src的根目录当中
(2)在web目录下面创建一个lib目录,将所有需要的jar存入到这个目录
(3)在lib目录下面选中所有的jar包,右键选中add as lib..
 (4)将所有的jar包关联到项目之后,确保你的代码不存在问题但是现在这个步骤仅仅只是将jar包和项目进行关联,并没有和tomcat的部署进行关联在开发阶段正常(jre),在运行阶段失败(tomcat)project Structure -- > Problem -- > fix 进行lib和tomcat的关联修复,lib包就和我们的web项目完全关联了。

举例:
package com.servlet.demo04;
import com.servlet.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;


public class TestMysql {
    public static void main(String[] args) throws SQLException {
        //创建一个QueryRunner的核心类
        QueryRunner qr = new QueryRunner( JdbcUtils.getDataSource());
        //编写一个sql
        String sql = "select * from account";
        //查询所有记录
        List<User> query = qr.query(sql, new BeanListHandler<User>(User.class));

        //测试数据的取出
        for(User user :query){
            System.out.println(user.getId()+"--"+user.getUsername()+"---"+user.getPassword());
        }
    }
}

10.获取前端参数的几种方式:
(1)获取单个key请求参数的value
request.getParameter("username"); //返回的是一个String的变量(前端提交的任何数据都认为是一个String,如果需要操作这些数据 请自己转换)

(2)获取多个相同key的请求参数的value
request.getParameterValues("ck"); //返回的是这个key对应的多个值,使用一个String的数组进行变量

(3)获取多个key和对应的value
request.getParameterMap();//返回的是前端请求过来的key和value,使用是一个map集合接受,因为value可能存在多个,所有使用的是一个String[]来接受value
注意:
前端的name属性其实就是对应了我们后端的key
前端的value属性其实就是对应了我们后端的value

举例:
package com.servlet.demo05;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

@WebServlet(name = "CheckboxServlet",urlPatterns = "/checkbox")
public class CheckboxServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取前端的请求参数的值
        String username = request.getParameter("username");
        String password = request.getParameter("password");


        //获取多选框的数据
        //        String java = request.getParameter("java");
        //        String php = request.getParameter("php");
        //        String python = request.getParameter("python");

        //解决多个复选框选中的问题
        String[] cks = request.getParameterValues("ck");
        for (String ck : cks) {
            System.out.println(ck);
        }

        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            String key = entry.getKey();
            System.out.println("name:"+key+"--- values:"+ Arrays.toString(entry.getValue()));
        }


        System.out.println(username);
        System.out.println(password);
    }
}

11.回想下我们之前说的一些问题
1一个方法不调用不执行
(2)方法的调用除了static修饰的,除此之外都需要依靠对象进行调用
看下我们现在的
(3)我们有去调用Servlet的方法吗?
没有,谁去调用?之前main方法我们也没有调用,是JVM调用 但是因为main方法是一个static方法,所以JVM不需要创建对象就可以调用但是,现在我们用过的servlet的方法并没有任何的static,是谁调用的?怎么调用的?
Tomcat进行调用的,Tomcat根据反射的newInstance()来进行了对象的创建

 (4)那么Tomcat这个运行的流程又是如何的?(其实就是Tomcat生命周期)如果要了解Servlet就需要知道JAVAEE的Servlet标准是什么,因为我们之前就说过,JAVAEE只提供接口(标准跟规范,跟JDBC是一个道理)接口的实现是由各个接口的使用者进行操作,比如说Tomcat就需要操作Servlet的标准。所以我们就需要去了解Servlet究竟提供了一些什么东西?
(5)Servlet主要的三个核心(生命周期)
<1>void init(ServletConfig var1)【只在启动的时候执行一次】Servlet的初始(出生)时机,这个时机会初始化Servlet的所有配置。
<2>void service(ServletRequest var1, ServletResponse var2)【每一次访问Servlet都需要执行】Servlet的生存时机,servlet在生存的时候需要干什么事,我们的doGet和doPost方法的请求和响应其实就是他完成的。
<3>void destroy()【Tomcat停止或者结束部署的时候执行一次】Servlet的死亡时机,就是Servlet某种原因中断,操作了Servlet死亡的时候需要干什么事情
(6)注意:

<1>一个Tomcat的项目启动,不会立即创建对象
<2>只有在首次访问项目的servlet的时候,才会创建对象 并且只初始化一次,即便你下次继续访问对象不会继续创建也不会在执行初始化
<3>综上所述,也就可以证明Servlet使用是单例设计模式(保证的内存当中且能存在一个相同对象),因为是要访问Servlet后才会创建对象,在项目启动的时候不会创建,所以我们可以知道这个单例设计模式采用的懒汉式的设计模式。因为Servlet采用的是单例设计,那么也就意味这所有的Servlet成员变量之间的数据是可以进行共享的。这种情况就有可能造成线程安全(并发)的问题,针对针对这种情况,我们一般句建议不再在任何的servlet类上面写成员变量。如果非得写,最好给成员的位置加上代码锁,但是锁的范围控制好一点,因为怕造成同步代码产生效率低的问题。
//@WebServlet(name = "LifeServlet",urlPatterns = "/life",loadOnStartup = 1,initParams = {@WebInitParam(name = "toobug",value = "18"),@WebInitParam(name = "toobug",value = "18")})

举例:

package com.servlet.demo06;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LifeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("hello");
    }
    public LifeServlet(){

        System.out.println("我是构造");
    }

    //初始化时机
    public void init(ServletConfig config) throws ServletException {
        String name = config.getInitParameter("name");
        String age = config.getInitParameter("age");
        String servletName = config.getServletName();
        System.out.println(servletName);
        System.out.println(name+"---"+age);
        System.out.println("hello init开始出生了");
    }
    //生存时机
    public void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException{
        System.out.println("hello service开始工作了");
    }
    //销毁时机
    public void destroy(){
        System.out.println("hello destroy死亡了");
    }
}

12.servler的运行步骤

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值