文章目录
- 一 JSP
- 1.1 jsp介绍
- 1.2 jsp相关概念
- 1.3 jsp脚本
- 1.3.1 普通脚本
- 1.3.2 声明脚本
- 1.3.3 输出脚本
- 1.4 jsp注释
- 1.5 jsp指令
- 1.5.1 include指令(了解)
- 1.5.2 page指令
- 1.5.3 taglib指令
- 1.6 jsp内置对象
- 1.7 jsp中四大域对象
- 1.7.1 pageContext域对象
- 二 el表达式
- 2.1 el表达式介绍
- 2.2 el获取域数据基本使用
- 2.3 el获取复杂域数据
- 2.4 el表达式执行运算
- 2.5 el表达式中web对象
- 三 jstl标签库
- 3.1 介绍
- 3.1.1 环境准备
- 3.2 jstl核心标签
- 3.2.1 set标签
- 3.2.2 remove标签
- 3.2.3 catch标签
- 3.2.4 if标签
- 3.2.5 forEach标签
- 3.2.6 forToken标签
- 3.2.7 choose标签
- 3.2.8 ul标签
- 3.3 jstl综合案例——显示商品信息
- 3.3.1 准备工作
- 3.3.2 功能完成
- 四 jsp模式
- 4.1 model1模式
- 4.2 model2模式
- 五 BeanUtils框架
- 5.1 开发步骤
- 5.2 自定义BeanUtils框架
- 六 mvc设计模式
一 JSP
1.1 jsp介绍
为什么要引入jsp?
html文件无法获取java程序中的数据,同时,如果使用Servlet来显示java数据又显得不太合理!
综上,需要一门技术,既可以显示页面,同时也可以获取java程序中的数据
什么是jsp
jsp:java server page
简单理解为,它就是一个可以获取java数据的html文件。
1.2 jsp相关概念
jsp为什么是一个Servlet
jsp文件会转义成对应的java文件
比如:demo01.jsp转义成demo01_jsp.java,类demo01_jsp会继承于HttpJspPage,HttpJspPage又是Servlet子类,demo01.jsp就是Servlet
jsp的执行流程
浏览器发起请求demo01.jsp
demo01.jsp就会转义生成对应demo01_jsp.java
在demo01_jsp类中,通过JspWriter类将demo01.jsp中的html标签作为响应正文响应给浏览器进行渲染显示!
1.3 jsp脚本
作用
可以在页面上写java代码
分类
声明脚本:<%! java代码 %> 在jsp对应java类中,生成一个成员变量
片段脚本:<% java代码 %> 在jsp对应的java类的_jspService方法中,生成一个局部变量
输出脚本::<%= 变量值 %> 向浏览器输出内容,相当于response.getWriter().write()
1.3.1 普通脚本
<% java代码%>
Hello World!<br/>
<%
//jsp使用小脚本嵌入代码
out.println("hi");
System.out.println("hello");
%>
- 普通脚本可以使用所有java语法,除了定义函数
- 脚步与脚本之间不可嵌套,脚步与html标签不可嵌套
1.3.2 声明脚本
<%! 定义变量、函数%>
<%! int i=0;%>
<%! int a,b,c;%>
<%! Object object = new Object();%>
<%!
//定义方法
public void m1(){
System.out.println("你好");
}
%>
- 声明脚本声明的变量是全局变量
- 声明脚本的内容必须在偶同脚本中调用
- 如果声明脚本中的函数具有返回值,可以使用输出脚本调用<%= %>
1.3.3 输出脚本
<%= java表达式%>
<p>
今天的日期是:<%=new java.util.Date()%>
</p>
输出脚本可以输出带有返回值的函数
输出脚本没有“;”
1.4 jsp注释
jsp文件中,既可以有html代码,也可以有java代码
这就意味着,jsp文件中,既可以使用html注释,也可以使用java注释,同时还可以使用jsp注释
html注释 <!-- -->
用来注释html代码
会将注释内容生成到jsp对应的java文件中
通过浏览器查看源代码可以看见
java注释 //
用来注释java代码
会将注释内容生成到jsp对应的java文件中
jsp注释 <%-- --%>
用来注释html代码
不会讲注释内容生成到jsp对应的java文件中
注释内容不会发送至浏览器甚至不会被编译
<p>
今天的日期是:<%=new java.util.Date()%>
</p>
<%--jsp注释在网页中不会被显示--%>
<!--html注释在网页中会显示-->
1.5 jsp指令
用于指示jsp执行某些操作 、用于指示jsp表现特定行为或效果
<%@ 指令名称 属性名1="属性值1" 属性名2="属性值2" %>
1.5.1 include指令(了解)
用于将外部引入到jsp文件中
<%@ include file="top.jsp"%>
1.5.2 page指令
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" errorPage="error.jsp" %>
<%@ page isErrorPage="true" %>
contentType="text/html;charset=UTF-8"
告诉浏览器应该以utf-8解码响应正文,告诉服务器应该以utf-8对响应正文进行编码
language="java"
设置jsp页面能够使用的语言,不动!
import="java.util.List"
在当前jsp页面中导入List类
isELIgnored="false"
当前jsp页面不要忽略el表达式,默认就是不忽略
errorPage="error.jsp"
当前jsp页面发生异常,所要跳转到页面
isErrorPage="true"
标记当前jsp页面是否是一个错误页面,如果为true那么就可以使用jsp内置对象exception,否则不能使用
1.5.3 taglib指令
在当前jsp页面中导入jstl标签库
<%@taglib prefix="前缀" uri="路径" %>
- 导入jstl标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
1.6 jsp内置对象
可以在jsp页面上直接使用的对象
内置对象名 | 描述 |
page | 当前页面对象 java.lang.Object |
pageContext | 当前页面上下文对 javax.servlet.jsp.PageContext |
request | 请求对象 javax.servlet.http.HttpServletRequest |
response | 响应对象 javax.servlet.http.HttpServletResponse |
session | 会话对象 javax.servlet.http.HttpSession |
config | ServletConfig对象 javax.servlet.ServletConfig |
exception | 异常对象 java.lang.Throwable |
application | ServletContext对象 javax.servlet.ServletContext |
out | JspWriter对象 javax.servlet.jsp.JspWriter |
在jsp对应的java文件中,已经提前声明好了这些内置对象,所以可以直接使用
- request、response、session
<%
// String username = request.getParameter("username");
// System.out.println(username);
// response.getWriter().write(username);
// session.setAttribute("msg","hello jsp");
application.setAttribute("msg","hello jsp jsp");
%>
<%
// String msg = (String) session.getAttribute("msg");
// System.out.println(msg);
String msg = (String) application.getAttribute("msg");
System.out.println(msg);
%>
<%
out.write("i am very happy");
%>
1.7 jsp中四大域对象
域对象:就是可以用来存储数据对象
jsp域对象
request 代表整个请求链
session 整个会话
application 整个web应用
pageContext 代表page域,但是jsp中page它的类型是Object,所以操作page域我们使用的是
pageContext对象,page域就是指当前页面范围
1.7.1 pageContext域对象
作用
获取其他的内置对象
操作域
操作page域
操作request、session、application
- 获取其他的内置对象
- 没有获取out内置对象
<%
pageContext.getPage();//获取内置对象page
pageContext.getRequest();//获取内置对象request
pageContext.getResponse();//获取内置对象response
pageContext.getSession();//获取内置对象session
pageContext.getServletContext();//获取application
pageContext.getServletConfig();//config
pageContext.getException();//exception
%>
- 操作page域
- 作用范围只在当前页面
<%
//往pageContext域中存储了一个msg变量
pageContext.setAttribute("msg" ,"hello page msg");
%>
<%
//往pageContext域中存储了一个msg变量
Object msg = pageContext.getAttribute("msg");
System.out.println(msg);
%>
- 操作其他域
- request域
<%
//定义变量的意义! 提高复用性! 提高可维护性!
//String name : 参数名称
//Object value : 参数值
//int scope : 操作的域
pageContext.setAttribute("msg1","hello page1",PageContext.REQUEST_SCOPE);
//请求转发
request.getRequestDispatcher("/demo06.jsp").forward(request,response);
%>
<%
//变量msg1定义到_jspService方法中
Object msg1 = request.getAttribute("msg1");
System.out.println("msg1 : "+msg1);
Object msg11 = pageContext.getAttribute("msg1", PageContext.REQUEST_SCOPE);
System.out.println(msg11);
%>
- session域
<%
pageContext.setAttribute("msg2","hello page2",PageContext.SESSION_SCOPE);
%>
- application域
<%
pageContext.setAttribute("msg3","hello page3",PageContext.APPLICATION_SCOPE);
%>
二 el表达式
2.1 el表达式介绍
el(expression language),是由jsp内置提供
el表达式用来替换jsp脚本
作用
向页面输出数据
获取web对象
格式
${表达式}
如果page指令中isELIgnored=“true”,jsp页面就不会解析执行el表达式,会原样显示
2.2 el获取域数据基本使用
- 获取page域数据
<%
pageContext.setAttribute("msg1","hello page1");
%>
${pageScope.msg1}
- 获取request域数据
<%
request.setAttribute("msg1","hello page1");
%>
${requestScope.msg1}
- 获取session域数据
<%
session.setAttribute("msg1","hello page1");
%>
${sessionScope.msg1}
- 获取application域数据
<%
application.setAttribute("msg1","hello page1");
%>
${applicationScope.msg1}
2.3 el获取复杂域数据
- 获取数组
<%
//数组静态初始化
String[] msgs = {"tom","steve","barry"};
pageContext.setAttribute("msgs",msgs);
%>
<%--jsp输出脚本--%>
<%=
((String[])pageContext.getAttribute("msgs"))[0]
%>
${msgs[1]}
- 获取List集合
<%
List<String> msgs1 = new ArrayList<>();
msgs1.add("kate");
msgs1.add("jay");
request.setAttribute("msgs1",msgs1);
%>
<%=
((List<String>)request.getAttribute("msgs1")).get(0)
%>
${msgs1[1]}
- 获取map集合
<%
HashMap<String,Object> map = new HashMap<>();
map.put("username","jerry");
map.put("age",16);
session.setAttribute("map",map);
%>
<%=
((HashMap<String,Object>)session.getAttribute("map")).get("username")
%>
${map.age}
- 获取java对象
<%
User user = new User();
user.setId(1);
user.setUsername("alex");
user.setPassword("123456");
application.setAttribute("user",user);
%>
<%=
((User)application.getAttribute("user")).getUsername()
%>
${user.password}
2.4 el表达式执行运算
- 算术运算
+
-
*
/:div
%:mod
- 关系运算
> : gt
>= : ge
< : lt
<= : le
== : eq
!= : ne
- 逻辑运算
&& : and
|| : or
! : not
- 三元运算
${num1 gt num2 ? "num1大于num2" : "num1不大于num2"}
2.5 el表达式中web对象
- 11个web对象
el表达式 | 说明 |
pageScope (常用) | 是page域对象,获取pageContext域属性 |
requestScope (常用) | 获取request域属性 |
sessionScope (常用) | 获取session域属性 |
applicationScope (常用) | 获取application域属性 |
param | 对应参数,它是一个Map,其中key是参数,value是参数值,适用于单值的参数 相当于request.getParameter() |
paramValues | 对应参数,她是一个Map,其中key是参数,value是多个参数值,适用于多值的参数 相当于request.getParameterValues() |
header | 对应请求头,它是一个Map,其中key表示头名称,value是单个头值,适用于单值的请求头 获取单个请求头值 |
headerValues | 对应请求头,它是一个Map,其中key表示头名称,value是多个头值,适用于多值的请求头 获取一组请求头的值 |
initParam | 获取初始化参数,获取web.xml中内的参数 |
cookie (常用) | 用于获取cookie Map<String,Cookie>,其中key是cookie的name,value是cookie对象 |
pageContext (常用) | 相当于pageContext对象,获取jsp九大内置对象 |
应用场景:获取当前项目路径
${pageContext.request.contextPath}
三 jstl标签库
3.1 介绍
jstl (java standard tag libarary),jsp标签库,它是apache对el表达式的扩展
和el表达式结合使用,可以让功能更加强
3.1.1 环境准备
- 导入jar包
- 在jsp页面导入jstl标签库
- 使用taglib指令
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3.2 jstl核心标签
3.2.1 set标签
向域对象(page域、request域、session域、application域)中存储数据
var:参数名称
scope:域
value:参数值
<c:set var="msg" scope="request" value="hello jstl"></c:set>
${msg}
3.2.2 remove标签
移除域对象中的数据
var:参数名称
scope:域
<c:remove var="msg" scope="request"></c:remove>
${msg}<br>
3.2.3 catch标签
捕获jsp页面的异常,相当于try…catch
var:声明异常对象名称,比如:var="e" ,变量e就可以接收异常对象
<c:catch var="e">
<%
int num = 1 / 0;
%>
</c:catch>
${e}<br>
3.2.4 if标签
条件判断
test :编写条件
<c:set var="num" value="2" scope="request"></c:set>
<c:if test="${num == 1}">
num 等于 1
</c:if>
<c:if test="${num != 1}">
num 不等于 1
</c:if>
3.2.5 forEach标签
遍历集合或数组
begin:开始
end:结束
step:步数
var:元素名称
items:集合/数组
varStatus:元素状态对象
first:是否是第一个元素
last:是否是最后一个元素
current:当前元素
index“:当前脚标
<!-- 基本使用 -->
<c:forEach begin="1" end="10" step="3" var="num">
${num}
</c:forEach>
<%
List<String> strs = new ArrayList<>();
strs.add("aaa");
strs.add("bbb");
strs.add("ccc");
request.setAttribute("strs",strs);
%>
<!-- 相当于普通for循环 -->
<c:forEach begin="0" end="${strs.size() - 1}" step="1" var="i">
${strs[i]}
</c:forEach>
<!-- 相当于增强for循环 -->
<c:forEach var="str" items="${strs}" varStatus="status">
${str}<br>
${status.current} -- ${status.index} -- ${status.first} -- ${status.last}<br>
</c:forEach>
3.2.6 forToken标签
分割字符串
items:要分割的字符串
delims:分割的规则
var:分割产生的元素
<%
String msg1 = "aaa--bbb--ccc";
request.setAttribute("msg1",msg1);
%>
<c:forTokens items="${msg1}" delims="--" var="sonMsg">
${sonMsg}
</c:forTokens>
3.2.7 choose标签
<c:choose>标签与switch语句功能一样,用于在众多选项中做出选择
<c:choose>
<c:when test="条件1">结果1</c:when>
<c:when test="条件2">结果2</c:when>
<c:when test="条件3">结果3</c:when>
<c:otherwise>结果4</c:otherwise>
</c:choose>
3.2.8 ul标签
<c:ul>标签将URL格式化为一个字符串,然后存储在变量中
自动重写URL,var属性用于存储格式化后的URL
<c:ul value='${pageContext.request.contextPath}/xxxController' var="myurl"/>
3.3 jstl综合案例——显示商品信息
3.3.1 准备工作
- 导入jar包
- ProductDao
public class ProductDaoImpl implements ProductDao {
@Override
public List<Product> selectProductList() throws Exception {
return new QueryRunner(JDBCUtils.getDataSource())
.query("select * from tb_product",
new BeanListHandler<Product>(Product.class));
}
}
- ProductServlet
@WebServlet(name = "ProductServlet" ,urlPatterns = "/selectProductList")
public class ProductServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ProductDao productDao = new ProductDaoImpl();
try {
List<Product> productList = productDao.selectProductList();
System.out.println(productList);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3.3.2 功能完成
- productList.jsp
<table border="1px" cellspacing="0px" cellpadding="10px" width="500px" height="200px">
<tr>
<td>ID</td>
<td>名称</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
</tr>
<%--循环之前,总价为0--%>
<c:set var="total" value="0" scope="page"></c:set>
<c:forEach items="${productList}" var="product">
<%--forEach标签,循环一次就是一个小计!--%>
<tr>
<td>${product.id}</td>
<td>${product.name}</td>
<td>${product.price}</td>
<td>${product.count}</td>
<td>${product.price * product.count}</td>
</tr>
<c:set var="total" value="${total + product.price * product.count}" scope="page"></c:set>
</c:forEach>
<%--循环之后,计算出总价--%>
<tr>
<td colspan="5" align="right">
总价:${total}元
</td>
</tr>
</table>
四 jsp模式
分类
model1模式 jsp+javaBean
model2模式 jsp+javaBean+Servlet
4.1 model1模式
jsp
处理请求
业务处理
操作数据库
显示数据
javaBean
封装数据
优点:开发简单
缺点:维护难,代码几乎都在jsp中
<%@ page import="org.apache.commons.dbutils.QueryRunner" %>
<%@ page import="util.JDBCUtils" %>
<%@ page import="org.apache.commons.dbutils.handlers.BeanListHandler" %>
<%@ page import="bean.Product" %>
<%@ page import="java.util.List" %>
<%@ page import="java.security.interfaces.RSAKey" %><%--
Created by IntelliJ IDEA.
User: EVA_01
Date: 2020/4/28 0028
Time: 15:13
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>jsp的model1模式</title>
</head>
<body>
<%
//请求处理
//业务处理
//操作数据库
List<Product> productList = new QueryRunner(JDBCUtils.getDataSource())
.query("select * from tb_product", new BeanListHandler<Product>(Product.class));
System.out.println(productList);
pageContext.setAttribute("productList",productList);
// request.getRequestDispatcher("/productList1.jsp").forward(request, response);
%>
<table border="1px" cellspacing="0px" cellpadding="10px" width="500px" height="200px">
<tr>
<td>ID</td>
<td>名称</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
</tr>
<%--循环之前,总价为0--%>
<c:set var="total" value="0" scope="page"></c:set>
<c:forEach items="${productList}" var="product">
<%--forEach标签,循环一次就是一个小计!--%>
<tr>
<td>${product.id}</td>
<td>${product.name}</td>
<td>${product.price}</td>
<td>${product.count}</td>
<td>${product.price * product.count}</td>
</tr>
<c:set var="total" value="${total + product.price * product.count}" scope="page"></c:set>
</c:forEach>
<%--循环之后,计算出总价--%>
<tr>
<td colspan="5" align="right">
总价:${total}元
</td>
</tr>
</table>
</body>
</html>
4.2 model2模式
servlet
处理请求
业务处理
操作数据库
jsp
显示数据
javaBean
封装数据
优缺点
维护方便,开发人员各司其职,有利于我们进行分工操作
比较适合开发一些比较复杂项目,因为它的很多组件可以重用。
开发难度增大,对开发人员要求比较高
五 BeanUtils框架
可以将请求参数封装到java对象中
5.1 开发步骤
- 导包
Map<String, String[]> map = request.getParameterMap();
User user = new User();
System.out.println(user);
try {
BeanUtils.populate(user,map);
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
}
页面上的name属性值要和java对象中的属性名一致
5.2 自定义BeanUtils框架
- MyBeanUtils
public class MyBeanUtils {
/**
* 将map集合中的请求参数值封装到对象t中
* @param t
* @param map : 键:参数名称;值:一组参数值。
* @param <T>
*/
public static<T> void populate(T t , Map<String,? extends Object> map ){
Class<?> clazz = t.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
System.out.println(methodName);
//获取对应的set方法
try {
Class<?> type = field.getType();
Method method = clazz.getMethod(methodName, type);
if (null != method) {
//第二个参数:请求参数的值
//id、username、password、age
Object object = map.get(fieldName);
if (null != object) {
String[] strs = (String[]) object;
if (type.getName().equals("java.lang.Integer")) {
method.invoke(t,Integer.parseInt(strs[0]));
} else {
method.invoke(t,strs[0]);
}
}
}
} catch (Exception e) {
// e.printStackTrace();
throw new MyNoSuchMethodException("field " + fieldName + " there is no setter method!!!");
}
}
}
}
- MyNoSuchMethodException
public class MyNoSuchMethodException extends RuntimeException{
public MyNoSuchMethodException() {
}
public MyNoSuchMethodException(String message) {
super(message);
}
public MyNoSuchMethodException(String message, Throwable cause) {
super(message, cause);
}
public MyNoSuchMethodException(Throwable cause) {
super(cause);
}
public MyNoSuchMethodException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
六 mvc设计模式
它是一种软件设计典范,用一种业务逻辑,数据,界面分离的方式来组织代码,将业务逻辑聚集 到一个部件中,方便程序的重复使用,提高我们的开发效率
jsp的model2模式是mvc设计模式的一种
- 业务分工
m: model 数据封装
v: view 显示页面,即视图层 数据的显示 jsp
c: controller 控制层,用于业务处理,而业务处理包含:处理请求、业务逻辑、操作数据库
存在的弊端
c中的代码太多,职责不单一!需要使用到三层结构
- 三层结构
web层:处理请求
service层:业务逻辑,业务层
dao层:操作数据库,持久层