目录
2-3-4 了解:和全局初始化参数相关的el内置对象(用不上)
2-3-6 pageContext:获取不是map集合,相当于jsp的pageContext内置对象
3-1-1 导入jar包 (jstl.jar和standard.jar)
4-1-4 ProductService.findAll() 调用dao.findAll()
4-1-5 dao.findAll() 使用beanListHandler()
-
一、jsp
-
1-1 jsp
java 服务器页面
作用:
将内容的生成和信息的展示相分离
运行在服务器端,本质上就是一个serlvet,产生的java文件和class保留在tomcat的word目录下.
-
1-2 jsp脚本
<%..%> java代码片段
<%=..%> 输出表达式 相当于out.print();
<%!...%> 声明成员
-
1-3 jsp的指令
作用:声明jsp页面的一些属性和动作
格式:
<%@指令名称 属性="值" 属性="值"%>
-
1-3-1 jsp指令的分类
page:主要声明jsp页面的一些属性
include:静态包含.
taglib:导入标签库
-
1-3-2 注意
一个页面中可以出现多个指令
指令可以放在任意位置,一般都放在jsp页面最上面.
-
1-4 page指令
-
1-4-1 重要属性:3个
- contentType:设置响应流的编码,及通知浏览器用什么编码打开.设置文件的mimetype
- pageEncoding:设置页面的编码
- import:导入所需要的包
- contentType和pageEncoding联系:
若两者都出现的时候,各自使用各自的编码
若只出现一者,两个都使用出现的这个编码
若两者都不出现,使用服务器默认的编码 tomcat7使用的iso-8859-1
-
1-4-2 了解属性
language:当前jsp页面里面可以嵌套的语言——java
buffer:设置jsp页面的流的缓冲区的大小
autoFlush:是否自动刷新
extends:声明当前jsp的页面继承于那个类.必须继承的是 httpservlet | 其子类
session:设置jsp页面是否可以使用session内置对象 ——默认可以使用
isELIgnored:是否忽略el表达式——默认false,不忽略 ; 忽略时el表达式为普通字符串。
errorPage:当前jsp页面出现异常的时候要跳转到的jsp页面
isErrorPage:当前jsp页面是否是一个错误页面
若值为true,可以使用jsp页面的一个内置对象 exception
-
1-5 include指令
静态包含,就是将其他页面或者servlet的内容包含进来,一起进行编译运行.生成一个java文件.
格式:
<%@include file="相对路径或者是内部路径" %>
例如:
<%@include file="/jsp/include/i1.jsp" %>
-
1-5-1 路径
相对路径:
./ 或者什么都不写 当前路径
上一级路径 ../
绝对路径:
带协议和主机的绝对路径
不带协议和主机的绝对路径
/项目名/资源
内部路径:
不带协议和主机的绝对路径去掉项目名
请求转发 静态包含 动态包含
-
1-6 taglib指令:导入标签库
格式:
<%@taglib prefix="前缀名" uri="名称空间" %>
若导入之后
<前缀名:标签 .. >
例如:
<c:if test="(布尔表达式)">输出内容(为真)</c:if>
-
1-7 jsp的内置对象:★★★(9大内置对象)
在jsp页面上可以直接使用的对象
内置对象 类型
- out JspWriter
- request HttpServletRequest
- response HttpServletResponse
- session HttpSession
- exception Throwable
- page Servlet(this)
- config ServletConfig
- application ServletContext 通信
- pageContext PageContext
-
1-8 jsp的域对象:理解
application 整个项目
session 一次会话
request 一次请求(跨页面)
pageContext 一个页面
-
1-9 pagecontext作用:理解
-
1-9-1 pagecontext 域对象
xxxAttribute() get,set
-
1-9-2 操作其他域对象(用得少)
方法:
xxxAttribute(...,int scope);
scope取值:
APPLICATION_SCOPE
SESSION_SCOPE
REQUEST_SCOPE 通过pagecontext往request中放入一个值PAGE_SCOPE
-
1-9-3 获取其他的内置对象
getXxx()
注意:
getRequest():获取request内置对象
-
1-9-4 便捷查找
findAttribute(String key):
依次(次序)从pagecontext,request,session,application四个域中,查找相应的属性,若查找到了返回值,且结束该次查找
若查找不到,返回一个null若 存在多个 同名不同域 的属性,得到小域中的
-
1-10 jsp的动作标签
<jsp:forward>:请求转发 相当于java中 request.getRequestDispatcher(..).forward(..);
<jsp:forward page="内部路径"></jsp:forward>
<jsp:forward page="/jsp/action/for1.jsp"></jsp:forward>
<jsp:include>:动态包含(生成多个.java 和 .class 文件)
就是将被包含页面或者servlet的运行结果包含到当前页面中.
<body> 动态包含页面内容 <hr> i1内容:<jsp:include page="/jsp/action/i1.jsp"></jsp:include> <hr> i2内容:<jsp:include page="/jsp/action/i2.jsp"></jsp:include> </body>
-
1-11 jsp总结图
-
二、el
jsp的内置表达式语言,从jsp2.0开始.
用来替代<%=..%>
作用:
1.获取域中数据 ★
2.执行运算 ★
3.获取常见的web对象
4.调用java的方法
格式:
${el表达式}
-
2-1 获取域中数据:★
-
2-1-1 注意:★
若属性名中出现了"."|"+"|"-"等特殊符号,需要使用scope获取
例如:
${requestScope["arr.age"] }
-
2-1-2 获取简单数据
${pageScope|requestScope|sessionScope|applicationScope.属性名}
以后经常使用: 便捷获取
${属性名}:依次从pageContext,request,session,application查找指定属性,若查找到返回值,结束该次查找
若查找不到,返回"" (空字符串) 老方式:返回 null<% request.setAttribute("rkey", "rvalue"); %> 获取request中的数据:<br> 老方式:<%=request.getAttribute("rkey") %><br/> el方式:${requestScope.rkey }<br/> <hr> <hr> 便捷获取: ${skey },${rkey },${aakey },${akey } <hr>
-
2-1-3 获取复杂数据★★★
获取数组中的数据
${域中的名称[index]}<body> <% //往request域中放入数组 request.setAttribute("arr", new String[]{"aa","bb","cc"}); %> 获取域中的数组:<br> 老方式:<%=((String[])request.getAttribute("arr"))[1] %><br> el方式:${arr[1] }<br> <hr> </body>
获取list中的数据 集合
${域中的名称[index]}<body> <% //往request域中放入list List list=new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); request.setAttribute("list", list); %> 获取域中的list:<br> 老方式:<%=((List)request.getAttribute("list")).get(1) %><br> el方式:${list[1] }<br> list的长度:${list.size() } <hr> </body>
获取map中的数据 获取特殊名字的数据
${域中的名称 . 键名}<body> <% //往request域中放入map Map m=new HashMap(); m.put("username","tom"); m.put("age",18); request.setAttribute("map", m); %> 获取域中的map:<br> 老方式:<%=((Map)request.getAttribute("map")).get("age") %><br> el方式:${map.age }<br> <hr> </body>
获取特殊名字的数据
<body> <% //往域中放入一个简单数据 request.setAttribute("arr.age","18"); %> 获取特殊名字的数据<br> ${requestScope["arr.age"] } </body>
-
2-1-4 javabean导航
javabean:
java语言编写的一个可重用的组件,
狭义上来说就是我们编写的一个普通的java类 例如:User Person
javabean规范:
1.必须是一个公共的具体的类 public class
2.提供私有的字段 private String id;//id称之为字段
3.提供公共访问字段的方法 get|set|is(对于布尔类型)方法
public String getId(){..}
一旦有公共的方法之后,get|set|is之后的内容,将首字母小写,将这个东西称之为bean属性
id就是一个bean属性
4.提供一个无参的构造器
5.一般实现序列化接口 serializable
${域中javabean名称.bean属性} bean属性 与 类属性 不同<% User u=new User(); u.setId("001"); u.setName("tom"); u.setPassword("123"); //将u放入域中 request.setAttribute("user", u); %> 获取域中javabean的id值:<br> 老方式:<%=((User)request.getAttribute("user")).getId() %><br/> el方式:${user.id }<!-- 相当于调用 getXxx() --> <hr> el获取名称:${user.name }<br> 错误演示:${user.username } </body>
-
2-2 执行运算
四则运算 关系(>..) 逻辑(&& ||)
注意:
+:只能进行加法运算,字符串形式数字可以进行加法运算.不能拼接字符串
empty:判断一个容器的长度是否为0(array set list map),还可以判断一个对象是否为空 (new后不为空)
${empty 域中的对象名称}三元运算符
<body> <% request.setAttribute("i", 3); request.setAttribute("j", 4); request.setAttribute("q", "12"); request.setAttribute("k", "k"); List l=null; request.setAttribute("list", l); List ll=new ArrayList(); ll.add("22"); request.setAttribute("list_", ll); User user=null; request.setAttribute("bean", user); User user_=new User(); request.setAttribute("bean_", user_); %> ${i+j }<br/> ${i+q }<br/> ${q+q }<br/> <%-- ${i+k }<br/> --%> <hr> 域中list的长度是否为0:${empty list}<br/><%--true--%> 域中list_的长度是否为0:${empty list_ }<br/><%--false--%> <hr> 域中的bean是否为空:${empty bean }<br/> 域中的bean_是否为空:${empty bean_ }<br/><%--false--%> <hr> ${ 3>4?"yes":"no" }<br/> ${i==3 }<%--true--%> </body>
-
2-3 el的内置对象(了解)
11个
pageScope
requestScope
sessionScope
applicationScope
param
paramValues
header
headerValues
initParam
cookie★
pageContext★
-
2-3-1 注意
除了pagecontext其余对象获取的全是map集合—— 获取: .键名
-
2-3-2 了解:和参数相关的el内置对象
param
paramValues<a href="/day12/el/demo5.jsp?username=tom&password=123&hobby=drink&hobby=sleep">和参数相关的内置对象(了解)</a><br>
<body> ${param.username }<hr> <%--tom--%> ${param }<hr> ${paramValues }<hr> <%--地址--%> ${paramValues.hobby[0] } </body>
-
2-3-3 了解:和请求头相关的el内置对象
header
headerValues<body> ${header }<hr> ${headerValues } <hr> <hr> referer:${header.referer }<br> user-agent:${headerValues["user-agent"][0] } <%--错误:headerValues.user-agent--%> </body>
-
2-3-4 了解:和全局初始化参数相关的el内置对象(用不上)
initParam 在xml中的 content-param 标签内的内容
<context-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </context-param>
<body> ${initParam } <%--encoding=utf-8--%> </body>
-
2-3-5 cookie内置对象
${cookie} 获取map{key=Cookie}
例如:创建cookie
Cookie c=new Cookie("username","tom");
通过${cookie}获取相当于
{username=new Cookie("username","tom")}
相当于map的key是cookie的键
map的value是当前cookie
若想获取名称username的cookie的value值(获取tom)
${cookie.username键.value}--javabean导航
注意:
java中Cookie的api
getName():获取cookie的名称
getValue():获取cookie的value值
我们称name和value是cookie的bean属性使用cookie内置对象:
${cookie.给cookie起名字.value}
例如:
获取jsession的值
${cookie.JSESSIONID.value}
-
2-3-6 pageContext:获取不是map集合,相当于jsp的pageContext内置对象
在jsp页面中获取项目名
${pageContext.request.contextPath}
获取request内置对象 request中的bean属性<a href="${pageContext.request.contextPath }/el/demo8.jsp">pagecontext内置对象获取项目名(掌握)</a><br>
-
2-4 jsp注释
html注释 <!-- -->
注释的内容只在页面上看不到 java代码和html源代码都有
java注释
只在java代码中存在
jsp注释 <%-- --%>
只在jsp页面中存在,翻译成java文件之后就没有了
-
三、jstl
jsp标准的标签库语言
apache的
用来替代java脚本
-
3-1 使用步骤
-
3-1-1 导入jar包 (jstl.jar和standard.jar)
/WebContent/WEB-INF/lib 目录下
-
3-1-2 在页面上导入标签库
<%@taglib prefix="" uri=""%>
例如:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
3-2 jstl的分类
core:核心类库 ★
fmt:格式化|国际化
xml:过时了
sql:过时了
函数库:很少使用
-
3-3 core:掌握
★c:if
★c:forEach
c:set 往域中设置值
c:choose c:when c:otherwise 分支
-
3-4 ★c:if 判断
<c:if test="${el表达式}">满足的时候输出的内容</c:if>
例如:<c:if test="${3>4 }"> 3大于4 </c:if> <c:if test="${3<=4 }"> 3不大于4 </c:if>
-
3-5 ★c:forEach 循环
-
3-5-1 格式1
<c:forEach begin="从那里开始" end="到那里结束" step="步长" var="给变量起个名字" varStatus="循环状态变量">
${i }--${vs.count }--${vs.current }<br>
</c:forEach><c:forEach begin="1" end="10" step="1" var="i"> ${i } </c:forEach> <!-- for(int i=1;i<=10;i++) i -->
varStatus:用来记录循环的状态
常用的属性:
count:记录次数
current:当前遍历的内容
例如:<hr> <c:forEach begin="1" end="20" step="2" var="i" varStatus="vs"> ${i }--${vs.count }--${vs.current }<br> </c:forEach>
-
3-5-2 格式2
<c:forEach items="${el获取域中的容器}" var="n">
${n }
</c:forEach>
例如:<body> <% //往域中放入一个list List l=new ArrayList(); l.add(11); l.add(22); l.add(33); request.setAttribute("list", l); //往域中放入一个set Set s=new HashSet(); s.add("11"); s.add("22"); s.add("33"); request.setAttribute("set", s); //往域中放入一个map Map m=new HashMap(); m.put("username","tom"); m.put("age","18"); request.setAttribute("map", m); %> <c:forEach items="${list }" var="n"> ${n } </c:forEach> <hr> <!-- for(Integer n:list){ i } --> <c:forEach items="${set }" var="n" varStatus="vs"> ${n }--${vs.count }<br> </c:forEach> <hr> <c:forEach items="${map }" var="en"> ${en.key }-- ${en.value }<br/> </c:forEach> </body>
-
3-6 扩展
c:set 和 c:choose
<body> <c:set var="day" value="4"/> <!-- 相当于 pageContext.setAttribute("day",3) 也可以<c:set var="day" value="4" scope="request"/> --> <c:choose> <c:when test="${day==1 }"> 周1 </c:when> <c:when test="${day==2}"> 周2 </c:when> <c:when test="${day==3 }"> 周3 </c:when> <c:otherwise> 其他 </c:otherwise> </c:choose> </body>
函数库:
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <body> ${fn:toUpperCase("hello") } </body>
-
四、案例1-在页面中展示所有商品信息,不要使用jsp的脚本
-
4-1 案例1-步骤分析
-
4-1-0 数据库和表
create database day12;
use day12;
create table product(
id int primary key auto_increment,
pname varchar(20),
price double,
pdesc varchar(20)
);insert into product values (null,'电视机',3200,'液晶曲面大电视');
insert into product values (null,'韭菜盒子',3,'味重请小心食用');
insert into product values (null,'益达',10,'韭菜伴侣');
insert into product values (null,'十三香',12,'守义牌');
-
4-1-1 新建一个项目
导入jar包:
驱动 dbutils c3p0 jstl
导入c3p0配置文件 和工具类
实体类:
private int id;
private String pname;
private double price;
private String pdesc;
-
4-1-2 index.jsp中添加一个连接
<a href="/day1201/findAll">展示所有商品</a>
-
4-1-3 FindAllServlet
调用ProductService.findAll() 返回一个集合 List<Product>——不实现展示商品(太麻烦)
将list放入request域中(由小到大 servlet三个域对象)
请求转发到product_list.jsp(jsp展示方便)/** 展示所有商品 */ public class FindAllservlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.调用service 返回list List<Product> plist=null; try { plist = new ProductService().findAll(); } catch (SQLException e) { e.printStackTrace(); } //2.将list放入request域中 request.setAttribute("list", plist); //3.请求转发 request.getRequestDispatcher("/product_list.jsp").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
-
4-1-4 ProductService.findAll() 调用dao.findAll()
public class ProductService { public List<Product> findAll() throws SQLException { return new ProductDao().findAll(); } }
-
4-1-5 dao.findAll() 使用beanListHandler()
public class ProductDao { public List<Product> findAll() throws SQLException { //创建queryrunner QueryRunner qr=new QueryRunner(DataSourceUtils.getDataSource()); //编写 sqll String sql="select * from product"; //执行sql return qr.query(sql, new BeanListHandler<>(Product.class)); } }
-
4-1-6 在product_list.jsp展示所有商品
使用 c:forEach
使用javabean导航获取里面的数据<body> <table border="1" align="center"> <tr> <td>id</td> <td>商品名称</td> <td>单价</td> <td>描述</td> </tr> <c:forEach items="${list }" var="p"> <tr> <td>${p.id }</td> <td>${p.pname }</td> <td>${p.price }</td> <td>${p.pdesc }</td> </tr> </c:forEach> </table> </body>
-
五、案例2-重写登录案例
需求:
在页面上填写用户名和密码及验证码,点击提交,先校验验证码是否一致.若一致后再去找数据库.顺便记住用户名
技术:
表单
验证码
servlet
request:记住用户名
session::验证码(私有,不能放request中)
cookie:记住用户名
-
5-1 步骤分析
-
5-1-1 数据库和表
create table user(
id int primary key auto_increment,
username varchar(20),
password varchar(20)
);
-
5-1-2 创建一个项目
包结构
jar包
工具类和配置文件
-
5-1-3 表单 login.jsp
表单和验证码的servlet路径映射
<form class="form-horizontal" action="${pageContext.request.contextPath }/login" method="post">
<img src="${pageContext.request.contextPath }/code"/>
添加name属性
记住用户名添加name 和 value属性 <input type="checkbox" name="savename" value="ok"> 记住用户名
显示错误信息 <font color="red">${msg }</font>
记住用户名后查询cookie,显示在页面
<input type="text" class="form-control" id="username" placeholder="请输入用户名" name="username" value="${cookie.saveName.value }"> (在servlet创建cookie时设置的名字)
<form class="form-horizontal" action="${pageContext.request.contextPath }/login" method="post"> <div class="form-group"> <label for="username" class="col-sm-2 control-label">用户名</label> <div class="col-sm-6"> <input type="text" class="form-control" id="username" placeholder="请输入用户名" name="username" value="${cookie.saveName.value }"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">密码</label> <div class="col-sm-6"> <input type="password" class="form-control" id="inputPassword3" placeholder="请输入密码" name="password"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">验证码</label> <div class="col-sm-3"> <input type="text" class="form-control" id="inputPassword3" placeholder="请输入验证码" name="checkCode"> </div> <div class="col-sm-3"> <img src="${pageContext.request.contextPath }/code"/> </div> <div class="checkbox"> <label> <input type="checkbox" name="savename" value="ok"> 记住用户名 </label> </div>
-
5-1-4 表单提交 loginServlet
loginServlet:
获取验证码(从前台传过来和session中)
判断两个验证码是否一致(一次性 判断之后要移除)在CodeServlet中添加代码,保存验证码
//将验证码放入session中 request.getSession().setAttribute("sessionCode", msg);
从request中获取验证码
//1.接受两个验证码 String rCode=request.getParameter("checkCode");
若不一致:
填写错误信息,请求转发到login.jsp
若一致:获取用户名和密码
调用userService的getuserbyusernameandpassword 返回值 User user
判断user是否为空
若为空:填写错误信息,请求转发到login.jsp
若不为空:
继续判断是否勾选了记住用户名
若勾选:
创建cookie 将用户名放入cookie写回浏览器
将user对象放入session中(一次切私有)
页面重定向 index.jsp 展示 xxx:欢迎回来/** * 登录 */ public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.设置编码 request.setCharacterEncoding("utf-8"); //1.接受两个验证码 String rCode=request.getParameter("checkCode"); String sCode=(String) request.getSession().getAttribute("sessionCode"); //一次性验证码 用完之后从session中移除 request.getSession().removeAttribute("sessionCode"); //判断两个验证码是否一致. if(rCode==null || rCode.trim().length()==0||sCode==null){ //验证码有问题 提示信息 页面跳转到login.jsp request.setAttribute("msg", "请重新输入验证码"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } if(!rCode.equalsIgnoreCase(sCode)){ //验证码输入不一致 提示信息 页面跳转到login.jsp request.setAttribute("msg", "验证码输入错误"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } //2.接受用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //3.调用userservice getUserByUsernameAndPwd() 返回值 user User user=null; try { user = new UserService().getUserByUsernameAndPwd(username,password); } catch (SQLException e) { e.printStackTrace(); } //4.判断user if(user==null){ //4.1若user为空 提示信息,请求转发到login.jsp request.setAttribute("msg", "用户名和密码不匹配"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; }else{ //4.2若user 不为空 判断是否勾选了记住用户名 将user放入session if("ok".equals(request.getParameter("savename"))){ //创建cookie username不能是中文 Cookie c= new Cookie("saveName", username); c.setPath(request.getContextPath()+"/"); c.setMaxAge(3600); //写回浏览器 response.addCookie(c); } request.getSession().setAttribute("user", user); } //5.页面重定向 index.jsp response.sendRedirect(request.getContextPath()+"/index.jsp"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
-
5-1-5 其他类
public class UserService { public User getUserByUsernameAndPwd(String username, String password) throws SQLException { // TODO Auto-generated method stub return new UserDao().getUserByUsernameAndPwd(username,password); } }
public class UserDao { public User getUserByUsernameAndPwd(String username, String password) throws SQLException { QueryRunner qr=new QueryRunner(DataSourceUtils.getDataSource()); String sql="select * from user where username = ? and password = ?"; return qr.query(sql, new BeanHandler<>(User.class), username,password); } }
-
总结
- 1 jsp:
作用:
将内容的生成和信息的展示相分离
jsp脚本:
jsp的指令:
作用:声明jsp页面的一些属性或者动作
格式:
<%@指令名 属性=值 属性=值%>
page:
重要属性:
import
pageEncoding:
contentType:
了解:
isErrorPage:一旦值为true 可以使用jsp的一个内置对象 exception
include:静态包含,就是将被包含页面或者servlet的所有内容复制过来一起编译运行,只生成一个java文件
taglib:导入标签库
jsp的内置对象:
out
request
response
session
exception
page
config
application
pageContext
jsp的域对象:
pageContext
request
session
application
pageContext的使用:
1.域对象 xxxAttribute()
2.操作其他域对象 xxxAttribute(..,int scope)
3.获取其他的内置对象 getXxx()
4.便捷查找 findAttribute(String key):依次从小到大
jsp的动作标签
jsp:forward 请求转发
jsp:include 动态包含 是将被包含页面或者servlet运行的结果包含进来
- 2 el: jsp内置的表达式语言
用来替代 <%=...%>
作用:
注意:
若属性名中出现一些特殊符号 "."等等
必须使用:${域Scope["属性名"]}
1.获取域中的数据
获取简单数据
${域Scope.属性名}
${域中的属性名}:依次从小到大
获取复杂数据
数组和list
${域中的容器名称[index]}
map
${域中的容器名称.键名}
javabean导航
${域中的bean名称.bean属性}
2.执行运算
注意:
+:加法运算
empty:判断一个容器的长度是否为0,还能判断一个对象是否为空
${empty 域中的对象}
${not empty 域中的对象}
三元运算符
3.获取常见的web对象
4.调用java的方法
el内置对象(11个)
cookie:
${cookie.cookie的key.value}
pageContext
${pageContext.request.contextPath}://动态获取项目名
- 3 jstl
jsp 标准标签库
apache组织
使用步骤:
1.导入jar包
2.在页面上导入标签库
core:核心包
c:if 判断
c:forEach 循环