Java学习路线-48:Servlet学习

举报
彭世瑜 发表于 2021/08/14 01:19:18 2021/08/14
【摘要】 课时1 Servlet是什么 Servlet作用是处理请求 接收请求 处理请求 完成响应 课时2 实现Servlet方式 依赖 <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId>...

课时1 Servlet是什么

Servlet作用是处理请求
接收请求
处理请求
完成响应

课时2 实现Servlet方式

依赖

<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope>
</dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

实现方式

// 实现接口:
javax.servlet.Servlet

// 继承类:
javax.servlet.GenericServlet

// 继承类:
javax.servlet.HttpServlet

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

继承示例
AServlet.java

import javax.servlet.*;
import java.io.IOException;

public class AServlet implements Servlet{ // 创建时执行 @Override public void init(ServletConfig servletConfig) throws ServletException { } // 获取配置信息 @Override public ServletConfig getServletConfig() { return null; } // 处理请求 @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { } // 获取servlet信息 @Override public String getServletInfo() { return null; } // 销毁前调用 @Override public void destroy() { }
}


  
 
  • 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
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

课时3 Servlet的生命周期

生命周期

init 实例化调用
service 每次处理请求都调用
destroy 销毁调用

  
 
  • 1
  • 2
  • 3

特性
(1)单例,每个类只有一个对象
(2)线程不安全,效率最高

Servlet类由用户自定义,对象由服务器来创建,并有服务器调用对应的方法

浏览器访问Servlet
给Servlet配置一个路径
web.xml

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

<web-app> <!-- 注册 Servlet,帮助web服务器反射该类 --> <servlet> <servlet-name>demo</servlet-name> <servlet-class>AServlet</servlet-class> </servlet> <!-- 映射 Servlet 资源,用url-pattern元素标示 URL --> <servlet-mapping> <servlet-name>demo</servlet-name> <url-pattern>demo</url-pattern> </servlet-mapping>
</web-app>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

目录结构

webapp └── WEB-INF ├── classes │   └── AServlet.class └── web.xml

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

课时4 ServletConfig介绍


interface ServletConfig{ // 获取servlet-name中的内容 String getServletName() // 获取Servlet上下文对象 ServletContext getServletContext() // 获取指定初始化参数值 String getInitParameter(String name) // 获取所有初始化参数值 Enumeration<String> getInitParameterNames() 

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
<servlet> <init-param> <param-name>name</param-name> <param-value>Tom</param-value> </init-param>
</servlet>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

获取参数

@Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println(servletConfig.getInitParameter("name")); }

  
 
  • 1
  • 2
  • 3
  • 4

课时5 ServletRequest和Servletresponse对象

interface ServletRequest;

interface ServletResponse;

  
 
  • 1
  • 2
  • 3

课时6 GenericServlet介绍

GenericServlet可以只覆写service方法,不用全写

基本原理

import javax.servlet.*;
import java.io.IOException;

public class AServlet implements Servlet { private ServletConfig config = null; @Override public void init(ServletConfig servletConfig) { this.config = servletConfig; this.init(); } // 实现此方法,初始化后可以调用 public void init() { } @Override public ServletConfig getServletConfig() { return this.config; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { } @Override public String getServletInfo() { return null; } @Override public void destroy() { }
}


  
 
  • 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
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

使用示例

import javax.servlet.*;
import java.io.IOException;

public class AServlet extends GenericServlet { @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException { servletResponse.getWriter().write("<h2>hello<h2>"); }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

课时7 HttpServlet介绍

源码


package javax.servlet.http;


public abstract class HttpServlet extends GenericServlet { // 重写 protected void doGet(HttpServletRequest req, HttpServletResponse resp); // 重写 protected void doPost(HttpServletRequest req, HttpServletResponse resp); protected void service(HttpServletRequest req, HttpServletResponse resp); public void service(ServletRequest req, ServletResponse res){ if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; this.service(request, response); } else { throw new ServletException("non-HTTP request or response"); } }
}


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

使用示例: 接收GET请求

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("<h2>hello</h2>"); }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

课时8 Servlet的细节

1、非线程安全
一个Servlet类只有一个实例对象,不是线程安全的,工作效率高

(1)不要在Servlet中创建成员,创建局部变量即可
(2)可以创建无状态成员
(3)可以创建有状态的成员,但是状态必须为只读

2、创建时启动
默认情况下,服务器会在第一次访问Servlet时创建实例对象

给load-on-startup设置一个非负整数
正数的值越小,启动该servlet的优先级越高

可以配置创建时启动

<servlet> <servlet-name>servletName</servlet-name> <load-on-startup>0</load-on-startup>
</servlet>

  
 
  • 1
  • 2
  • 3
  • 4

3、url-pattern
可以有多个访问路径
可以使用前缀或者后缀通配符*

