Servlet

Tomcat

Web服务器软件

  • Web服务器软件:接收用户的请求,处理请求,做出响应。web容器,部署web项目。
  • 常见的web服务器:

    • webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
    • webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
    • JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
    • Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范servlet/jsp。开源的,免费的。
  • Java SE:Java Standard Edition,Java 标准版。是Java技术的核心和基础,是Java ME和Java EE编程的基础。

  • Java EE:Java Platform Enterprise Edition企业级应用程序版本。Java语言在企业级开发中使用的技术规范的总和,一共规定了13项大的规范

  • Java ME:Java Platform Micro Edition,是一个技术和规范的集合,它为移动设备(包括消费类产品、嵌入式设备、高级移动设备等)提供了基于Java环境的开发与应用平台。

Tomcat

  • 目录结构

    • bin:可执行文件
    • conf:配置文件
    • libs:依赖jar包
    • logs:日志文件
    • temp:临时文件
    • webapps:存放web项目
    • work:存放运行时的数据
  • 可能遇到的问题

    • 黑窗一闪而过

      • 原因:没有正确配置JAVA_HOME环境变量
    • 启动报错

      • 端口被占用:找到占用的端口号,杀死该进程,或修改自身端口号(查看进程和端口号netstat -ano)
      • 修改端口号:conf/server.xml

        1
        2
        3
        <Connector port="8080" protocol="HTTP/1.1"
        connectionTimeout="20000"
        redirectPort="8443" />
      • 一般会将tomcat的默认端口号修改为80。80端口号是http协议的默认端号。在访问时,就不用输入端口号

  • 关闭

    • 正常关闭

      • bin/shutdown.bat
      • ctrl+c
    • 强制关闭

      • 关闭窗口
  • 部署

    • 简单部署:将项目打成一个war包,再将war包放置到webapps目录下。(war包会自动解压缩)

    • 配置conf/server.xml文件

      1
      2
      3
      4
      在<Host>标签体中配置
      <Context docBase="D:\xxx" path="/xxx" />
      // docBase:项目存放的路径
      // path:虚拟目录
    • 热部署:在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写

      1
      2
      <Context docBase="D:\xxx" />
      * 虚拟目录:xml文件的名称

Servlet

  • Server Applet:运行再服务器端的小程序

    概念

  • Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
  • Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则
  • 需要自定义一个类,实现Servlet接口,复写方法。

快速入门

  • 创建JavaEE项目

  • 定义一个类,实现Servlet接口

    • public class 类名 implements Servlet
  • 实现接口中的抽象方法

    • init:创建
    • ServletConfig:获取Servlet配置对象
    • service:提供服务
    • getServletInfo:获取Servlet信息
    • destroy:销毁
  • 配置Servlet
1
2
3
4
5
6
7
8
9
10
11
12

<!--配置Servlet-->
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>com.nogizaka.servlet.ServletDemo</servlet-class>
</servlet>

<!--配置映射路径-->
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>
  • 执行原理
    1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
    2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。
    3. 如果有,则在找到对应的<servlet-class>全类名
    4. tomcat会将字节码文件加载进内存,并且创建其对象
    5. 调用其方法

Servlet生命周期

创建

  • init方法,只执行一次
  • 默认情况:第一次被访问时,Servlet被创建
  • 配置执行创建时机:

    1. <servlet>标签下配置<load-on-startup>
    2. 负数:第一次被访问时创建
    3. 0或正整数:服务器启动时创建
  • 注意:Servlet的iniy方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的。

    • 多个用户同时访问时,可能存在线程安全问题
    • 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要修改值。

提供服务

  • 提供服务:执行service方法,执行多次
  • 每次访问Servlet时,service方法都会被调用一次

销毁

  • 销毁:destroy方法,只执行一次
  • 只有服务器正常关闭时,才会执行destroy方法。
  • destroy方法在Servlet被销毁之前执行,一般用于释放资源

Servlet3.0

  • 支持注解配置,无需web.xml

  • 步骤

    1. 创建JavaEE项目。选择Servlet的版本3.0以上,可以不创建web.xml
    2. 定义一个类,实现Servlet接口
    3. 复写方法
    4. 在类上使用@WebServlet注解,进行配置

      • @WebServlet(urlPatterns = "资源路径")

      • @WebServlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)b
@Documented
public @interface WebServlet {
String name() default "";//相当于<Servlet-name>

String[] value() default {};//代表urlPatterns()属性配置

String[] urlPatterns() default {};//相当于<url-pattern>

int loadOnStartup() default -1;//相当于<load-on-startup>

WebInitParam[] initParams() default {};

boolean asyncSupported() default false;

String smallIcon() default "";

String largeIcon() default "";

String description() default "";

String displayName() default "";
}

