Servlet
如何完成Servlet—>并且能够 通过Servlet完成请求过程(使用步骤)
Servlet–>Server Applet :服务器应用程序开发(小服务程序或者服务连接器),连接前端和后端接口的中间层 (Java语言编写)
Servlet:被web容器进行解析(web容器—> tomcat服务器/Jetty服务器/nginx服务器)—>开发一个中间层,首先需要有核心类----->服务器提供了核心jar包 servet-api.jar
Servlet的本质
狭义的Servlet要实现javax.servlet.Servlet接口
一般都是广义的servlet,要实现javax.servlet.Servlet接口的类—>HttpServlet----->自定义一个类继承它,完成业务功能!
一句话:servlet本身就是要实现Servlet接口的java类
Servlet的入门开发步骤
- 创建web项目
- 导入核心的jar包—web服务器本身提供 servlet-api.jar
- 在web项目的src下面,创建包–自定义一个类 继承 HttpServlet
package com.qf.servlet_01;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 自定义一个类继承HttpServlet
*/
public class MyFirstServlet extends HttpServlet {
//重写HttpServlet里面的doGet()和doPost()
/**
* 接收来自web客户端(浏览器)的get请求 (默认就是get请求)
* @param req 请求对象
* @param resp 响应对象
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入服务端程序了") ;
//HttpServletResponse response:响应对象----
//解决服务器响应乱码
response.setContentType("text/html;charset=utf-8");
//给浏览器响应信息
response.getWriter().write("这是我第一个Servlet,响应给你了!");
}
/**
* 接收来自web客户端(浏览器)的post请求
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req,resp);
}
}
- 在web项目下的WEB-INF的web.xml 全局配置文件,配置Servlet,让tomcat解析
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--servlet的xml配置方式-->
<!-- servlet的基本配置-->
<servlet>
<!--建议和当前自定义的类名一致-->
<servlet-name>MyFirstServlet</servlet-name>
<!--当前自定义的servlet的全限定名称-->
<servlet-class>com.qf.servlet_01.MyFirstServlet</servlet-class>
</servlet>
<!--serlvet的映射配置-->
<servlet-mapping>
<!--名称要和上面的servlet的名称一致-->
<servlet-name>MyFirstServlet</servlet-name>
<!--映射路径, 访问后端接口的路径
必须"/"开头,但是不能直接"/"结束
如果启动tomcat报错===LifecycleException: 无法启动组件 就是当前servlet配置里面或者后面注解方式都没有带"/"
-->
<url-pattern>/myFirst</url-pattern>
</servlet-mapping>
</web-app>
- 通过浏览器请求服务器—>服务器tomcat 解析刚才写的servlet
http://localhost:8080/Servlet_Study_war_exploded/myFirst
Servlet的执行原理
0)定义一个类- extends HttpServlet 重写doGet()/doPost()--->web.xml文件中配置Servlet
1)浏览器给服务器发送请求,默认get提交
http://localhost:8080/web标识(上下文路径)/访问后端接口地址 url-pattern ---- url
2)服务器解析地址信息 URL是URI的子集
/web标识(上下文路径)/访问后端接口地址 --uri
2.1)找到web标识上下文路径进入到WEB-INF --->web.xml文件 寻找url-pattern映射路径
2.2)如果找不到404,如果找到了---->url-pattern获取到当前servlet-name (servlet的名称)
2.3)通过servlet-mapping里面的servlet-name--->找到servlet基本配置里面servlet-name
2.4)通过servlet里面的servlet-name---->解析servlet-class的内容---当前类全限定名称
3)web容器通过反射的方式创建当前类对象
Class clazz = Class.forName("当前类全限定名称");
//创建当前类实例
Object obj = clazz.newIntance() ;
4)调用当前类中的方法
Method method = clazz.getDeclaredMethod("doGet/doPost",HttpServletRequest.class,HttpResvletResponse.class)
;
method.setAccessiable(true) ;//抑制Java语言访问检查
method.invoke(obj,request,response) ;
5)响应数据给浏览器
Servlet的生命周期
Servlet是一个单例的线程不安全的;
提供无参构造方法
void init(ServletCon g con g) 初始化
void service(ServletRequest request,ServletResponse response)服务方法,程序入口
void destory() :serv
1)自定义的类 extends HttpServlet(抽象类)
HttpServlet里面的入口service具体的方法进行从写 doGet()/doPost() --实现自己的业务逻辑
2)HttpServlet extends GenericServlet(抽象类)
针对
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; servlet的业务
服务方法(servlet程序入口)做实现
void service(HttpServletRequest request,HttpServletResonse response){
//针对前端不同的提交方式,执行不同的doXX()方法 doGet()/doPost()
}
3)GenericServlet implements Servlet接口
只是将servlet重写了
void init(ServletCong var1) throws ServletException; servlet初始化
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; servlet的业务
服务方法(servlet程序入口)
void destroy();销毁 ----需要被GC来销毁
init(ServletCong)和定义构造函数都执行一次,它是单例的,它是一个线程不安全!
默认对象的创建是在访问浏览器第一次请求请求服务器解析Servlet的时候才去创建对象
而service方法而不断的反复调用:程序入口---要覆盖的里面doGet()/doPost()
让Servlet在tomcat启动的时候就创建并初始化
web.xml中servlet的基本配置---->load-on-starup
<servlet>
<servlet-name>MyLifeServlet</servlet-name>
<servlet-class>com.qf.servlet_02_life.MyLifeServlet</servlet-class>
<!--servlet初始化时机
值越小,优先级越大
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyLifeServlet</servlet-name>
<url-pattern>/life</url-pattern>
</servlet-mapping>
ServletContext 的请求转发
ServletContext称为 “servlet全局对象”,代表整个Web Application
请求转发---->服务器行为,不属于浏览器行为,服务器行为里面牵扯写路径"/直接地址,不需要带上下文路径"
浏览器请求服务器的时候----访问servlet---->解析这个Servlet
通过请求对象获取到分发器RequestDispatcher---->访问指定资源文件"/xxx.html /xx.jsp"
—>调用分发器forward(请求对象,响应对象) ;
简写格式:
请求对象request.getRequestDispatcher(“/xxx.html或者xxx.jsp”).forward(request,response) ;
请求转发特点:
- 地址栏没有变化
- 整个请求转发的过程:request对象是同一个,HttpServletRequest本身就是域对象,可以在不同servlet之间进行数据传输,jsp—是servlet,只要需要用到数据,就可以使用请求转发传递数据!
- 可以访问当前工程下的资源文件也可以访问WEB-INF的资源文件
- 请求转发只能当前工程下的资源文件
- 作用1: 获取上下文路径
当前项目上下文路径/Servlet_Study_war_exploded/—> 浏览器行为 --有地址必须携带上下文路径 (保证永远不会404)
前端 <a href="跳转后端地址就需要书写上下文路径"></a>
<img src="后端地址访问图片 带上下文路径" />
表单提交 action="访问后端接口地址 需要上下文路径"
导入css文件 <link href="xx" rel="stylesheet" />
导入js文件 <script src="xxx.js"></script>
- 作用2:获取全局参数 —后期学习springmvc框架, 读取核心配置文件
- 作用3:请求转发,后端接口—直接跳转前端
- 作用4:作为"域对象",存储数据
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
/**
* ServletContext
* 作用3:请求转发
* 后端接口---直接跳转前端
*/
public class ServletContextDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//完成一个请求转发
//1)获取全局对象ServletContext
/*ServletContext context = this.getServletContext();
//2)public RequestDispatcher getRequestDispatcher(String path) :通过全局对象获取请求分发对象
RequestDispatcher rd = context.getRequestDispatcher("/adv.html") ;//参数访问当前web项目下的资源文件的地址
("/开头") "请求转发 属于服务器行为,不需要带上下文路径,否则404"
//3)RequestDispatcher--->进行分发
//public void forward(ServletRequest request, ServletResponse response) throws ServletException,
java.io.IOException
rd.forward(request,response) ;*/
//上面代码的简写格式:
//HttpServletRequest它的父接口ServletRequest 请求对象-->
//public RequestDispatcher getRequestDispatcher(String path);
//public void forward(ServletRequest request, ServletResponse response) throws ServletException,
java.io.IOException
//request.getRequestDispatcher("/adv.html").forward(request,response); ;
//请求转发访问WEB-INF下的资源文件
request.getRequestDispatcher("/WEB-INF/my.html").forward(request,response); ;
System.out.println("请求转发成功");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
doGet(request,response);
}
}
域对象
域对象:就是在web容器中,不同servlet之间进行数据通信! ----jsp(模板引擎)
四个域对象-------------->分别又是Jsp ->9大内置对象里面四个(重要)
jsp核心:3个指令 9大内置对象(四个域对象) el表达式使用 + “jstl核心标签库”
从小到大
- PageContext page域 :在当前jsp中页面中有效,一旦页面跳转了,就"无了"
- HttpServletRequest: 请求对象 request---->是在一次请求中有效
- HttpSession:会话对象 session对象 ---->是在一次会话中有效
- ServletContext:全局对象 application对象 —是在整个web 应用中有效
通用的方法
public void setAttribute(String name,Object obj):存储数据
public Object getAttribute(String name):域对象中通过存储属性名获取它绑定内容
public void removeAttribute(String name):从域对象移除属性对应的内容
模板引擎:jsp,freemarke(网页静态化)
${}--->el表达式
Spring---开源表达式--->spring的el表达式 ${}
模板引擎:一种数据集,存储一些数据--->类似于Map<K,V>
Map集合对象.put(String name,Stirng value) ;
通过key获取value
请求对象获取前端提交参数的其他方式
/**
* 接受前端提交参数
*/
public class GetDataServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//post请求中文乱码
request.setCharacterEncoding("utf-8") ;
//响应乱码
response.setContentType("text/html;charset=utf-8");
//通过HttpServletRequest ---String getParameter(String name):参数名称获取参数值
//其他方式
//post: key1=value1&key2=value2
// /get:地址栏上 url?key1=value1&key2=value2
//Map<String, String[]> getParameterMap(); 通过request对象获取前端提交的参数的Map集合
Map<String, String[]> map = request.getParameterMap();
//遍历map
//Set <K> keySet() ---遍历键 通过 Object get(K key) :通过键获取值
//Set<Map.entry<K,V>> entrySet(); 通过getKey() getValue()
Set<String> keySet = map.keySet();
for(String key:keySet){
//通过键获取值
String[] value = map.get(key);
System.out.println(key+"---"+ Arrays.toString(value));
}
System.out.println("---------------------------------------");
//Enumeration<String> getParameterNames();获取前端请求所有的参数名称
Enumeration<String> en = request.getParameterNames();
while(en.hasMoreElements()){
String name = en.nextElement(); //获取每一个参数名称
// String getParameter(String var1); 通过参数名称获取值
String value = request.getParameter(name); //获取单个参数
System.out.println(name+"---"+value);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
HttpServletRequest对象引入
/*
通过浏览器请求服务器的时候,获取浏览器携带的一请求头的数据
*/
public class RequestDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* 获取请求头中请求行的内容
* String getMethod(); 获取前端提交方式
* String getRequestURI(); 获取uri /上文路径/请求地址
* StringBuffer getRequestURL(); 获取url http://xxx
* String getProtocol();获取请求的协议版本号
*/
String method = request.getMethod();
System.out.println(method) ;
String uri = request.getRequestURI();
System.out.println(uri) ;
StringBuffer stringBuffer = request.getRequestURL();
System.out.println(stringBuffer.toString());
String protocol = request.getProtocol();
System.out.println(protocol);
System.out.println("-------------------------------------------") ;
//获取请求头的内容
//String getHeader(String var1);请求头的名称获取value
//host:localhost:8080 主机地址
String host = request.getHeader("host");
System.out.println(host);
//"user-agent":用户使用的浏览器类型
String userAgent = request.getHeader("user-agent");
System.out.println(userAgent);
if(userAgent.contains("Firefox")){
System.out.println("使用的火狐浏览器");
}else if(userAgent.contains("Chrome")){
System.out.println("使用的谷歌浏览器");
}else if(userAgent.contains("Trident")){
System.out.println("使用的ie浏览器");
}else{
System.out.println("未知浏览器") ;
}
//请求"referer":地址---- 防止非法访问地址
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
引入响应对象HttpSerlvetResponse
/**
* 通过响应对象给浏览器设置头
*
* Content-Type响应头:设置响应格式 解决中文乱码
* refresh响应头:定时刷新/定时跳转页面
*/
public class ResponseDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//HttpServletResonse
//void setContentType(String var1); 给浏览器响应 指定文本格式html/xml/json
// response.setContentType("text/html;charset=utf-8");//解决而响应中文乱码
//上面的这个方法等价于 :给浏览器设置响应头以及内容
//Content-Type: text/html;charset=utf-8
//void setHeader(String var1, String var2); 设置响应头
// response.setHeader("Content-Type","text/html;charset=utf-8");
//设置refresh响应头
// response.setHeader("refresh","n");n秒数 每 n秒后定时刷新这个这个页面
response.setHeader("refresh","3");
//response.setHeader("refresh","n;上下文路径+请求地址") ; n秒后跳转到指定页面上
// response.setHeader("refresh","3;"+request.getContextPath()+"/login.html");
// response.getWriter().write("响应数据成功!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req,resp);
}
}
响应头
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 通过响应对象给浏览器设置头
*
* Content-Type响应头:设置响应格式 解决中文乱码
* refresh响应头:定时刷新/定时跳转页面
*/
public class ResponseDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//HttpServletResonse
//void setContentType(String var1); 给浏览器响应 指定文本格式html/xml/json
// response.setContentType("text/html;charset=utf-8");//解决而响应中文乱码
//上面的这个方法等价于 :给浏览器设置响应头以及内容
//Content-Type: text/html;charset=utf-8
//void setHeader(String var1, String var2); 设置响应头
// response.setHeader("Content-Type","text/html;charset=utf-8");
//设置refresh响应头
// response.setHeader("refresh","n");n秒数 每 n秒后定时刷新这个这个页面
response.setHeader("refresh","3");
//response.setHeader("refresh","n;上下文路径+请求地址") ; n秒后跳转到指定页面上
// response.setHeader("refresh","3;"+request.getContextPath()+"/login.html");
// response.getWriter().write("响应数据成功!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req,resp);
}
}
重定向
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 ResponseDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//重定向的原理
//http://localhost:8080/Servlet_Jsp_war_exploded/responseDemo2
//当前浏览器请求服务器的时候,HttpServletResponse响应对象给浏览器设置响应头"location" +访问资源文件地址
//响应对象同时给浏览器响应一个状态码 302 :进一步请求(再次发送请求 )
//response.setHeader("location",request.getContextPath()+"/login.html"); //上下文路径必须带上
//void setStatus(int var1);
//response.setStatus(302) ;
//HttpServletRequest域对象存储了一个数据name
//request.setAttribute("name","张三丰") ;
//上面的简写格式
//void sendRedirect(String var1) throws IOException;
// response.sendRedirect(request.getContextPath()+"/getName.jsp");
//response.sendRedirect(request.getContextPath()+"/login.html");
response.sendRedirect(request.getContextPath()+"/WEB-INF/hello.jsp");
System.out.println("重定向成功");
/*
response.getWriter().write("<html>");
response.getWriter().write("<head>");
response.getWriter().write("<title>");
response.getWriter().write("页面");
response.getWriter().write("</title>");
response.getWriter().write("</head>");
response.getWriter().write("</html>");
*/
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
重定向的特点
JSP
Java Server Pages :Java服务页面,通过java语言编写动态脚本,快速和后端数据进行交互,以html静态页面为模板
使用jsp的指令以及一些核心库完成动态内容的生成!
能够书写Java代码的html页面
Jsp的执行原理
1)浏览器发送请求 地址http://localhost:8080/Servlet_Jsp_war_exploded/hello.jsp
2)服务器解析hello.jsp
2.1)hello.jsp----->翻译 hello_jsp.java文件 ---
public fnal class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
class HttpJspBase extends HttpServlet ---jsp本质就是Servlet 2.2)hello_jsp.java 通过jvm 编译 ----hello_jsp.class字节码文件
我们书写<%jsp脚本 %>---都是这个_jspService()jsp的程序入口里面的局部变量....
Jsp的9大内置对象
9大内置对象 其中四个域对象中从小到大的四个域对象
PageContext pageContext (page域)
HttpServletRequest request对象(request域) 使用居多
HttpSession session域(会话对象) 使用居多
ServletContext application域:代表整个web应用程序
HttpServletResponse 响应对象
ServletConfig 配置对象
JspWriter out:输出对象 out.write() /out.print(xx) Object page(this)代表jsp页面(当前类对象)
hrowable 异常
Jsp的三大指令
jsp--->html页面上加入<%@指令名称%>
<%@page contentType="text/html;charset=utf-8" 当前页码的编码格式
import 导入java包路径
language="支持java"
buer="8kb" 默认值 不用写出来,jsp给浏览器输出数据最大支持8kb
isErrorPage="false" 是否为错误页面 ,默认值false
errorPage="错误页面" 当前页码如果发生异常,会跳转到指定错误页面上
isELIgnored="jsp页面上面启用el表达式" 默认值true ${}
%>
静态包含 :file属性可以导入指定jsp页面(公告页面)
将被导入的jsp不会进行翻译和编译,只是将被导入jsp文件内容放进来,节省jsp内存销毁
<%@include file=""%>
<%@taglib prefix="前缀的名称" uri="具体的地址"%>
在项目中需要导入jstl(jsp的核心标签库的jar以及standard.jar 标准库)
<%--引入taglib指令--%>
<%@taglib pre
el表达式
el表达式是来代替 jsp的输出表达式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el表达式</title>
</head>
<body>
<%--
el表达式是来代替 jsp的输出表达式
--%>
<%
//request域对象存储一个数据
/* pageContext.setAttribute("name1","张三丰");
request.setAttribute("name2","红太狼") ;
session.setAttribute("name3","灰太狼") ;
application.setAttribute("name4","懒洋洋") ;*/
//pageContext.setAttribute("name","沸羊羊") ;
//request.setAttribute("name","美羊羊") ;
session.setAttribute("name","蕉太狼") ;
%>
<%--输出表达式--%>
<%--<%=(String)request.getAttribute("name")%>--%>
<br/>
<%--
el表达式 ${域对象.属性名} el表达式里面有很多内置对象
${pageScoope.属性名称} page域
${requestScope.属性名称} request域 相当于Map对象.get(key)---获取value
${sessionScope.属性名称} session域
${applicationScope.属性名称} application域
--%>
<%--
指定域获取里面存储数据
${pageScope.name1}
${requestScope.name2} <%–相当于 jsp 脚本 request.getAttribute("name") 获取value–%>
${sessionScope.name3}
${applicationScope.name4}--%>
<%--${属性名称} 需要从域对象中获取存储数据 ,自动从小到大搜索域对象中存储数据获取到--%>
${name}
</body>
</html>
el表达式操作JavaBean
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el表达式操作JavaBean</title>
</head>
<body>
<%
//模拟后端接口---封装User对象
User user = new User() ;
user.setUsername("红太狼") ;
user.setPassword("123456") ;
user.setAge(25) ;
user.setGender("女") ;
//将user对象存储在request域中
request.setAttribute("user",user);
%>
<%=((User)request.getAttribute("user")).getUsername()%> -
<%=((User)request.getAttribute("user")).getPassword()%> -
<%=((User)request.getAttribute("user")).getAge()%> -
<%=((User)request.getAttribute("user")).getGender()%>
<%--el表达式 代表输出表达式 --%>
<%--
对象导航图语言(Object Graph Navigation Language)
${域对象中的属性名称}--- 获取到实体对象.访问实体类bean属性
${域对象中存储属性名称.调用getXXX()} ---get()去掉,首字母小写
${域对象中存储属性名称.bean属性}
--%>
<hr/>
${user.username} - ${user.password} - ${user.age} - ${user.gender}
</body>
</html>
核心库
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入taglib指令--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>核心库</title>
</head>
<body>
<%--
c:if判断
c:choose:选择结构语句
c:foeach遍历 最常用的
--%>
<%
request.setAttribute("num",10);
User user = new User() ;
user.setUsername("高圆圆") ;
request.setAttribute("user",user);
%>
<%--test属性判断true还是false--%>
<c:if test="${num ==10}">
<h3>num的值是10</h3>
</c:if>
<c:if test="${num !=10}">
<h3>num的值不是10</h3>
</c:if>
<%--
c:if test属性---${empty user} 对象为空
c:if test属性---${not empty user} 对象不为空
--%>
<c:if test="${empty user}">
<h3>当前user对象null值</h3>
</c:if>
<c:if test="${not empty user}">
欢迎,${user.username}
</c:if>
<hr/>
<%
//模拟后端数据 List
List<User> list = new ArrayList<>() ;
User user1 = new User() ;
user1.setUsername("红太狼");
user1.setPassword("123");
user1.setAge(32);
user1.setGender("女");
list.add(user1) ;
User user2 = new User() ;
user2.setUsername("灰太狼");
user2.setPassword("123456");
user2.setAge(35);
user2.setGender("男");
list.add(user2) ;
User user3 = new User() ;
user3.setUsername("小灰灰");
user3.setPassword("1234");
user3.setAge(12);
user3.setGender("男");
list.add(user3) ;
//将list存request域中
request.setAttribute("list",list);
%>
<%--
c:foreach 遍历数据
items="${域对像存储的属性名称对应的内容}"
var="循环中变量名"
--%>
<table border="1px" width="500px" height="500px" align="center">
<tr>
<th>用户名</th>
<th>密码</th>
<th>年龄</th>
<th>性别</th>
</tr>
<c:forEach items="${list}" var="user" > <%--${List}--->每一个user对象获取到了 getAttribute("list")--%>
<%--${user.username}--%>
<tr>
<td>${user.username}</td>
<td>${user.password}</td>
<td>${user.age}</td>
<td>${user.gender}</td>
</tr>
</c:forEach>
</table>
</body>
</html>