JSP的EL简化,MVC分层,各模块的功能和关系

JSP

Javaweb — emmm……不知道是多少天了:happy:;快四个月了


JSP的EL表达式


昨天已经分享了关于JSP的基本内容,JSP技术的意义就是一个工具帮助普通的Servlet类实现嵌入HTML代码,自动完成了out.write的功能,HTML代码书写在执行标记之外;所有的执行标记是一个整体,JSP的作用就是通过共享域将Servlet传递过来的域属性中取出变量,然后输出到响应体,一般不处理业务功能;但是普通的JSP开发需要取出对象并使用<%= %>输出变量; EL表达式就直接一步代替了上面的三步,直接输出

EL简化

EL的普通写法是${requestScope.域属性名.对象的属性};简化EL可以将前面的对象域别名省略,直接使用

${域属性名.对象的属性}

命令的作用 : EL表达式允许省略作用域对象的别名

工作原理 :在EL表达式的简化版中没有制定作用域对象,所以执行的时候采用猜测算法 ----- 在多线程中也是,多线程的 三大特性 — 原子性atomic,可见性 , 有序性;

服务器会先到pageContext当前页作用域中查找是否有这个数据,如果存在就会读取输出;没有则会进入request请求作用域中寻找,如果还是没有找到就会到session作用域中寻找,如果仍然没有找到就到application中寻找;如果仍然没有定位成功,就会返回null;

所以就是 pageContext 》 request 》 session 》 application 【所以这样搜索就会降低程序的执行速度】

并且前面的数据会对后面的数据进行覆盖,所以会发生定位错误

EL简化表达式的应用

EL的是进行的按照顺序进行检索,会浪费时间,并且会发生错误,那么EL简化的意义是什么?

可以从执行的顺序就可以看出,EL简化最有利的就是pageContext;所以EL的简化目的就是为了方便简化输出pageContext的对象,pageContext中的共享数据是JSTL自动放入的

EL表达式简化版总之就是慎用

EL表达式 — 支持运算

在JSP文件中有的时候需要读取共享域数据之后要运算之后才会输出,这里的EL表达式是支持直接进行运算的

比如要对共享域中的数据key1和key2进行求和操作,不需要单独取出运算,可以直接使用EL表达式运算

${key1 + key2}

支持的运算:

  1. 数学运算 : + - * /
  2. 关系运算: > < >= <= & gt; & lt 使用关系运算的时候使用三目运算符来输出
  3. 逻辑运算 && ||
${age >= 19?"欢迎光临":"谢绝入内"}

这样就可以实现输出,一定要配合三目使用

JSP中不会做复杂的运算,负责的运算一般Servlet中进行

EL表达的内置对象 【很少使用,不会直接发个jsp】

${param.请求参数名}

命令的作用: 通过请求对象读取当前的请求包中的请求参数内容,并将请求体中的参数内容写道响应体

所以这就要求一定要用请求转发的方式或者重定向中路径加上?来携带数据

//这个代码代替的是
发送了请求 : Http://localhost:8080/myWeb/index.jsp?user=cfeng&pwd=123

<%
	String user = request.getParameter("user");
	String user = request.getParameter("pwd");
%>
	用户姓名<%= user%>
	用户密码<%= pwd%>



-------------------使用内置对象-----------------------------
${param.user}<br/>
${param.pwd}

那么这是读取单一的值的请求,对于多个值的比如checkbox也有专门的内置对象paramValues

${paramValues.数据名[下标]}

作用 : 如果浏览器发送的请求参数是一个请求参数关联多个值,此时可以通过paramValues读取请求参数下制定位置的值,并写入到响应体中【还是一次只能输出一个】

代替的命令

发送了请求 : Http://localhost:8080/myWeb/index.jsp?intre=soccer&intre=soccer&intre=tennis

<%
	String []arr = request.getParameterValues("intre");
%>
	第一个值<%= arr[0]%>
	第二个值<%= arr[1]%>



-------------------使用内置对象-----------------------------
${paramValues.intre[0]}<br/>
${paramValues.intre[1]}

EL表达式直接在HTML中就是直接将结果给输出到响应体,在JavaScript中,可以用变量接收,代表将数据输出给变量

JSON传输

之前的JSON是从前台的角度考虑的,现在从Servlet的角度来考虑,也就是从后台考虑JSON的使用;首先复习一下,JSON是js中使用的一种对象标记语言,用来进行数据的传输;JS中数组是使用的中括号,JSON是大括号

var students = {
    "total" : 11,
    "data":[{"name":"Jning","no":21,"class":"HC2001"},{"name":"lisi","no":21,"class":"HC2001"}]
}

这里就是一个简单的JSON对象,total指出学生的个数,data存储了JSON数组

再JS中,使用JSON也非常简单,直接.引用

students.total = 11
students.data[0].name = Jning

这里再script域中,可以直接使用EL表达式将域中的对象赋值给变量,但是对象类型传递的不是内容,而是地址,所以无法正常使用

//var stu = cfeng.oa.entity.Student@7e9df29d;

这里就是,传递给stu的不是想要的学生的内容,而是传递了一个地址,js无法识别使用

但是普通的类型就可以;为了解决引用的问题,这里使用JSON来解决

//在servlet中使用JSON格式的字符串,要么使用转义字符,要么使用单引号,因为语法松散
Student stu = new Student(1, "张三", "HC2001");
String str = "{'name':'张三','class':'HC2001'}";     //JSON格式字符串

request.setAttribute("stu", str);

-------------------在JSP中使用EL表达式接收------------
    
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>信息JSON</title>
		<script type="text/javascript">
			var stu = ${requestScope.stu};
			window.alert("学生姓名:" + stu.name + " 学生班级" + stu.class);
		</script>
	</head>
	<body>
		这里就是JSP界面【】;
	</body>
