jsp开发模型
Sun(Oracle)为了指导开发,提出了2种开发模型
jspModel1
Jsp页面与JavaBeans共同协作完成任务
Model 1模式的实现比较简单,适用于快速开发小规模项目。但从工程化的角度看,它的局限性非常明显:JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。
早期有大量ASP和JSP技术开发出来的Web应用,这些Web应用都采用了Model 1架构。
输入页面login1.jsp
<form action="login_do.jsp" method="post">
<input name="username" value="<%=request.getParameter("username")!=null?request.getParameter("username"):""%>"/>
<input type="submit" value="登录系统"/>
</form>
接收数据的页面login_do.jsp,其中负责接收数据并进行数据校验,然后调用javaBean完成业务逻辑处理,最后根据处理结果跳转对应的页面
<%@ page import="com.yan.dao.IUserDao" %>
<%@ page import="com.yan.util.DaoFactory" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="user" class="com.yan.entity.UserBean">
<jsp:setProperty name="user" property="*"/>
</jsp:useBean>
<%!
private IUserDao userDao= DaoFactory.getUserDao();
%>
<%
boolean bb=userDao.login(user);
System.out.println(user.getUsername());
if(bb){
session.setAttribute("user",user);
response.sendRedirect("login_succ.jsp");
}else{
request.setAttribute("msg","登录失败!请重新登录");
request.getRequestDispatcher("login1.jsp").forward(request,response);
}
%>
javaBean负责处理实际的业务逻辑,采用的是DAO模式:1个接口,若干实现,1个值bean,1个工厂
public class UserDaoImpl implements IUserDao{
@Override
public boolean login(UserBean user) throws Exception {
return true;
}
}
最后再定义对应的显示页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
欢迎您,
<%
Object obj=session.getAttribute("user");
if(obj!=null && obj instanceof UserBean){
UserBean ub=(UserBean)obj;
out.println(ub.getUsername());
}
%>
</body>
</html>
jspModel2
Jsp Model2中使用了三种技术JSP、Servlet和JavaBeans
- Jsp负责生成动态网页,只用显示业务数据和收集客户动作
- Servlet负责流程控制,用来处理各种请求的分派
- JavaBeans负责业务逻辑和业务数据,对数据库的操作
Jsp Model2优点
消除了Jsp Model1的缺点:
- 该模式适合多人合作开发大中型的Web项目
- 各司其职,互不干涉
- 有利于开发中的分工
- 有利于组件的重用
Jsp Model2缺点
Web项目的开发难度加大,同时对开发人员的技术要求也提高了
各个部分的开发难度降低,总体难度加大
lombok
Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现 Lombok,开发人员可以节省构建诸如 hashCode() 和 equals() 这样的方法以及以往用来分类各种 accessor 和 mutator 的大量时间。
依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
开发工具中需要安装插件
java -jar lombok.jar
定义POJO
@Data
public class CatalogBean implements Serializable {
private Long id;
private String title;
}
在编译时会自动添加所有属性的get/set方法,以及构造器和hashcode/equals方法
@ToString:作用于类,覆盖默认的toString()方法,可以通过of属性限定显示某些字段,通过exclude属性排除某些字段。
@Getter/@Setter: 作用类上,生成所有成员变量的getter/setter方法;作用于成员变量上,生成该成员变量的getter/setter方法。可以设定访问权限及是否懒加载等。
@EqualsAndHashCode:作用于类,覆盖默认的equals和hashCode
@NonNull:主要作用于成员变量和参数中,标识不能为空,否则抛出空指针异常。
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor:作用于类上,用于生成构造函数。有staticName、access等属性。
@NoArgsConstructor:生成无参构造器;
@RequiredArgsConstructor:生成包含final和@NonNull注解的成员变量的构造器;
@AllArgsConstructor:生成全参构造器
@Data:作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
@Builder:作用于类上,将类转变为建造者模式
@Log:作用于类上,生成日志变量。针对不同的日志实现产品,有不同的注解:
@Synchronized:作用于方法级别,可以替换synchronize关键字或lock锁
@SneakyThrows:可以对受检异常进行捕捉并抛出
@Cleanup:自动关闭资源,针对实现了java.io.Closeable接口的对象有效
#页面种的EL
配置了上下文参数
<context-param>
<param-name>project</param-name>
<param-value>闫氏书店</param-value>
</context-param>
页面显示
<title><%=application.getInitParameter("project")!=null?application.getInitParameter("project"):""%> - 欢迎页</title>
如何避免jsp页面中读取4大范围中数据的麻烦
- 传递数据使用的4大范围
- page
- request
- session
- application
jsp提供了EL表达式语言解决
表达式语言
JSTL定制标记支持另一种用于指定动态属性值的机制。可以用简化的表达式语言EL而不使用完整的 JSP 表达式来指定 JSTL 操作的属性值
EL提供了一些标识符、存取器和运算符,用来检索和操作驻留在 JSP 容器中的数据
- EL擅长寻找对象及其特性,然后对它们执行简单操作;它不是编程语言,甚至不是脚本编制语言
- EL与JSTL标记一起使用时,它就能使用简单而又方便的符号来表示复杂的行为
- EL表达式的格式是这样的:用美元符号$定界,内容包括在花括号{ }
- 不允许在EL表达式中直接调用方法,例如${abc.trim()}
JSP2开始将Expression Language整合进JSP标准规格
- EL并非全新的语言,最早出现于JSTL 1.0当中,被用来简化数据存取的相关操作
- 由于EL已是JSP的标准,因此用户可以选择直接在JSP网页当中使用EL替代Java进行数据的存取操作
例如:
<title>${initParam.project} - 欢迎页</title>
EL脚本语言的配置
对于一个单个JSP页面,可以使用定义page指令来设置jsp页面是否支持EL
默认是支持EL,如果要页面不支持EL,设置为isELIgnored=true;
<%@ page isELIgnored="true|false"%>
###运算符
运算符 | 说 明 |
---|---|
. | 存取bean property 或是map entry |
[] | 存取 array or List 元素 |
() | 改变运算顺序 |
? : | 条件式三元运算 condition ? ifTrue : ifFalse |
+ - * /或div %或mod | 加、减、乘、除、模数学运算 |
无论action elements 或是隐含对象的数据内容,均是一种集合collection对象,EL可以通过点运算符.或是方括号[]对其作存取
${ param.yearValue}
${ param["yearValue"] }
<h1><jsp:useBean id="now" class="java.util.Date" scope="session"/>
<%
request.setAttribute("now",new Random());
%>
${now} 自动从小到大在4大范围中查找key=now的对象,类似于pageContext.findAttribute("now")。如果找不到返回为"",不是null
样例2:可以通过.或者[]两种不同方式访问对象的属性,如果查找不到对象,不会出现空指针异常,反而有默认值
<jsp:useBean id="now" class="java.util.Date" scope="session"/>
${now.year+1900}--${now['month']+1} 形式上看似乎是直接访问属性,但是访问属性实际上是调用对应的getXXX方法
${now2.year+1900}--${now2['month']+1}
运算符 | 说明 |
---|---|
==或eq !=或ne | 对等运算与不相等运算 |
< 或lt > 或gt |
小于比较运算与大于比较运算 |
<= 或le >= 或ge |
小于或等于比较运算与大于或等于比较运算 |
&& 或and || 或or ! 或not |
逻辑AND运算、逻辑OR运算、逻辑非运算 |
empty | 判空运算 |
<%
request.setAttribute("now3","");
%>
<%
//非空字符串判断
out.println(pageContext.findAttribute("now3")!=null && pageContext.findAttribute("now3").toString().trim().length()>0);
%>
${empty now3}-- ${not empty now3} empty针对一般对象判断null,如果是集合判断null或者空集合,针对字符串判断null或者空串,注意判空串时不会自动调用trim()方法
11个内建对象
内建对象 | 说明 |
---|---|
pageContext | 取得网页运行环境的相关信息 |
pageScope | 取得page范围内特定属性的属性值 |
requestScope | 取得request范围内特定属性的属性值 |
sessionScope | 取得session范围内特定属性的属性值 |
applicationScope | 取得application范围内特定属性的属性值 |
param | 取得request对象的单一参数值 |
paramValues | 取得request对象的参数值 |
header | 取得request对象单一标头值 |
headerValues | 取得request对象标头值 |
cookie | 取得request对象的cookie |
initParam | 取得网页运行环境的初始参数值 |
- 4大范围xxxScope,例如pageScope、requestScope、sessionScope和applicationScope,用于操作其中的attribute数据
- 请求参数 param和paramValues
- 请求头参数 header和headerValues
- 特殊的参数 cookie initParam pageContext
EL对象与request对象存取
EL对象 | Request对象存取 |
---|---|
param | ServletRequest.getParameter(String name) |
paramValues | ServletRequest.getParameterValues(String name) |
header | HttpServletRequest.getHeader(String name) |
headerValues | HttpervletRequest.getHeaders(String) |
cookie | HttpServletRequest.getCookies() |
<%=request.getParameter("name")%> -- ${param.name}<br/>
<%=request.getParameterValues("hobby")%> -- ${paramValues.hobby}<br/>
<%
Cookie[] cks=request.getCookies();
for(Cookie ck:cks){
out.println(ck.getName()+":::"+ck.getValue()+":::"+ck.getDomain()+":::"+ck.getMaxAge());
}
%> -- ${cookie.JSESSIONID.value}
范围变量
EL中4个与范围有关的隐含对象,pageScope、requestScope、sessionScope和applicationScope,可直接用来存取属于特定范围内的变量值,它们与JSP内建所的隐含对象基本上是相同的
- pageScope对应pageContext、 requestScope对应request、sessionScope对应session、applicationScope对应application
- 在JSP网页当中取得特定范围变量属性,必须引用getAttribute(),并且指定所要取得的变量名称
application.getAttribute("cname")
- 通过EL的存取方式
${applicationScope.cname}
param & paramValues
EL对象param与paramValues被设计用来提供使用request之外的一个选择
EL | request |
---|---|
${param.paraName} |
request.getParameter(paraName) |
${paramValues.name} |
request.getParameterValues(name) |
param内容包含当前网页所有的request参数,这段程序代码取得其中名称为yearValue的参数值${param.yearValue}
针对取得的参数内容,进一步对其作运算${param.yearValue+100}
param与paramValues最大的好处便是简化了request参数数据的存取
cookie
提供直接读取cookie所需的语法${cookie.cname.value}
如果想要了解此cookie的识别名称,省略value即可${cookie.cname}
initParam
网站一开始启动的时候,通常需要设定某些与网站有关的参数 ,这些参数在网站根目录底下WEB-INF数据夹的web.xml文件里面作设定
<web-app>
<context-param>
<param-name>admin</param-name>
<param-value>tea</param-value>
</context-param>
</web-app>
引用initParam读取系统参数非常的容易,指定所要取得的参数名称即可。${initParam.admin}
小结
EL表达式语言Expression Language是JSTL的两个组成部分之一
- JSP 标准标签库专家组和 JSP 2.0 专家组共同开发了 JSP EL
- JSP 表达式语言用于访问存储于JavaBean中的数据
- JSP 表达式语言可以用于任何静态文本和标准标签或自定义标签
开发书店
欢迎首页
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<title>${initParam.project} - 欢迎页</title>
</head>
<body>
<jsp:forward page="books.do"/>
</body>
</html>
web.xml