JavaWeb项目
开发JavaWeb的程序,必需要严格参照JavaWeb提供的规范来存放我们的资源。结构分析如下:
注:
-
WEB-INF里面的程序是不可见的,必需通过我们的程序访问;
-
现在web.xml并不是必需的;如果项目中需要用到这个web.xml,建议可以从apache-tomcat-xxx\webapps\ROOT\WEB-INF\web.xml拷贝;
-
index是非常特殊的,我们访问到一个文件夹,如果没有确定是哪一个文件,它就会去找名称为index.html或者index.jsp的文件;
部署流程
-
创建一个文件夹oa;
-
在oa下面创建WEB-INF文件夹,在WEB-INF下面分别创建lib和classes文件夹;
-
拷贝web.xml到WEB-INF下面。可以从\apache-tomcat-xxx\webapps\ROOT\WEB-INF\web.xml拷贝;
-
在oa文件夹下面创建一个hello.html;
-
直接把文件夹放到Tomcat的webapps中
-
在server.xml里面进行配置
<!--
docBase:项目的路径
path:项目访问的虚拟路径(可以为/代表没有)
-->
<Context docBase="D:/oa" path="myoa" />
注1:项目需要部署(将项目就交给tomcat保管)才能访问,以上两种部署方式:第一种将整个WebContent文件夹拖到tomcat的webapps下(不推荐,一般开发完项目可以这样做)。第二种使用server.xml配置(方便开发)。
注2:直接访问域名+端口号会根据apache-tomcat-xxx\webapps\ROOT\WEB-INF\web.xml配置文件中的<welcome-file-list>
标签中的顺序匹配
Servlet相关
Servlet是一个接口,一个规范(sun公司并没有去实现它),它的实现就是由各大服务器厂商(Tomcat)去实现;Tomcat是一个javaweb服务器,也是一个Servlet容器;Servlet容器是管理所有Servlet对象的创建,运行,销毁的容器。而Servlet对象也只有在Servlet容器中才能使用。所以如果写了一个Servlet, 那么一定要记住,把这个Servlet交给Tomcat去管理。
Servlet部署流程
-
访问之前一定要确保Tomcat服务要开启,并且要将项目部署到Tomcat,否则出现404错误;
-
用户在浏览器端输入地址。例如:http://localhost:80/servlet/hello 该请求访问的是本地(localhost)端口号为80的程序,即tomcat;
-
Tomcat会到webapps中去找到servlet这个程序或者到server.xml中根据上下文路径
<Context>
中的找到对应的项目 -
然后Tomcat会去找到该项目的配置文件web.xml,然后查看有没有hello这个请求;
-
请求:http://localhost:80/servlet/hello
注:当我们找到这个 /hello 的时候,也就相应的找到了Servlet的名字(servlet-name) : hello
-
Tomcat会根据请求hello去匹配web.xml中的
<url-pattern>
中的值:-
如果没有匹配上就去找这个项目默认web路径下有没有hello这个页面(html或jsp):
如果没有,404;
如果有这个页面,显示页面的内容;
-
如果匹配上了会根据
<Servlet-name>
标签找到相应的Servlet类:
-
-
找到相应的类之后,到缓存区里面去看这个类有没有相应的实例:
-
如果没有,通过反射创建一个实例,并将这个实例放到缓存区:
执行构造方法
执行初始化方法
-
如果有,直接拿到这个实例;
-
-
调用实例的service方法执行业务逻辑处理;
-
如果正常关闭的话,会执行destroy方法,必须要初始化了servlet才会执行destroy方法;
Servlet生命周期
- Servlet容器调用无参构造创建对象:第一次访问 或 项目部署的时候
- Servlet容器调用初始化方法
init()
:第一次访问 或 项目部署的时候 - Servlet容器调用服务方法
service()
、doGet()
、doPost()
:第n次访问 - 对于Tomcat来说,Servlet只有一个(它是单例的,每次创建的Servlet实例都会缓存起来)
- 当我们正常关闭Tomcat的时候,Servlet容器会自动调用销毁方法
destory()
- 构造方法 –> init方法 –> service【每次请求都会执行】 –> destory【正常关闭才执行】
Servlet的实现方式
有两种实现方式:
第一种是实现Servlet接口,重写其中的所有方法;第二种是继承服务器重写Servlet接口的实现类,例如Tomcat中的HttpServlet
public class SecondServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//写功能代码
}
}
处理请求的方式
Get请求与Post请求的区别:
-
get请求时,请求参数放在请求地址url后面,而post提交方式时,请求参数是放在请求数据包中的实体内容中传递;
-
由于地址栏的数据有长度限制,所以Get请求传输的数据量小,一般不能大于2kb,Post请求传输的数据大小没有限制。所以一般文件上传下载使用的是Post请求;
-
Post安全性相对Get较高;
-
get请求的发送时间:
- 直接输入网址
- 点击链接
- 设置表单的提交方式为get或表单的默认提交
post请求的发送时间:
- 设置表单提交方式为
post(method="post")
HttpServlet中的Request与Response对象
HttpServletRequest
HttpServletRequest对象是Servlet的请求对象,可以获取请求数据包/报文中的所有信息。
常用方法:
String getContextPath()
获取上下文路径,<Context path="上下文" ../>
;
String getHeader(String headName)
根据指定的请求头获取对应的请求头的值;
String getRequestURI()
返回当期请求的资源路径URI(上下文路径/资源名);
StringBuffer getRequestURL()
返回浏览器请求地址URL;
String getRemoteAddr()
返回请求服务器的客户端的IP;
String getServletPath()
返回请求,<url-pattern>
中的值;
String getParameter(String name)
根据参数名称,获取对应参数的值;
String[] getParameterValues(String name)
根据参数名称,获取该参数的多个值;
Map<String,String[]> getParameterMap()
返回请求参数组成的Map集合;
void req.setCharacterEncoding("UTF-8")
能够正确获取post请求的中文参数而不出现乱码;
String getProtocol()
获取协议版本HTTP/1.1
String getMethod()
获取请求方式(GET or POST)
int getServerPort()
获取端口号
HttpServletResponse
HttpServletResponse对象是Servlet的响应对象,可以设置响应的文件格式和编码格式,还可以获取输出流。
常用方法:
OutputStream getOutputStream()
获取流的方法一,获取字节输出流(上传下载用)
resp.getWriter()
获取流的方法二,获取字符输出流(字符输出用此流,向页面输出)
resp.setContentType("text/html;charset=UTF-8")
响应页面的文件格式和编码格式
乱码问题
-
向页面输出中文
resp.setContentType("text/html;charset=utf-8")
能够向页面输出中文,""
中的内容不要写错,否则浏览器不认识响应的类型,就会将问题抛给用户; -
获取表单提交的中文数据
针对post请求(请求参数是在实体内容中)
第一种:
req.setCharacterEncoding("utf-8")
必须写在获取参数前,因为如果获取了参数,设置编码无效第二种:
name = new String(name.getBytes("iso-8859-1"), "utf-8");
转码,缺点:太麻烦,每个数据都要转注:两种只能用其一。
-
针对get请求(请求参数是在地址栏上),tomcat8不做处理,如果是tomcat7及其以前:
第一种:
name = new String(name.getBytes("iso-8859-1"), "utf-8");
转码第二种:修改服务器中的配置conf – server.xml –
<Connector>
标签中最后加上属性URIEncoding="utf-8"
注:两种只能用其一 ,以后服务器换了,还需重新配置一次;
-
注意:
-
tomcat8.x之前的默认编码集为ISO-8859-1,tomcat8.x之后默认编码集为UTF-8;
-
对于tomcat8.x以及之后的get请求不需要转码或配置,而Tomcat7需要配置;
-
做项目的时候,项目部署不一定是tomcat,在不能修改web服务器的状态下,可以通过过滤器来解决;
-
Servlet细节
url-pattern的多种匹配方式:
-
精确匹配配置什么就必须写什么,精确匹配中
/
不能少方式一:在一个
<servlet-mapping>
中配置多个<url-pattern></url-pattern>
方式二:在一个Servlet中可以配置配置多个
<servlet-mapping></servlet-mapping>
-
通配符匹配
/*
方式一:通配符匹配:可以拦截到所有的请求
方式二:以指定路径开始的匹配,例如:
/system/
*、/system/user/*
很多时候,我们做权限,就会用到这个拦截 -
后缀匹配(
*.后缀名
)以后缀的方式匹配,注意后缀匹配是没有加
/
的例如:
*.action
、*.do
、*.user
、*.student
、*.admin
等等,此方式不能加/
注:后缀匹配中不要配置
*.html
和*.jsp后缀(与页面的后缀冲突),后缀请求匹配会先匹配web.xml或注解直接找到Servlet,而不会请求对应的html和jsp页面
初始化配置:
-
为了提高第一次访问Servlet的效率,可以将Servlet实例化初始化的时机提前到项目部署的时候,只需要加上
<load-on-startup></load-on-startup>
即可 -
<load-on-startup></load-on-startup>
里面的数字代表就是servlet创建的先后顺序,数字越小,越早启动 -
<servlet-name>
中不能取名叫做default,默认的default对应的servlet就是访问静态资源,如果servlet名字叫做default会把别的功能覆盖掉
注解方式:
通过传统方式每配置一个servlet就需要写一大段的配置信息,所以servlet给我们提供了注解的形式。
通过@WebServlet("/暴露路径")
,将此注解加在servlet控制器类上,就可以代替我们之前的配置,配置方式:如果只有一个路径名称那么可以不加,但是*.xxx
除外。
例如:@WebServlet("/mapping")
、@WebServlet(urlPatterns={"/mapping","/mapping2","/mapping3"})
、@WebServlet(urlPatterns={"/system/user/*"})
、@WebServlet(urlPatterns={"*.xxx"})
、@WebServlet("/*")
线程安全:
Servlet是单例的(同一个线程发送多次请求,只会创建一个对象)。但是Servlet是线程不安全的。当多个线程同时访问同一个成员变量时,若其中一个线程修改了成员变量的值,则会出现线程安全问题。
解决方法一:
实现SingleThreadModel接口,这个方法SingleThreadModel相当于一个把锁,必须等第一个线程计算完,之后线程才进来,这样导致效率低下。
解决方法二:
避免写成员变量。
注:Servlet和Springmvc都是非线程安全的(不要写成员变量);Struts2是线程安全的(可以写成员变量)。
合并Servlet:
如果涉及到一个表中有多个请求(CRUD等),可以将多个Servlet合并为一个。
有三种合并方式:
- 使用后缀匹配
*.
表名实现,后台判断请求的uri区分不同的请求,调用不同的方法处理; - 在表单中使用隐藏域,每个请求写不同的值,后台获取这个隐藏域参数之后再判断,然后调用不同的方法处理;
- 在请求路径后面跟上一个特定参数,后台以这个参数来判断是要执行什么操作。
/**
* dept页面的servlet
* 主要功能:
* 展示数据,增加部门,修改部门,删除部门
* @author bruises
*/
@WebServlet("/dept/*")
public class DeptServlet extends HttpServlet {
/**
* 获取一个私有化的dept的service层对象
*/
private DeptService deptService = new DeptServiceImpl();
/**
* 重写HttpServlet类中的doGet方法
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求内容的字符集
req.setCharacterEncoding("utf-8");
// 请求过来的路径path
String uri = req.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/")+1);
// 判断请求类型
switch (path) {
case "list":
doList(req,resp);
break;
case "add":
doAdd(req,resp);
break;
case "update":
doUpdate(req,resp);
break;
case "update_save":
doSave(req,resp);
break;
case "delete":
doDel(req,resp);
break;
default:
break;
}
}
/**
* 重写HttpServlet类中的doPost方法,设置了输出内容字符集后,直接调用doGet业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
doGet(req,resp);
}
/**
* 查询全量Dept数据的方法,私有化,仅允许doGet与doPost方法调用
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
private void doList(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Dept> listDept = deptService.findAllDept();
req.setAttribute("listDept",listDept);
req.getRequestDispatcher("/WEB-INF/dept.jsp").forward(req,resp);
}
/**
* 获取用户新增的数据,并新增
* @param req
* @param resp
*/
private void doAdd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String manager = req.getParameter("manager");
String tel = req.getParameter("tel");
String num = req.getParameter("num");
Dept dept = new Dept(name, manager, tel, Integer.valueOf(num));
deptService.add(dept);
doList(req,resp);
}
/**
* 删除部门的方法
* @param req
* @param resp
*/
private void doDel(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer id = Integer.valueOf(req.getParameter("id"));
deptService.del(id);
doList(req, resp);
}
/**
* 修改部门数据前,查询并展示部门的方法
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
private void doUpdate(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer id = Integer.valueOf(req.getParameter("id"));
Dept dept = deptService.findById(id);
req.setAttribute("dept",dept);
req.getRequestDispatcher("/dept_edit.jsp").forward(req,resp);
}
/**
* 将前端数据读取并修改部门数据的方法
* @param req
* @param resp
*/
private void doSave(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer id = Integer.valueOf(req.getParameter("id"));
String name = req.getParameter("name");
String manager = req.getParameter("manager");
String tel = req.getParameter("tel");
String num = req.getParameter("num");
Dept dept = new Dept(id, name, manager, tel, Integer.valueOf(num));
deptService.update(dept);
doList(req,resp);
}
}
Servlet交互
Servlet的三大职责:
-
接收请求参数(封装)
-
调用业务方法处理业务(去调用业务service层)
-
响应请求(跳转页面或其他Servlet)
跳转和数据共享的原因:
-
跳转:需要做责任分离(Servlet擅长写代码即处理业务逻辑,jsp擅长展示页面);
-
共享:Http是无状态的,我们跳转的时候数据无法传递,因此需要做数据共享。
跳转
跳转的目标有两种:Servlet跳转其它资源(例如:jsp,html)或者 Serlvet跳转其他Servlet
跳转有两种方式:请求转发与重定向
请求转发Forward:
转发的方式:req.getRequestDispatcher("路径").forward(request, response)
特点:
- 请求只有一次,不会发起多次请求
- 浏览器请求地址不会改变
- 多次转发之间获取到的参数是一样的
- 可以访问受保护的资源
- 只能转发到内部请求,不能访问别人的服务器,不能跨域
- 只有最后一个response会生效
- 即便请求转发走了,后面的代码还是会执行
使用场景:
- 如果想要多个servlet之间共享数据,那么使用请求转发
- 如果想要访问WEB-INF下面的资源,那么使用请求转发
- 查询完列表之后,使用请求转发,转发到列表界面,方便取值
重定向Redirect:
重定向跳转的方式:resp.sendRedirect("路径")
特点:
- 地址栏会发生变化
- 会发送多次请求
- 由于重定向是多次请求,所以多个servlet之间不能共享数据
- 无法访问受保护的资源
- 可以跨域访问
- 每个response都会生效,但是只能看到最后一个,可以通过代码看到是生效了
- 即便重定向走了,还是会执行后续的代码
使用场景:
- 如果想要跨域访问,那么使用重定向
- 做数据的添加、删除、修改操作,使用重定向,因为请求转发可能会造成多次重复提交问题
请求转发(forward) | 重定向(redirect) | |
---|---|---|
访问 WEB-INF | √ | × |
传参数 | √ | × |
访问外网 | × | √ |
重复提交的问题 | 有 | 无 |
路径变化 | 无 | 有 |
代码 | req.getRequestDispatcher(path).forward(req, resp); | resp.sendRedirect(path) |
JSP相关
为了将Servlet中用于表现的部分分离出来,Java使用JSP实现。JSP(java server page)即java服务器端(动态)网页,JSP就是Java中用来做动态网页的技术,既然是页面,对于前端代码编写人员来说,可以当成html页面来进行渲染工作。JSP底层就是一个Servlet,在执行的时候先转成Servlet然后同样要经历Servlet的生命周期,Servlet主要是处理业务为主(Java后台代码),JSP主要以表现为主(HTML,CSS,JS等前端代码),Servlet更擅长逻辑的编写,JSP更擅长于数据的显示,最后达到一个目标,servlet里面不要写HTML代码,jsp里面不要写java代码。
JSP原理分析:
-
浏览器第一次访问 hello.jsp 页面,会去找到
conf目录
web.xml里面*.jsp
,在会找到JspServlet -
tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet存储在tomcat目录下work\Catalina\localhost\ROOT\org\apache\jsp路径
-
tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
-
tomcat 会执行该字节码文件,向外提供服务
语法:
-
注释:
<%--这是注释--%>
在jsp翻译成Servlet的时候这个注释就没有了,源代码看不到 -
JSP表达式:
语法:
<%=表达式%>
(实际上就是调用输出流打印到页面上out.print(表达式)
)作用:输出数据到页面上
例子:
<%=new java.util.Date().toLocaleString() %>
转化成Java代码:转换到自动生成Servlet的_jspService方法中out.print(new java.util.Date ().toLocaleString());
-
JSP申明:
语法:
<%! Java代码 %>
作用:定义成员
转化成Java代码:转换成自动生成的Servlet类中的成员
-
JSP脚本:
语法:
<% Java语句1;Java语句2;%>
作用:编写Java逻辑代码;
转化成Java代码:转换到自动生成Servlet的_jspService方法中;
JSP指令:
JSP指令有三种:page(页面指令)、include(包含指令)、taglib(标签指令(JSTL))
-
page指令
格式:
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" ... >
属性:
language="java"
语言只有java,意义不大contentType="text/html; charset=UTF-8"
输出的页面类型,相当于在Servlet里面写resp.setContentType(“text/html;charset=utf-8”)`pageEncoding="UTF-8"
errorPage="/myerror.jsp"
如果当前页面出错,就跳转到对应的页面hello.jsp指定errorPage="/myerror.jsp"
isErrorPage="true"
这个页面是否是错误页面(当要在页面上直接使用exception的时候就可以加上该属性) -
include指令
当每个页面都有导航的时候,只需要使用一个,这个时候就可以使用包含指令。
![JSP指令- include指令](/JSP指令- include指令.jpg)
作用域对象:
在做数据共享的时候,会把数据放到不同的地方。这个不同的地方就是放到不同的作用域里面,作用域对象有四个,JSP四大作用域对象属于9大内置对象里面的,用来共享或传递数据的。作用域有大小,存在哪个作用域对象里,就需要在哪个作用域对象中去取得,即不能跨域获取值。
类 | 对象(叫法) | 范围 |
---|---|---|
PageContext | pageContext | 当前页才能使用,作用不大,值直接使用就是,根本不需要在放到对象里面 |
HttpServletRequest | request | 一次请求(必需请求转发) |
HttpSession | session(多个对象) | 一次会话(只要浏览器或服务器任意一端断开则会话结束) |
ServletContext | application(上下文对象) | 整个应用(有且只有一个对象) |
-
对象获取:
request就是通过请求获得的request对象
session是通过
request.getSession()
获取session对象application,有四种获取方式:
- 第一种是通过request获取,
ServletContext application = getServletContext();
或者req.getServletContext();
- 第二种是通过super获取,
ServletContext app1= super.getServletContext();
- 第三种是通过ServletConfig对象获取,
super.getServletConfig( ) .getServletContext();
- 第四种是通过session获取,
req.getSession() .getServletContext();
- 第一种是通过request获取,
-
语法:
- 拿到作用域中共享后的数据:
作用域对象.getAttribute("key")
- 设置作用域中数据:
作用域对象.setAttribute("key","value")
- 删除作用域中数据:
作用域对象.removeAttribute("key")
- 修改作用域内数据(重新放一次,设置一个相同的key)
作用域对象.setAttribute("key","value")
- 拿到作用域中共享后的数据:
-
ServletContext对象的常用方法:
getContextPath();
拿到上下文路径getRealPath("/");
拿到真实路径(以后做上传下载可以使用)getInitParameter("encoding");
拿到初始化参数(只能拿到全局里面的参数信息)
缺点:
由于 JSP页面内,既可以定义 HTML 标签,又可以定义 Java代码,造成了以下问题:
- 书写麻烦:特别是复杂的页面,既要写 HTML 标签,还要写 Java 代码
- 阅读麻烦:可读性差,html和java代码混合
- 复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…
- 占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存
- 调试困难:出错后,需要找到自动生成的.java文件进行调试
- 不利于团队协作:前端人员不会 Java,后端人员不精 HTML
- 如果页面布局发生变化,前端工程师对静态页面进行修改,然后再交给后端工程师,由后端工程师再将该页面改为 JSP 页面
由于上述的问题, JSP 已逐渐退出历史舞台,以后开发更多的是使用 HTML + Ajax 来替代。有Ajax这个技术后,前端工程师负责前端页面开发,而后端工程师只负责后端代码开发。
EL表达式
EL(Express Language)就是一种表达式语言,可以获取四大作用域中的共享数据,优化了JSP语法中的语句。EL表达式获取作用域中的属性要依靠JavaBean的可读属性即需要有getter方法,否则无法获取。
语法:
-
获取作用域中的属性:使用${key} 获取,会到依次从四个作用域里面去找到key对应的value,先取小的范围的值,小的没有,在取到大的范围的值,如果key不存在,显示为空字符串,而不会显示null值。
如果两个作用域都存在需要取的key,则需要在取值时使用作用域Scope.key,例如
${requstScope.msg}
如果在设置属性值时有特殊字符,例如
KEY.IN.SESSION
则在获取时需要用${sessionScope["KEY.IN.SESSION"]}
获取<%-- JSP语句写法 --%> <%= request.getAttribute("error")==null?"":request.getAttribute("error") %> <%-- EL表达式 --%> ${error}
-
访问JavaBean中的属性:用${对象名.属性名}获取,如果属性名有特殊字符,则通过 ${对象名[“属性名”]} 获取。其中对象名可以从四大作用中获取,而对象名写错会显示空字符串,属性名写错会报错。
// java代码中new一个对象 User user = new User(1L,"张飞","123");// 属性分别为id,ueserName,password
<%-- 获取user对象的JavaBean属性 --%> <p> id:${user.id}<br> user_name:${user.userName}<br> password:${user.password}<br> </p>
<%-- 拿到上下文路径,页面上的href,src等属性可以使用这种方式制定绝对路径 --%> ${pageContext.request.contextPath} <%-- 例如 --%> <a href="${pageContext.request.contextPath}">XXX</a>
-
EL运算符:
<%-- 算数运算符 --%> ${1+2} ${2-1} ${2*3} ${16/5} <%-- 关系运算符 --%> ${16>5} 或 ${16 gt 5} ${1==2} 或 ${1 eq 2} <%-- 逻辑运算符 --%> ${true && true} 或 ${true and true} ${!true} 或 ${not true} <%-- 三目运算符 --%> ${A?B:C} <%-- 其他运算符 --%> ${empty param.name} 如果param.name 为空返回true否则false
JSTL相关
JSTL(JavaServer Pages Standard Tag Library)JSP标准标签库,标签库由标签库和EL表达式语言两个部分组成,用来消除JAVA代码。
使用:
-
导包 jstl.jar 和 standard.jar
-
引用JSTL标签库
标签库 URL 前缀 使用模式 核心标签库 http://java.sun.com/jstl/core c <c:tagname>
国标化标签(I18N) http://java.sun.com/jstl/fmt fmt <fmt:tagname>
SQL标签库 http://java.sun.com/jstl/sql sql <sql:tagname>
XML标签库 http://java.sun.com/jstl/xml x <x:tagname>
函数标签库 http://java.sun.com/jstl/functions fn <fn:tagname>
-
在使用的jsp文件中导入使用语句,例如
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
常用标签
if标签:
<%
request.setAttribute("age",16);
%>
<c:if test="${age > 18}">
age is greater than 18
</c:if>
<c:if test="${age < 18}">
age is less than 18
</c:if>
foreach标签:
<c:forEach items="${users}" var="user" varStatus="s">
${s.count} |||| ${user.id}--${user.username}--${user.password}<br>
</c:forEach>
- items:要循环的集合或数组,必须通过el表达式获取作用域中的数据
- var:用于接收集合中的每一个对象
- varStatus:当前循环的状态,它是个javabean
- index:循环索引,从0开始,相当于我们for循环的下标
- count:计数,从1开始,计算遍历了几次,跟下标的区别是他只能每次增加1
- last:是否是最后一次,只有最后一次的时候才是true
- begin:表示从那里开始展示,从0开始
- end:表示从那里结束展示
- step:步长,表示每次循环+几个
choose标签:
<c:choose>
<c:when test="${age <= 18}">
age is less than 18
</c:when>
<c:when test="${age > 18 && age <= 60}">
age is between 18 and 60
</c:when>
<c:otherwise>
age is greater than 60
</c:when>
</c:choose>