jsp和EL表达式以及JSTL表达式
1、什么是JSP
Java server page(java服务器页面). JSP本质就是Servlet
它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。
JSP=html(js,css)+java+jsp特有的内容
2、JSP产生的原因
需求: 我们要向页面动态输出一个表格. 发现特别的繁琐
servlet在展示页面的时候,相当的繁琐。sun公司为了解决这个问题,参照asp开发了一套动态网页技术jsp。
也就是说jsp就是为了解决servlet展示前端信息太过于麻烦的问题的。
3、执行原理
JSP会翻译(通过默认的JspServlet,JSP引擎)成Servlet(.java),Servlet编译成class文件
JSP执行流程
1、第一次访问的xxx.jsp时候,服务器收到请求,JspServlet会去查找对应的jsp文件
2、找到之后,服务器会将这个jsp文件转换成java文件(Servlet)
3、服务器编译java文件,生成class文件
4、服务器运行class文件,生成动态的内容
5、服务器收到内容之后,返回给浏览器
jsp本质上就是servlet
对应的原理图如下所示:
这里可以在idea中看一下
首先先写一个jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/DotFogetServlet" method="post">
用户名:<input type="text" name="username" value="${cookie.username.value}"/><br/>
密 码:<input type="password" name="password"/><br/>
<%--<input type="checkbox" name="remember" onclick="" /> 记住用户名<br/>--%>
<input type="checkbox" value="uncheck" name="check" onclick="this.value=((this.value=='uncheck')?'checked':'uncheck')"/> 记住用户名<br/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
启动项目之后,会在控制台显示出来:
Using CATALINA_BASE: "C:\Users\liguang\AppData\Local\JetBrains\IntelliJIdea2020.3\tomcat\90d7a63c-992b-42e2-a921-c2e974066439"
那么jsp生成的java文件会在这个目录下面显示
如果没有访问,那么这个目录下是找不到对应的文件的,只有在访问的时候,才会生成。这也就对应了上面的原理图
那么第一次访问之后,会产生如下文件:
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class login_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("\r\n");
out.write("<form action=\"");
out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${pageContext.request.contextPath}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
out.write("/DotFogetServlet\" method=\"post\">\r\n");
out.write(" 用户名:<input type=\"text\" name=\"username\" value=\"");
out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${cookie.username.value}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
out.write("\"/><br/>\r\n");
out.write(" 密 码:<input type=\"password\" name=\"password\"/><br/>\r\n");
out.write(" ");
out.write("\r\n");
out.write(" <input type=\"checkbox\" value=\"uncheck\" name=\"check\" onclick=\"this.value=((this.value=='uncheck')?'checked':'uncheck')\"/> 记住用户名<br/>\r\n");
out.write(" <input type=\"submit\" value=\"登录\"/>\r\n");
out.write("</form>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
既然说jsp是servlet,那么jsp的类也一定会继承servlet类,并且一定会有service方法!我们发现,jsp继承了org.apache.jasper.runtime.HttpJspBase,查阅这个类的源码可以发现这样一行代码:
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage
由此我们得知,jsp通过继承httpServlet,然后继承了servlet类。
所以说jsp本质上就是servlet
我们可以看到上面的jsp在进行输出的时候,是利用流对象在进行写出,这跟利用servlet写出数据是一样的操作。
4、jsp语法
既然说jsp是代替servlet来对数据进行输出的,那么看看jsp中的语法
我们可以通过JSP脚本在JSP页面上编写Java代码. 一共有三种方式:
类型 | 翻译成Servlet对应的部分 | 注意 |
---|---|---|
<%...%>:Java程序片段 | 翻译成Service()方法里面的内容, 局部的 | |
<%=...%>:输出表达式 | 翻译成Service()方法里面的内容,相当于调用out.print() | 输出表达式不能以;结尾 |
<%!...%>:声明成员变量 | 翻译成Servlet类里面的内容 |
总结起来就是:
- <%....%> 翻译成了service()方法里面的局部内容
- <%=....%> 输出, 翻译成了service()方法里面的out.print()
- <%!...%> 翻译成了servlet类里面的全局内容
分别写三个例子来进行说明:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>demo1</title>
</head>
<body>
<%--局部变量--%>
<% int a = 3; %>
<%--打印java的变量值到网页上--%>
<%=a %>
<%--全局变量--%>
<%! int b = 33; %>
<%--如果写大段的代码怎么做--%>
<%
for(int i = 0 ; i < 10 ; i++){
%>
<%=i%><br/>
<h2><font color="red">aaaaaaaaaaaaaa</font></h2><br/>
<%
}
%>
</body>
</html>
那么访问一下,看一下对应的jsp页面对应的java文件
public final class jspdemo1_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
int b = 33;
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>demo1</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write('\r');
out.write('\n');
int a = 3;
out.write("\r\n");
out.write("\r\n");
out.write('\r');
out.write('\n');
out.print(a );
out.write("\r\n");
out.write("\r\n");
out.write('\r');
out.write('\n');
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
for (int i = 0; i < 10; i++) {
out.write('\r');
out.write('\n');
out.print(i);
out.write("<br/>\r\n");
out.write("<h2><font color=\"red\">aaaaaaaaaaaaaa</font></h2><br/>\r\n");
}
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
可以看到
<% int a = 3; %>
定义的位置是在方法位置内
<%! int b = 33; %>
这个是属于servlet中的成员变量类
而对应的java片段,在servlet中显示的是:
for (int i = 0; i < 10; i++) {
out.write('\r');
out.write('\n');
out.print(i);
out.write("<br/>\r\n");
out.write("<h2><font color=\"red\">aaaaaaaaaaaaaa</font></h2><br/>\r\n");
}
再写一个jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>demo1</title>
</head>
<body>
<%! int count = 250;%>
<%= "count对应的值是:"+count %>
<br>
<br>
<% String hello = "hello,world"; %>
<%= "hello对应的值是:"+hello %>
</body>
</html>
查看页面输出:
count对应的值是:250
hello对应的值是:hello,world
写一个循环看看
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>demo1</title>
</head>
<body>
<%
List<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
for (Integer integer : integers) {
%>
<%="循环遍历对应的值是:"+integer%>
<br/>
<%
}
%>
</body>
</html>
查看页面对应的输出:
循环遍历对应的值是:1
循环遍历对应的值是:2
循环遍历对应的值是:3
4、EL表达式
4.1、什么是EL表达式
Expression Language:表达式语言, jsp2.0之后内置在jsp里面
目的:为了使JSP写起来更加简单, 取值(取的域对象里面存的值)更加简单。(代替脚本 <% %>)
4.3、EL用途
语法:
${el表达式}
1.获取数据. 获取的是域(request,session,ServletContext)对象中存储的数据
2.EL执行运算
所以下面将会一个一个的来对其做执行操作
4.4、使用EL表达式获取得到数据
4.4.1、获取得到数据的几种形式
- 获取简单数据类型数据(基本类型,字符串)
- 获取数组
- 获取list
- 获取Map
- 获取bean
1、获取简单数据类型数据
语法:
${requestScope|sessionScope|applicationScope.属性名};
快捷写法:
${属性名}
属性名就是存在域对象里面的key
来一个对应的例子来进行说明:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>获取得到简单数据</title>
</head>
<body>
<body>
<%
//request存数据
request.setAttribute("rkey","rrr");
//session存数据
session.setAttribute("skey","sss");
//ServletContext存数据,jsp里面叫application
application.setAttribute("akey","aaa");
request.setAttribute("key","request");
session.setAttribute("key","session");
%>
取出request域里面存的数据:<br/>
老方式:<%=request.getAttribute("rkey") %> <br/>
El方式:${requestScope.rkey} <br/>
简单方式El方式:${rkey} <br/>
<hr/>
取出session域里面存的数据:<br/>
老方式:<%=session.getAttribute("skey") %> <br/>
El方式:${sessionScope.skey} <br/>
简单El方式:${skey} <br/>
<hr/>
取出ServletContext域里面存的数据:<br/>
老方式:<%=application.getAttribute("akey") %> <br/>
El方式:${applicationScope.akey} <br/>
简单El方式:${akey} <br/>
<hr/>
<hr/>
<%--直接写域里面的key原理: 从最小的往最大的找,, request-->session--->application--%>
简单的方式(直接写域里面的key):<br/>
${rkey}<br/>
${skey}<br/>
${akey}<br/>
${key}
</body>
</body>
</html>
打开浏览器去访问,查看浏览器结果:
取出request域里面存的数据:
老方式:rrr
El方式:rrr
简单方式El方式:rrr
取出session域里面存的数据:
老方式:sss
El方式:sss
简单El方式:sss
取出ServletContext域里面存的数据:
老方式:aaa
El方式:aaa
简单El方式:aaa
简单的方式(直接写域里面的key):
rrr
sss
aaa
request
最后一个获取的是request,同时验证了上面中的,如果使用EL表达式简单的写法,那么会首先从
request----->session------>servletcontext域对象中来获取得到数据。
2、获取数组
语法: ${key[下标]} key就是域对象里面存的key
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>数组操作jsp</title>
</head>
<body>
<%
Integer[] integersArray = new Integer[]{1,2,3,4,5};
request.setAttribute("array",integersArray);
%>
${array[2]}
</body>
</html>
3、获取得到list
语法:${list属性名[index]}或者${list属性名.get(index)};list属性名就是存入域对象里面的key
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>数组操作jsp</title>
</head>
<body>
<%
List<String> stringList = new ArrayList<>();
stringList.add("hello");
stringList.add("world");
stringList.add("helloworld");
request.setAttribute("list",stringList);
%>
${list[2]}
</body>
</html>
浏览器输出:
helloworld
4、获取得到map
语法:${map属性名.键}或者${map属性名.get("键")},map属性名就是存入域对象里面的key
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>map操作jsp</title>
</head>
<body>
<%
Map<String,Integer> map = new HashMap<>();
map.put("hello",1);
map.put("world",2);
map.put("helloworld",3);
request.setAttribute("map",map);
%>
${map.hello}
</body>
</html>
5、获取得到Bean
语法:${key.javabean属性}
依赖getxxx()方法; eg: getPassword()---去掉get-->Password()----首字母小写--->password
<%@ page import="com.guang.bean.User" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>bean操作jsp</title>
</head>
<body>
<%
User user = new User();
user.setAge(22);
user.setId(33L);
user.setName("lig");
request.setAttribute("user",user);
%>
${user.age}<br>
${user.id}<br>
${user.name}<br>
</body>
</html>
浏览器输出:
22
33
lig
4.4.2、EL运算
上面介绍了EL表达式的数据的存取,下面介绍一个EL的运算
4.1算数运算
+,-,*,/
- +不能拼接字符串.
4.2逻辑运算
< >= <= != ==
4.3关系运算
&& || !
4.4非空判断【重点】
empty,1. 判断一个对象是否为null, 2. 判断集合长度是否为0, 3. 判断一个字符串是否为 ""
not empty
语法: ${empyt 属性名};属性名 就是域对象里面的key值
例子:
<body>
<%
//request.setAttribute("a",10);
User user = null;
request.setAttribute("u",user);
User user1 = new User();
request.setAttribute("u1",user1);
List list = new ArrayList();
request.setAttribute("l",list);
List list02 = null;
request.setAttribute("l2",list02);
%>
<%--a就是从域里面获得的a
${a+19}
${a>20}
--%>
<%--1.判断对象(user是)否为null--%>
${empty u} <%--true--%>
${empty u1} <%--false--%>
${not empty u}<%--false--%>
<hr/>
<%--2.判断一个集合的长度是否为0--%>
${empty l} <%--true--%>
${empty l2} <%--true--%>
</body>
5、JSTL表达式
5.1、上面是JSTL表达式
JSTL(JSP Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。这个JSTL标签库没有集成到JSP的, 要使用的话, 需要导jar包.
5.2、JSTL表达式作用
为了简化在jsp页面上操作数据; eg: 遍历数据 判断数据等
能够使用el表达式域里面的数据(先要把数据存到域对象里面)
1、导入核心jar包
jstl.jar
standard.jar
2、在JSP页面上导入核心标签库<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
if标签
语法:
<c:if test="el表达式${..}" [var="给之前的表达式的结果起个名字"] [scope="将结果保存在那个域中 默认page"]>
</c:if>
对应的例子:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用jstl表达式</title>
</head>
<body>
<%request.setAttribute("hello","world");%>
<c:if test="${hello.equals('world')}" var="flag" scope="request">
在request域对象中存入的是数据是world
</c:if>
<c:if test="${hello.equals('hello')}" var="hello" scope="request">
在request域对象中存入的数据是hello
</c:if>
<br>
${flag}
<br>
${hello}
</body>
</html>
浏览器端输出:
在request域对象中存入的是数据是world
true
false
特点
- 如果test里面的是true, if标签体里面的就会执行
- 如果test里面的是false, if标签体里面的就不会执行
- 没有else的
利用上面的例子来使用java代码来进行表示:
if(i>1){
user.setFlag = true;
}
System.out.println(user.getFlag);
choose标签
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>choose</title>
</head>
<body>
<%
request.setAttribute("a", "前端");
%>
<c:choose>
<c:when test="${a == 'java' }">
java
</c:when>
<c:when test="${a == 'Android' }">
Android
</c:when>
<c:when test="${a == 'IOS' }">
IOS
</c:when>
<c:otherwise>
其它
</c:otherwise>
</c:choose>
</body>
</html>
浏览器输出:
其他
foreach标签
foreach标签是最重要的标签,使用这种来进行遍历。
其中:
c:forEach中的varStatus属性。 指向一个字符串,该字符串引用一个对象。 map.put("vs",一个对象);
这个对象记录着当前遍历的元素的一些信息:
index:返回索引。从0开始
count:返回计数。从1开始
last:是否是最后一个元素
first:是否是第一个元素
上案例来进行演示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--只要使用了jstl标签,都必须导入这个--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>jstl的 foreach标签</title>
</head>
<body>
<%--
for(int i = 0 ; i < 10 ; i++){
}--%>
<%--如果设置了var属性,那么把遍历得到的结果,赋值给这个变量 ,然后把这个变量
存储到一个page作用域去
begin: 从什么开始
end: 到什么结束
var :遍历出来的每一次结果,都赋值给这个变量 i 还要存储这个变量到page作用域
step : 步长,每次遍历的步长。如果现在打印1, 那么下一次就打印3.
--%>
<c:forEach begin="1" end="10" var="i" step="2">
${i}<br/>
</c:forEach>
</body>
</html>
第二个案例:
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--只要使用了jstl标签,都必须导入这个--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>jstl的 foreach标签</title>
</head>
<body>
<%
List<String> list = new ArrayList();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
list.add("ee");
pageContext.setAttribute("list", list);
%>
${list[0]}<br/>
<%--
items : 遍历的集合
现在知道了,遍历的集合是list集合,但是我们想输出每一次遍历的结果,这时候,需要搭配一个属性??
--%>
<c:forEach items="${list}" var="name">
${name} <br/>
</c:forEach>
</body>
</html>
第三个案例:
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--只要使用了jstl标签,都必须导入这个--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>jstl的 foreach标签</title>
</head>
<body>
<%!
/*这段代码会放在jsp翻译的那个java文件的全局位置, 这就相当于有了内部类*/
public class User{
public String name;
public int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
%>
<%
List<User> list = new ArrayList();
list.add(new User("张三1" ,8));
list.add(new User("张三2" ,18));
list.add(new User("张三3" ,28));
list.add(new User("张三4" ,38));
pageContext.setAttribute("list", list);
%>
<c:forEach items="${list}" var="u">
${u.name} , ${u.age} <br/>
</c:forEach>
</body>
</html>
6、项目
下面介绍一下开发思想,以转账案例来进行说明:
首先介绍一下在servlet的开发流程
上面的是原生servlet的开发模式,但是这种模式存在着很大的问题。有着很大的耦合性,而且无法造成代码的复用。
所以提出来的是对应的三层架构模式
软件中分层:按照不同功能分为不同层,通常分为三层:表现层(web层),业务层,持久(数据库)层。
分层的意义:
- 解耦:降低层与层之间的耦合性。
- 可维护性:提高软件的可维护性,对现有的功能进行修改和更新时不会影响原有的功能。
- 可扩展性:提升软件的可扩展性,添加新的功能的时候不会影响到现有的功能。
- 可重用性:不同层之间进行功能调用时,相同的功能可以重复使用。
上面的几点需要好好去理解和体会
接着看一下分析图
M:model,数据层,我们可以通俗的理解为,只要是能够产生的数据和输出数据的地方,都有model的影子;
V:视图层,功能比较简单,就是用来展示数据和发送数据到servlet的,两个功能;
C:controller,控制层,主要思想:1、从request对象中获取得到数据;2、将参数进行传递,然后调用业务逻辑;3、将业务逻辑返回的值进行页面展示(本质上就是模型数据展示到前端页面上);
转账案例代码:
Connection工具类:
public class ConnectionUtil {
private static final ThreadLocal<Connection> CONNECTION_THREAD_LOCAL = new ThreadLocal<>();
/**
* 设置线程
*/
public static void setConnection() {
CONNECTION_THREAD_LOCAL.set(C3P0Util.getConn());
}
/**
* 获取得到线程对象
*
* @return
*/
public static Connection getConnection() {
Connection connection = CONNECTION_THREAD_LOCAL.get();
if (Objects.isNull(connection)){
connection = C3P0Util.getConn();
CONNECTION_THREAD_LOCAL.set(connection);
}
return connection;
}
/**
* 将线程回归到线程池中去
*/
public static void revomeConneciton() {
CONNECTION_THREAD_LOCAL.remove();
}
}
连接池工具类:
public class C3P0Util {
static ComboPooledDataSource ds;
static {
ds = new ComboPooledDataSource();
}
public static DataSource getDataSource(){
return ds;
}
//提供获取连接
public static Connection getConn(){
try {
return ds.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
return null;
}
}
//关闭释放资源
//重载!!!!!
public static void closeAll( Statement st , Connection conn){
closeAll(null , st ,conn);
}
//真正这个st和 conn 是
public static void closeAll(ResultSet rs , Statement st , Connection conn){
try {
if(rs!=null)
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(st!=null)
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(conn !=null)
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
serlvet层
@WebServlet(name = "UserServlet", value = "/UserServlet")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//1.获得请求参数(付款人 pay,收款人 payee,金额)
String fukuan = request.getParameter("from");
String shoukuan = request.getParameter("to");
double money = Double.parseDouble(request.getParameter("money"));
UserService userService = new UserService();
//2.处理业务(判断付款人是否存在,收款人是否存在,判断金额是否有问题,判断钱是否够,进行转账(使用DBUtils操作数据库))
boolean flag = userService.transfer(fukuan,shoukuan,money);
//3.判断是否转账成功,响应
if (flag){
response.getWriter().print("转成成功");
}else{
response.getWriter().print("转成失败");
}
} catch (Exception e) {
e.printStackTrace();
response.getWriter().print("转成失败");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
service层
public class UserService {
public boolean transfer(String fukuan, String shoukuan, double money) throws Exception {
Connection connection = null;
try {
connection = ConnectionUtil.getConnection();
connection.setAutoCommit(false);
UserDao userDao = new UserDao();
boolean flag = userDao.transfer(fukuan,shoukuan,money);
connection.commit();
return flag;
} catch (SQLException throwables) {
try {
connection.rollback();
} catch (SQLException e) {
throw new Exception("转账失败");
}
}
return false;
}
}
dao层
public class UserDao {
/**
* 转账案例
* @param fukuan
* @param shoukuan
* @param money
* @return
* @throws SQLException
*/
public boolean transfer(String fukuan, String shoukuan, double money) throws SQLException {
QueryRunner queryRunner = new QueryRunner();
Connection connection = ConnectionUtil.getConnection();
String sql01 = "UPDATE account SET money = money-? WHERE name = ?";
int rows01 = queryRunner.update(connection,sql01, money, fukuan);
int i = 1/0;
String sql02 = "UPDATE account SET money = money+? WHERE name = ?";
int rows02 = queryRunner.update(connection,sql02,money,shoukuan);
ConnectionUtil.revomeConneciton();
if (rows01>0&&rows02>0){
return true;
}
return false;
}
}
不过我们也很容易看到这里的特点:有以下几个问题
1、繁琐。写代码起来,需要考虑到很多问题;
2、我们为了保证数据库中事务的完整性,我们需要拿到相同的连接来进行传递,需要关闭自动提交,在程序正确执行之后提交事务;在程序执行失败之后,需要将事务进行回滚,保证数据的完整性。在后期,我们要对这里的操作来进行改进。
正确的操作应该是我们只需要来关注我们的逻辑操作,类似这种事务的操作(小细节)不需要写大量的代码来进行实现。
3、SQL语句,这样子来写就会存在着硬编码问题,而且还不是特别通用,如果后期需要添加的话,还需要修改代码,这种方式比较麻烦
6.1、自己的一点想法
但是上面的原生方式开发我觉得有一个优点,就是没有大量的封装,性能上更快;运用这种方式来编写的代码会更具有效率,但同时在开发中,我们也需要考虑更多的问题以及自己来对问题来进行解决;
可能我更喜欢这种以原生代码的方式来运行代码,很多东西都是自己来做。但是我觉得更多的应该是让自己的代码变得通用
但是更多的是先写简单的代码,然后看更多的源码设计,理解别人为什么要这么设计,学习别人的设计思想,然后学以致用,运用到自己的代码开发中;