<servlet> <servlet-name>servletName</servlet-name> <!-- 后缀匹配 --> <url-pattern>/demo/*</url-pattern> <!-- 前缀匹配 --> <url-pattern>*.do</url-pattern> <!-- 匹配所有url --> <url-pattern>/*</url-pattern>
</servlet>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

课时9 在conf下的web.xml文件内容介绍

${CATALINA_HOME}/conf/web.xml

<!-- 优先级最低 -->
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- 过期时间30分钟 -->
<session-config> <session-timeout>30</session-timeout>
</session-config>

<!-- 类型映射 -->
<mime-mapping> <extension>xml</extension> <mime-type>application/xml</mime-type>
</mime-mapping>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

课时10 Servlet与反射

Servlet通过反射,获取配置文件的类名,进行实例化和方法调用

课时11 ServletContext概述

一个项目只有一个ServletContext对象
可以在多个Servlet中传递对象

Tomcat启动时创建,关闭时销毁

课时12 获取ServletContext对象

获取ServletContext


class ServeletConfig{ ServletContext getServletContext();
}

class GenericServlet{ ServletContext getServletContext();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

课时13 演示ServletContext

域对象: 在多个Servlet中传递数据

class ServletContext{ // 设置 多次调用会覆盖 void setAttribute(String name, Object vlaue); // 获取 Object getAttribute(String name); // 移除 void removeAttribute(String name); // 获取全部属性名称 Enumeration getAttributeNames();
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

例如: AServlet的数据可以传递到BServlet
AServlet.java

package com.pengshiyu;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String name = request.getParameter("name"); ServletContext context = getServletContext(); context.setAttribute("name", name); response.getWriter().write("<h2>" + name +"</h2>"); }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

BServlet.java

package com.pengshiyu;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class BServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { ServletContext context = getServletContext(); String name = (String)context.getAttribute("name"); response.getWriter().println(name); }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

课时14 ServletContext获取公共的初始化参数

Servlet只能获取自己的初始化参数
ServletContext获取公共的初始化参数

<web-app> <context-param> <param-name>key</param-name> <param-value>value</param-value> </context-param>
</web-app>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
package com.pengshiyu;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class BServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { ServletContext context = getServletContext(); String name = context.getInitParameter("key"); response.getWriter().println(name); }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

课时15 ServletContext获取资源相关方法

以webapp文根目录

ServletContext context = getServletContext();

// 获取绝对路径
String path = context.getRealPath("/index.html");

// 获取文件后转为输入流
InputStream in = context.getResourceAsStream("/index.html");

// 获取目录下的文件
Set<String> set = context.getResourcePaths("/");
// [/hello.html, /WEB-INF/]

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

课时16 网站访问量统计小案例

使用ServletContext对象共享统计数据

package com.pengshiyu;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class BServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { ServletContext context = getServletContext(); Integer count = (Integer) context.getAttribute("count"); if (count == null) { count = 1; // 第一次访问 } else { count++; } response.setContentType("text/html; charset=UTF-8"); response.getWriter().println("<h2>第"+count+"次访问</h2>"); context.setAttribute("count", count); }
}


  
 
  • 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
  • 26

课时17 获取类路径下的资源

依赖

<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version>
</dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

代码实例

package com.pengshiyu;

import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class Demo { public static void main(String[] args) throws IOException { Class<Demo> clazz = Demo.class; // 1、相对于.class所在目录 InputStream input1 = clazz.getResourceAsStream("1.txt"); System.out.println(IOUtils.toString(input1, StandardCharsets.UTF_8)); // 2、相对于/classes InputStream input2 = clazz.getResourceAsStream("/2.txt"); System.out.println(IOUtils.toString(input2, StandardCharsets.UTF_8)); ClassLoader loader = clazz.getClassLoader(); // 3、相对于/classes InputStream input3 = loader.getResourceAsStream("3.txt"); System.out.println(IOUtils.toString(input3, StandardCharsets.UTF_8)); }
}


  
 
  • 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
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

课时18 BaseServlet

一个Servlet中可以有多个请求处理方法

BaseServlet.java

package com.pengshiyu;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

public class BaseServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String methodName = req.getParameter("method"); if(methodName == null || methodName.trim().isEmpty()){ throw new RuntimeException("method is null or empty"); } System.out.println(methodName); // 通过参数获取方法 Class clazz = this.getClass(); Method method = null; try { method = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); } catch (NoSuchMethodException e) { throw new RuntimeException("方法获取失败"); } // 调用方法 try { method.invoke(this, req, resp); } catch (Exception e) { throw new RuntimeException("调用失败"); } }
}


  
 
  • 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
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

AServlet.java

package com.pengshiyu;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AServlet extends BaseServlet { public void getAge(HttpServletRequest request, HttpServletResponse response) throws IOException { response.getWriter().print("getAge"); } public void getName(HttpServletRequest request, HttpServletResponse response) throws IOException { response.getWriter().print("getName"); }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

调用时传入查询参数
http://localhost:8080/demo/hello?method=getAge

文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。

原文链接:pengshiyu.blog.csdn.net/article/details/104365513

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。