</html>

这样就可以成功的弹窗了

JSON总结:
其实JSON存在的目的就是为了方便java和JavaScript之间进行对象类型的数据的共享;因为基本数据类型是可以直接通过EL表达式赋值给JavaScript中的变量; 但是对象类型不行 , 因为对象之间的赋值是通过的地址,但是java和JavaScript是不相通的; JavaScript只能找到JavaScript中的堆中的地址;JavaScript不能找到java堆中的地址

这个时候就通过JSON来将对象类型的数据给使用JSON字符串给存储,通过共享域传递给前台jsp;在jsp中就可以使用EL表达式获得JSON对象,这样就成功还原成了对象类型

JSON工具类

通过上面的JSON使用,就可以看到,如果每次都拼串十分麻烦,因为每次的对象都是不同的,所以就有必要将这个过程给封装为工具类【前面的一个最常用的工具类就是DBUtil了】

package cfeng.oa.utils;

import java.lang.reflect.Field;

//该工具类能传入一个任意类型的对象给转化为JSON类型字符串
public class JSONUtil {
	public static StringBuffer getJSON(Object obj) {
		StringBuffer str = new StringBuffer("{"); //使用String会浪费内存,不可修改
		//通过反射机制获得传入对象的类型
		@SuppressWarnings("rawtypes")
		Class cls = obj.getClass();
			//通过反射机制获得该类型对象的所有的属性【所有的属性不止一个,所以为数组】
		Field filedArray[] = cls.getDeclaredFields();
		//循环得到所有的属性
		try {
			for (int i = 0; i < filedArray.length; i++) {//不能使用foreach,最后一个不用加,
				Field field = filedArray[i];
				//确保所有的私有属性能够访问
				field.setAccessible(true); //filed为私有的时候也可以访问
				//获得属性的名称
				String fieldName = field.getName();
				//获得当前对象该属性的值
				Object value = field.get(obj);
				//将获得的属性拼串
				str.append("'" + fieldName + "':" + "'" + value + "'");
				if(i < filedArray.length - 1) {
					str.append(",");
				}
			}
			str.append("}");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return str;
	}
}

JSON工具类使用StringBuffer,因为String为final类,浪费空间;同时StringBuffer为线程安全的,因为使用了synchronized同步锁,StringBuilder则为不安全的;

这里主要就是使用了反射机制,这里获取类的字节码的方式为obj.getClass;获取类的属性就是用Filed来接收,Filed就是属性的字节码;代表的就是这个类的某个属性,通过getName可以获取这个属性的名称;通过get可以获取当前这个对象的该属性的值

这里就很简单了,之后转化的时候就直接使用反射机制先建立一个工具类来一键转换;官网还提供了方便的JSON工具包,有兴趣的可以下载,其实就是使用的反射机制,只是封装的功能更加的复杂;这个可以自己写的

MVC开发规则

MVC开发规则制定了---------- 互联网开发过程中必须出现的角色及其他们的担负的职责还有就是它们的出场顺序

互联网中角色

  • Dao对象 : Dao对象提供了某张表文件的操作细节,降低对表文件的操作难度,避免而来反复开发表文件操作的代码提高复用性
  • Service对象 : 服务对象,提供了【业务】的具体的解决办法;service对象一个方法制定了一个业务的解决方案;避免业务的重复性开发行为【比如转账业务】,提高复用性,网站每一个业务都有一个标准的解决方案

那么为了理解service,首先就要明白什么是业务?

业务就是 浏览器向服务器发送请求:或者说用户向网站发出请求

比如: 张三用户发送请求:要求在服务端实现将张三账户的3000转给李四

​ 这个就是一个完整的业务,所以在数据库中也就要求开启事务,一致性,要么都成功,要么都失败

  1. 判断”张三 是否为系统用户 【令牌机制 JSESSIONID】
  2. 判断 李四 是否为当前系统用户
  3. 读取张三的用户余额,判断余额是否充足
  4. 读取李四账户余额,备账
  5. 更新张三账户余额,“” -3000
  6. 更新李四账户余额 +3000

其实就类似于算法,也是解决一个问题提供的有限的步骤

业务特征

真实的业务场景中,一个业务往往包含多个分支任务,因此解决业务开发的工作量往往比较大

真实的业务场景中,只有所有的分支任务都能顺利成功解决,才可以认为业务处理成功

业务开发难点:

  1. 一个业务可能在网站的多个地方重复出现,如果不封装,增加开发难度,进行业务的重复性开发【比如转账会有很多的地方都要使用转账】
  2. 不同的programmer面对同一个业务时,给出解决方案往往有偏差,导致最终解决的数据有偏差

MVC分层 ⭐ ⭐ ⭐ ⭐ ⭐

一次开发中,必须出现的角色有三个:

  • C : controller object : 控制层对象 (Servlet对象)
  • M : model object : 业务模型对象 (service对象)
  • V : view object : 视图层对象 (JSP或者HttpServletResponse)

它们所担负的职责为:

  • C (Servlet对象) :

    • 【可以】调用请求对象,读取请求包中的参数信息
    • 【必须】 调用【Service对象】处理业务
    • 【必须】调用视图层对象(请求转发重定向)将结果写入到响应体
  • M(service对象)

    • 处理业务中所有的分支任务
    • 根据分支任务的执行情况判断业务是否处理成功
    • 必须通过return将处理结果返回给【控制层对象】
  • V(jsp/HttpServletResponse)

    • 禁止参与业务的处理
    • 唯一任务就是将处理的结果写入到响应体

调用的过程

请求调用的顺序: 浏览器------------发送请求----> servlet -----Service----> Dao

这里可以画一个图给大家展示一下,【这个分层和分包是没有具体的关系】
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值