servlet简介:
Servlet 就像食堂里专门负责给你打饭的阿姨。当你想吃饭(发送网页请求),她负责接你的餐盘(接收请求)、问你要什么菜(处理数据)、转身去后厨拿菜(执行业务逻辑),最后把热乎的饭菜递给你(返回网页响应)。一句话来说,servlet就是一个容器。
Servlet 如何工作?🍚 → 🍛
1. 角色定位
- 你是顾客:在浏览器输入网址(比如
www.干饭人.com
),相当于喊:“阿姨,我要一份红烧肉盖饭!” - Servlet 是打饭阿姨:她站在窗口后(服务器里),专门处理你的点餐需求(HTTP 请求)。
2. 处理流程
1️⃣ 接单:你递出餐盘(浏览器发送请求) → 阿姨接过餐盘(Tomcat 等服务器把请求交给 Servlet)。
2️⃣ 问需求:阿姨问:“要辣吗?加卤蛋吗?”(Servlet 读取请求参数,比如 ?spicy=true&egg=1
)。
3️⃣ 干活:阿姨转身切肉、炒菜、盛饭(执行业务逻辑,比如查数据库、算价格)。
4️⃣ 出餐:阿姨把盖饭放你盘子上(生成 HTML/JSON 响应) → 你端走开吃(浏览器渲染页面)。
3. 动态 vs 静态
- 静态内容:像预包装的盒饭(直接读 HTML 文件),阿姨不用现做。
- 动态内容:Servlet 是现炒小灶,比如根据你的会员等级多送一勺肉(个性化数据)。
4. 生命周期(阿姨的职场生涯 📅)
- 入职培训:服务器启动时,阿姨学菜单(Servlet 的
init()
方法)。 - 日常接单:每次请求来,阿姨重复接单-炒菜-出餐(调用
service()
→doGet()
/doPost()
)。 - 退休:服务器关闭时,阿姨收拾灶台(
destroy()
释放资源)。
为什么需要 Servlet?🤔
- 没有阿姨的食堂:你只能吃冷冰冰的预包装盒饭(静态网页),无法现做热菜(无法交互)。
- 有了阿姨:你可以提要求(登录、下单、查数据),她灵活响应(动态生成内容)。
怎么写一个servlet? 🛠️
- 让一个类继承HttpServlet
- 给这个类取个名字。有两种取名方法:第一种是通过注解的方式,就是再类名上面写@WebServlet("/名字")。第二种是在lib文件夹下的xml文件里配置如下:
<!-- 配置Servlet --> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.example.HelloServlet</servlet-class> </servlet> <!-- 映射Servlet访问路径 --> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
- 重写doGet和doPost方法
- 通过req.getParameter和req.getParameterValues拿参数,前者是拿单参数,后者是拿多参数
- 通过resp.setContentType("text/html;charset=utf-8");设置请求和编码格式。建议采用这种方式:因为它同时涵盖了内容类型和编码信息。会自动覆盖之前可能设置的编码,避免冲突。设置了这个才不会导致结果显示乱码。
- 通过使用 resp.getWriter 输出内容。
最后用一个故事来加深下servlet的工作原理吧 场景:你向服务员点餐(提交表单 / URL 参数),服务员记录你的需求(如 “汉堡 + 可乐”)。 对应方法:getParameter() 相当于服务员把你点的餐单拿给厨师。 特点:数据直接来自客户端(你),每次请求都是新的。 request.getAttribute() 场景:厨师做好汉堡后,在盘子上贴了一张纸条(属性):“微辣,加番茄酱”。 对应方法:getAttribute() 相当于服务员从盘子上读取纸条信息,传递给你。 特点:数据由服务器内部设置(厨师),只在当前 “流程”(请求)中有效。
最后附上今天讲解的代码可以更加理解servlet
package com.wk;
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;
//路径:/menuAdd
//请求方式:get
//参数:userName food small
@WebServlet("/menuAdd")//2.取名字:1.这里用的注解 2.在lib文件夹下的xml文件中配置
public class MenuServlet extends HttpServlet {//1.继承HttpServlet
@Override
//3.重写doGet/doPost方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通过
String userName = req.getParameter("userName");
//单参数
String food = req.getParameter("food");
// 设置请求和响应的编码
// resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
/*
使用setContentType("text/html;charset=utf-8"),避免单独设置编码,因为:
它同时涵盖了内容类型和编码信息。
会自动覆盖之前可能设置的编码,避免冲突。
*/
//使用 resp.getWriter 输出内容
resp.getWriter().write(userName + "\t" + food + "\t");
//数组参数
String[] smalls = req.getParameterValues("small");
for (int i = 0; i <smalls.length; i++) {
resp.getWriter().write(smalls[i] + "\t");
}
//req.getRemoteHost() 是HttpServletRequest接口提供的方法,用于获取客户端(即发起HTTP请求的机器)的主机名(域名)
resp.getWriter().write(req.getRemoteHost());
}
}
/*在xml中去配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- 配置Servlet -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.example.HelloServlet</servlet-class>
</servlet>
<!-- 映射Servlet访问路径 -->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!-- 可以配置多个Servlet和映射 -->
<servlet>
<servlet-name>another</servlet-name>
<servlet-class>com.example.AnotherServlet</servlet-class>
<param-value>UTF-8</param-value>
</servlet>
<servlet-mapping>
<servlet-name>another</servlet-name>
<url-pattern>/another</url-pattern>
</servlet-mapping>
<!-- 配置欢迎页 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
*/
/*
1.其他知识:
2.如何编写一个servlet:1.继承,2.doGet/doPost3.resp.getWriter
3.JSP脚本:<% java代码 %>、<%=表达式 %>:相当于out.print(表达式)。
4.conf:配置文件。webapp:静态/动态资源目录,如果要部署就放到里面。lib:放一些jar包等写好的文件。bin:二进制文件。
5.配置路径:servletmapping里面配。
6.request重定向:2次。forword:1次。:重定向(Redirect):客户端向服务器发送请求 → 服务器返回 302 状态码和新 URL → 客户端再向新 URL 发送第二次请求。共两次请求,地址栏会变化。
转发(Forward):客户端发送一次请求 → 服务器内部将请求转发到另一个资源 → 直接返回结果给客户端。仅一次请求,地址栏不变。
7.req.getParameter:获取前端传来的数据。req.getAttribution:获取作用域内的变量。
request.getParameter()
场景:你向服务员点餐(提交表单 / URL 参数),服务员记录你的需求(如 “汉堡 + 可乐”)。
对应方法:getParameter() 相当于服务员把你点的餐单拿给厨师。
特点:数据直接来自客户端(你),每次请求都是新的。
request.getAttribute()
场景:厨师做好汉堡后,在盘子上贴了一张纸条(属性):“微辣,加番茄酱”。
对应方法:getAttribute() 相当于服务员从盘子上读取纸条信息,传递给你。
特点:数据由服务器内部设置(厨师),只在当前 “流程”(请求)中有效。
String username = req.getParameter("username");
// 将用户对象放入请求属性(服务器内部数据)
req.setAttribute("currentUser", user);
8.pageEncoding:相应编码。filter实现:1.servlet的implements Filter 2.重写doFilter方法。
package com.example.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
// 使用注解配置Filter,拦截所有请求
@WebFilter("/*")
public class EncodingFilter implements Filter {
private String encoding;
// 初始化方法,获取Filter配置参数
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 从web.xml获取配置的编码,默认为UTF-8
encoding = filterConfig.getInitParameter("encoding");
if (encoding == null) {
encoding = "UTF-8";
}
}
// 核心过滤方法
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 设置请求编码
request.setCharacterEncoding(encoding);
// 设置响应编码
response.setCharacterEncoding(encoding);
response.setContentType("text/html; charset=" + encoding);
// 继续处理请求
chain.doFilter(request, response);
}
// 销毁方法
@Override
public void destroy() {
// 释放资源
}
}
9.三大作用域:session/request(这个是默认的)/Application。
作用域类型 接口 / 类 作用范围 生命周期
request HttpServletRequest 一次请求(包括转发)的范围,不同请求之间数据不共享。 从请求开始到请求结束(例如请求处理完成或页面跳转后销毁)。
session HttpSession 同一用户的多次请求共享数据(基于会话,通常通过 Cookie 或 URL 重写识别)。 从用户首次访问创建会话开始,到会话超时(默认 30 分钟)或手动销毁为止。
application ServletContext 整个 Web 应用共享数据,所有用户、所有请求均可访问。 从 Web 应用启动(服务器加载应用)到服务器关闭(应用卸载)期间持续存在。
10.生命周期:初始化,服务,销毁。
用户请求JSP → 服务器检查是否已编译 → 未编译 → 转译为Servlet → 编译Servlet → 实例化Servlet →
调用jspInit() → 调用_jspService() → 生成响应 → 保留Servlet实例 → 后续请求直接调用_jspService()
↑
│
服务器关闭或JSP修改 → 调用jspDestroy() → 销毁Servlet实例 ← 重新加载JSP时
11.JSP编译后是_jspService。
12.500:服务器内部错误。200:正常访问。把三大作用域设置方法。拿多个就是getParameterValues,拿单个就是getParamater。JSP生命周期。
13.需要页面回显的时候:用JSP。不需要回显的时候:servlet。
14.servlet:
Servlet-Mapping:用来替代webservlet的映射。
*/