IDEA与tomcat的相关配置

  • IDEA会为每一个tomcat部署的项目单独建立一份配置文件

    • 查看控制台的log:Using CATALINA_BASE
  • 工作空间项目tomcat部署的web项目

    • tomcat真正访问的是“tomcat部署的web项目”(out文件夹),”tomcat部署的web项目”对应着”工作空间项目” 的web目录下的所有资源
    • WEB-INF目录下的资源不能被浏览器直接访问。

Servlet体系结构

1
2
3
4
5
Servlet -- 接口
|
GenericServlet -- 抽象类
|
HttpServlet -- 抽象类
  • GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象

    • 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
  • HttpServlet:对http协议的一种封装,简化操作

    1. 定义类继承HttpServlet
    2. 复写doGet/doPost方法

Servlet相关配置

  • urlPattern:Servlet访问路径

    1. 一个Servlet可以定义多个访问路径 :@WebServlet({"/d4","/dd4","/ddd4"})
    2. 路径定义规则:
      1. /xxx:路径匹配
      2. /xxx/xxx:多层路径,目录结构
      3. *.do:扩展名匹配

Request & Response

  • request对象和response对象的原理
    1. request和response对象是由服务器创建的
    2. request对象是来获取请求消息,response对象是来设置响应消息

Request

request对象继承体系结构

1
2
3
4
5
ServletRequest		--	接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)

request功能

  • 获取请求消息数据

    • 获取请求行数据

      1. 获取当前请求方式:String getMethod()
      2. 获取当前虚拟目录:String getContextPath()
      3. 获取Servlet路径:String getServletPath()
      4. 获取get方式请求参数:String getQueryString()
      5. 获取请求URI:

        • String getRequestURI():URI:统一资源标识符
        • StringBuffer getRequestURL():URL:统一资源定位符
      6. 获取协议及版本:String getProtocol()

      7. 获取客户机的IP地址:String getRemoteAddr()
    • 获取请求头数据

      • String getHeader(String name):通过请求头的名称获取请求头的值
      • Enumeration<String> getHeaderNames():获取所有的请求头名称
    • 获取请求体数据

      • 请求体:只有POST请求方式才有,请求体中封装了POST请求的请求参数
      • BufferedReader getReader():获取字符输入流,只能操作字符数据
      • ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
  • 其他功能

    • 获取请求参数通用方法

      • String getParameter(String name):根据参数名称获取参数值
      • String[] getParameterValues(String name):根据参数名称获取参数值的数组
      • Enumeration<String> getParameterNames():获取所有请求的参数名称
      • Map<String,String[]> getParameterMap():获取所有参数的map集合

      • 中文乱码问题:

        • get方式:tomcat 8 已经将get方式乱码问题解决了
        • post方式:会乱码
          • 解决:在获取参数前,设置request的编码
            • request.setCharacterEncoding("utf-8");
    • 请求转发

      • 一种在服务器内部的资源跳转方式
      • 步骤

        1. 通过request对象获取请求转发器对象
          • RequestDispatcher getRequestDispatcher(String path)
        2. 使用RequestDistpatcher对象来进行转发:
          • forward(ServletRequest request,ServletRespons response)
      • 特点:

        1. 浏览器地址栏路径不发生变化
        2. 只能转发到当前服务器内部资源中
        3. 转发是一次请求
    • 共享数据

      • 域对象:一个有作用范围的对象,可以在范围内共享数据
      • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
      • 方法:
        • void setAttribute(String name,Object obj):存储数据
        • Object getAttribute(String name):通过键 获取 值
        • void removeAttribute(String name):通过键 移除 键值对
    • 获取ServletContext

      • ServletContext getServletContext()

用户登录

步骤

  1. 创建项目,导入html页面,配置文件,jar包
  2. 创建数据库
  3. 创建包domain,创建类User

    • domain 存放 javabean
  4. 创建包util,编写工具类JDBCUtils

    • JDBC工具类:
      • 获取连接池DataSource对象
      • 获取数据库连接Connection对象
  5. 创建包dao,创建类UserDao,提高login方法

    • dao:datasource access object,数据库连接对象
    • dao:处理所有的数据库相关操作
  6. 单元测试,数据库是否正常连接

  7. 创建web.servlet包,实现LoginServlet类

注意

  • html中的form表单中的action属性:虚拟目录+Servlet的资源路径

BeanUtils工具类

  • 导包:commons-beanutils-1.8.0.jar
  • 用于封装JavaBean
  • JavaBean:

    1. 类必须被public修饰
    2. 必须提供空参的构造器
    3. 成员变量必须使用private修饰
    4. 提供公共setter和getter方法
  • JavaBean中的属性:setter和getter方法截取后的产物

    • 例如:getUsername() –> Username–> username(一般和成员方法名相同)
  • 常用方法:

    • setProperty(Object bean, String name, Object value):设置属性
    • getProperty(Object bean, String name):获取属性
    • populate(Object bean, Map<String,? extends Object> properties):将map集合的键值对信息,封装到对应的JavaBean对象中

