JSP 负责显示页面(给人看),Servlet 负责干活(后台处理)
核心作用(4 件事)
- 接收浏览器发来的请求、获取参数(表单提交、url 传参)
- 做业务处理:判断逻辑、调用数据库查 / 增删改
- 把处理完的数据存起来,传给 JSP 页面
- 跳转页面:请求转发 / 重定向 跳到 JSP
完整流程(一定要懂)
浏览器 → 访问 Servlet 地址
- Servlet 拿到表单数据
- Servlet 处理数据
- Servlet 把数据存入
request域 - Servlet转发到 JSP
- JSP 取出数据,生成 HTML 返回浏览器
⚠️ 两个跳转区别(考试高频)
- 请求转发(forward)
request.getRequestDispatcher("/xxx.jsp").forward(request,response);- 地址栏不变
- 共享 request 数据✅,JSP 能拿到 setAttribute 存的数据
- 是服务器内部跳转
2.重定向(sendRedirect)
response.sendRedirect("xxx.jsp");- 地址栏会变
- 不共享 request 数据❌,JSP 拿不到 request 存的值
- 浏览器重新发一次新请求
要把数据传给 JSP,优先用转发 forward
二.完整 Java 代码 MyServlet.java
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //方式1:注解配置(新版本,不用写web.xml) //@WebServlet(urlPatterns = "/myServlet") public class MyServlet extends HttpServlet { //处理GET请求 @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取浏览器传过来的参数,参数名myName String myName = request.getParameter("myName"); //2. 设置响应编码,防止中文乱码!【考试高频】 response.setContentType("text/html;charset=gb2312"); //清除浏览器缓存(课本写的) response.setHeader("Pragma","No‑cache"); response.setDateHeader("Expires",0); response.setHeader("Cache‑Control","no‑cache"); //3. 拿到输出流,向浏览器写html页面 PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head><title>一个简单的Servlet程序</title></head>"); out.println("<body>"); out.println("<h1>一个简单的Servlet程序</h1>"); out.println("<p>"+myName+" 您好,欢迎访问!</p>"); out.println("</body>"); out.println("</html>"); out.flush(); //把缓冲区数据推送出去 } //处理POST请求 @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //post直接调用doGet,共用业务代码 this.doGet(request,response); } }三.方式 A:web.xml 配置(老式配置,考试必考)
<?xml version="1.0" encoding="UTF‑8"?> <web‑app> <!-- 1.声明Servlet:给类起逻辑名字 --> <servlet> <servlet‑name>MyServlet</servlet‑name> <!-- 写完整包名.类名 --> <servlet‑class>com.MyServlet</servlet‑class> <!-- 【拓展:初始化参数】 --> <init‑param> <param‑name>number</param‑name> <param‑value>1000</param‑value> </init‑param> <!-- 【拓展:启动优先级,数字越小,服务器启动越早加载】 --> <load‑on‑startup>10</load‑on‑startup> </servlet> <!-- 2.Servlet映射:访问路径,浏览器输入这个地址访问 --> <servlet‑mapping> <servlet‑name>MyServlet</servlet‑name> <url‑pattern>/myServlet</url‑pattern> </servlet‑mapping> </web‑app>浏览器访问地址:http://localhost:8080/项目名/myServlet?myName=张三?myName=张三就是 get 方式传参数,request.getParameter("myName")拿到 "张三"
四、方式 B:注解配置(@WebServlet,现代开发,不用 web.xml)
直接写在 Servlet 类上面,替代 web.xml 全部配置
import javax.servlet.annotation.WebServlet; //urlPatterns 访问路径,多个路径可以写 {"/a","/b"} @WebServlet(urlPatterns = "/myServlet", loadOnStartup = -1, //加载顺序,‑1代表第一次访问才创建 initParams = {@WebInitParam(name="number",value="1000")} ) public class MyServlet extends HttpServlet{ //doGet doPost方法同上 }Filter 过滤器完整整理(课本案例)
Filter 过滤器:请求到达 Servlet/JSP 之前,先经过过滤器拦截处理,可以做:编码统一、登录校验、访问统计、过滤敏感词。 过滤器链:多个过滤器按顺序执行,
chain.doFilter()把请求传给下一个过滤器 / 目标资源。
一、Filter 核心 3 个方法(实现 Filter 接口必须重写)
public interface Filter{ //①init():过滤器创建的时候执行,【只执行1次】,做初始化,读取init‑param参数 void init(FilterConfig filterConfig); //②doFilter():每一次请求进来都会执行!核心过滤方法 void doFilter(ServletRequest request,ServletResponse response,FilterChain chain); //③destroy():服务器关闭,销毁过滤器,【只执行1次】释放资源 void destroy(); }二、基础过滤器 MyFilter 完整代码(例 6‑2)
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class MyFilter implements Filter { //初始化,服务器启动,过滤器对象创建执行一次 @Override public void init(FilterConfig fConfig) throws ServletException { //初始化处理,读取配置的初始化参数 } //核心过滤,每次请求都跑这里 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //==== 请求到达资源之前,写【预处理代码】(例如设置编码) ==== //放行!向下传递请求,执行下一个过滤器/目标Servlet/JSP chain.doFilter(request, response); //==== 服务器处理完资源之后,回来执行【后处理代码】 ==== } //销毁,服务器关闭执行一次,释放资源 @Override public void destroy() { //释放资源 } }三、配置过滤器两种方式
方式 1:web.xml 配置(考试重点,老式)
<!-- 1.声明过滤器 --> <filter> <filter‑name>MyFilter</filter‑name> <!-- 完整包名.类名 --> <filter‑class>com.lyq.MyFilter</filter‑class> <!-- 初始化参数(可选) --> <init‑param> <param‑name>xxx</param‑name> <param‑value>123</param‑value> </init‑param> </filter> <!--2.过滤器映射:哪些url要被这个过滤器拦截 --> <filter‑mapping> <filter‑name>MyFilter</filter‑name> <!--拦截路径: /* 拦截全部请求;/index.jsp只拦截首页 --> <url‑pattern>/MyFilter</url‑pattern> </filter‑mapping>方式 2:注解配置(现代开发,替代 web.xml)
import javax.servlet.annotation.WebFilter; //urlPatterns拦截路径,/*代表拦截所有访问 @WebFilter(urlPatterns = "/*") public class MyFilter implements Filter{ //三个方法同上 }四、课本案例:网站访问计数器 CountFilter(例 6‑4)
功能:统计网站访客,初始访问数量 5000,存到ServletContext(application),所有页面共享。
1.CountFilter.java 代码
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class CountFilter implements Filter { private int count; //访问计数 @Override public void init(FilterConfig filterConfig) throws ServletException { //读取web.xml配置的初始化参数count String param = filterConfig.getInitParameter("count"); count = Integer.valueOf(param); //字符串转数字 } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { count++; //访问数+1 //ServletRequest转成HttpServletRequest HttpServletRequest req = (HttpServletRequest) request; //拿到全局ServletContext,对应JSP的application对象 ServletContext context = req.getSession().getServletContext(); //把计数存入全局域,所有页面共享 context.setAttribute("count",count); //放行,访问目标页面 chain.doFilter(request, response); } @Override public void destroy() { } }2.web.xml 配置 CountFilter
<filter> <filter‑name>CountFilter</filter‑name> <filter‑class>com.lyq.CountFilter</filter‑class> <!--初始化参数,初始访问数5000 --> <init‑param> <param‑name>count</param‑name> <param‑value>5000</param‑value> </init‑param> </filter> <!--拦截index.jsp首页 --> <filter‑mapping> <filter‑name>CountFilter</filter‑name> <url‑pattern>/index.jsp</url‑pattern> </filter‑mapping>3.index.jsp 页面(取出计数显示)
<body> <h2>欢迎光临,<br> 您是本站的第【${applicationScope.count}】位访客! </h2> </body>五、字符编码过滤器(开发最常用!解决中文乱码)
@WebFilter("/*") //拦截全部请求 public class EncodingFilter implements Filter{ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //统一设置请求编码 request.setCharacterEncoding("utf‑8"); //统一设置响应编码 response.setContentType("text/html;charset=utf‑8"); //放行 chain.doFilter(request,response); } @Override public void init(FilterConfig filterConfig) {} @Override public void destroy() {} }字符编码过滤器 + 添加图书 Servlet 案例整理(课本例 6‑5)
一、CharacterFilter 字符编码过滤器
作用:统一设置请求、响应编码,解决中文乱码;编码写在 web.xml 初始化参数,代码不写死 UTF‑8,灵活修改。
1. CharacterFilter.java 完整代码
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class CharacterFilter implements Filter { private String encoding; //保存编码,从web.xml读取 @Override public void init(FilterConfig filterConfig) throws ServletException { //读取web.xml里面 <init‑param> 的encoding参数 encoding = filterConfig.getInitParameter("encoding"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //判断编码参数不为空,才设置 if(encoding != null){ request.setCharacterEncoding(encoding); response.setContentType("text/html;charset="+encoding); } //放行,交给下一个过滤器/Servlet chain.doFilter(request, response); } @Override public void destroy() { encoding = null; } }2. web.xml 配置过滤器
<!--声明过滤器--> <filter> <filter‑name>CharacterFilter</filter‑name> <filter‑class>com.lyq.CharacterFilter</filter‑class> <!--初始化参数:编码UTF‑8--> <init‑param> <param‑name>encoding</param‑name> <param‑value>UTF‑8</param‑value> </init‑param> </filter> <!--过滤器映射,/*拦截全部请求--> <filter‑mapping> <filter‑name>CharacterFilter</filter‑name> <url‑pattern>/*</url‑pattern> </filter‑mapping>考点:
/*代表拦截项目下所有资源(jsp、servlet、html),所有请求自动设置 UTF‑8 编码。
二、AddServlet:处理添加图书(Servlet)
功能:表单 post 提交图书编号、名称、作者、价格,Servlet 接收参数输出。 小技巧:
doGet()里面直接调用doPost(request,response),GET、POST 请求都走 doPost 代码,不用写两份业务。
1. AddServlet.java
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AddServlet extends HttpServlet { private static final long serialVersionUID = 1L; //get请求直接调用post方法 @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); //获取表单提交参数,name属性对应 String id = request.getParameter("id"); String name = request.getParameter("name"); String author = request.getParameter("author"); String price = request.getParameter("price"); //输出结果页面 out.print("<h2>图书信息添加成功</h2><hr>"); out.print("图书编号:"+id +"<br/>"); out.print("图书名称:"+name +"<br/>"); out.print("作者:"+author +"<br/>"); out.print("价格:"+price +"<br/>"); out.flush(); //刷新缓冲区 out.close(); //关闭输出流 } }2. web.xml 配置 AddServlet
<servlet> <servlet‑name>AddServlet</servlet‑name> <servlet‑class>com.lyq.AddServlet</servlet‑class> </servlet> <servlet‑mapping> <servlet‑name>AddServlet</servlet‑name> <url‑pattern>/AddServlet</url‑pattern> </servlet‑mapping>3. index.jsp 表单页面(输入图书信息)
<%@ page language="java" contentType="text/html; charset=UTF‑8" pageEncoding="UTF‑8"%> <html> <body> <form action="AddServlet" method="post"> <table align="center" border="1" width="350"> <tr> <td colspan="2" align="center"> <h2>添加图书信息</h2> </td> </tr> <tr> <td align="right">图书编号:</td> <td><input type="text" name="id"></td> </tr> <tr> <td align="right">图书名称:</td> <td><input type="text" name="name"></td> </tr> <tr> <td align="right">作 者:</td> <td><input type="text" name="author"></td> </tr> <tr> <td align="right">价 格:</td> <td><input type="text" name="price"></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="添 加"> </td> </tr> </table> </form> </body> </html>Servlet 监听器在线用户统计案例整理
https://www.doubao.com/thread/xiYECyrPDZSaWWo2F