Response

  • 功能:设置响应消息

    1. 设置响应行

      • 格式:HTTP/1.1 200 OK
      • 设置状态码:setStatus(int sc)
    2. 设置响应头

      • setHeader(String name,String value)
    3. 设置响应体

      • 获取输出流

        • 字符输出流:PrintWriter getWriter()
        • 字节输出流:ServletOutputStream getOutputStream()
      • 使用输出流:将数据输出到客户端浏览器

重定向

  • 资源的跳转

    1
    2
    3
    4
    // 设置状态码为302
    response.setStatus(302);
    // 设置响应头location
    response.setHeader("location","/JavaEE_Response/responseDemo2");
  • 方法:sendRedirect("/虚拟目录/资源路径")

  • 特点:

    ||地址栏|服务器|请求|
    |—|—|—|—|
    |转发Forward|地址栏路径不变|只能访问当前服务器下的资源|一次请求
    可以使用request对象共享数据|
    |重定向Redirect|地址栏发送变化|可以访问其他站点(服务器)资源|两次请求
    不可以使用request对象共享数据|

路径写法

相对路径

  • 通过相对路径不可以确定唯一资源
  • 不以/开头,以.开头
  • 规则:找到当前资源和目标资源之间的相对位置关系
    • ./:当前目录
    • ../:后退一级目录

绝对路径

  • 通过绝对路径可以确定唯一资源
  • /开头
  • 规则:判断定义的路径是给谁用

    • 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)

      • 建议虚拟目录动态获取:request.getContextPath()
      • <a>,<form>,重定向
    • 给服务器使用:不需要加虚拟目录()

      • 转发路径

服务器输出字符数据到浏览器

  • 步骤:

    1. 获取字符输出流
    2. 输出数据

      1
      2
      3
      4
      5
      // 获取字符输出流
      PrintWriter pw = response.getWriter();

      // 输出数据
      pw.write("<h1>hello response</h1><br>");
  • 中文乱码

    • 浏览器:与操作系统有关,windows GBK
    • PrintWriter pw = response.getWriter();:获取的流的默认编码是ISO-8859-1
    • 设置该流的默认编码
    • 告诉浏览器响应体使用的编码(设置响应头content-type)

      1
      2
      3
      4
      // 设置响应头
      response.setHeader("content-type","text/html;charset=utf-8");
      //或者使用简单的形式,设置编码,是在获取流之前设置
      response.setContentType("text/html;charset=utf-8");

ServletContext对象

  • 概念:代表整个web应用,可以和程序的容器(服务器)进行通信
  • 获取:

    • 通过request对象获取:request.getServletContext();
    • 通过HttpServlet获取:this.getServletContext();
  • 功能:

    1. 获取MIME类型

      • MIME:在互联网通信过程中定义的一种文件数据类型
      • 格式:大类型/小类型 text/html image/jpeg
      • 获取方法:String getMimeType(String file)
    2. 域对象:共享数据

      • ServletContext对象范围:所有用户所有请求的数据
      • setAttribute(String name,Object value)
      • getAttribute(String name)
      • removeAttribute(String name)
3. 获取文件的真实(服务器)路径
    - 方法:`String getRealPath(String path)`

文件下载

  • 步骤:

    1. 获取下载文件名:request.getParameter()
    2. 将资源按字节输入流读入内存

      • 找到资源在服务器内的路径:ServletContext对象getRealPath方法
      • 读入字节输入流:创建FileInputStream对象,传递路径
    3. 设置response响应头

      • 获取文件类型:ServletContext对象的getMimeType()
      • 设置响应头类型:content-type
      • 设置响应头打开方式:content-disposition
    4. 将输入流数据 写出到 response输出流

      • 获取输出流对象:response.getOutputStream()
      • 设置缓冲区:byte[] buff = new byte[1024*4];
      • 输出数据:write方法
      • 关闭缓冲区:close方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 获取文件名称
String filename = request.getParameter("filename");
// 使用字节输入流加载进入内存
// 找到文件的服务器路径
ServletContext context = this.getServletContext();
String realPath = context.getRealPath("/img/" + filename);
// 字节流关联
FileInputStream fis = new FileInputStream(realPath);

// 指定response的响应头

// 设置响应头类型:content-type
String mimeType = context.getMimeType(filename);
response.setHeader("content-type",mimeType);
// 设置想要头打开方式:content-disposition
response.setHeader("content-disposition","attachmemt;filename="+filename);

// 将输入流数据写出到response输出流
ServletOutputStream sos = response.getOutputStream();
byte[] buff=new byte[1024*8];// 缓冲区
int len=0;
while((len=fis.read(buff))!=-1){
sos.write(buff,0,len);
}
fis.close();
  • 中文乱码
    1. 获取客户端使用的浏览器版本信息
    2. 根据不同的版本信息,设置filename的编码方式不同
Knowledge is priceless, thanks for your support !