OA的学习--第四天的内容--优化功能和页面

    这是OA第4天学习内容的总结,这个是写于3月4号的,所以有部分内容刚刚第三天的19号写的,里面已经介绍了。
    第四天的内容是从28集到34集,先是讲了处理3个细节的问题.1.回到上一级,2.删除/修改/添加之后回到当前页面,而不是顶级页面;还有懒加载问题的解决,通过配置OpenSessionInViewFilter达到Session在Service之后不关闭,而是在结束Filter或者Interceptor之后再结束.
    还有就是添加/修改页面的部门的树形结构的选择,使用了递归的方式来生成树,并且设置了树的排序方式.
    以及在多次写Action之后,抽取BaseAction,将继承ActionSupport和实现ModelDriven都交由BaseAction来处理,当前getModel也通过泛型和反射来处理了.而使用的各种Service也在BaseAction中声明,因为Service本身就是单例的,所以只要在BaseAction中实例过一次,继承BaseAction的子类就不用再实例化了.
    并且,同样理由,整理了页面,将导入js和css样式和引入标签都抽取放在了公共片段文件中,用的时候只需要将该.jspf片段文件导入.
    其中,将介绍各个点的内容.

回到上一级

    这个代码很简单,只需要在页面上添加一段链接的html语句就可以了.在list.jsp页面中,添加这一段,其中图片内容就是"返回到上一级",并且需要带上参数parentId作为参数,他是上级部门的上级部门的id.就是当在第三级部门,返回到上一级,也就是第二级部门,而第二级部门的parentId就是第一级部门的id.

<s:a action="department_list?parentId=%{#parent.parent.id}"><img src="${pageContext.request.contextPath}/style/blue/images/button/ReturnToPrevLevel.png"/></s:a>

    下面是代码分析:

    点击该图片的时候,会根据action到struts.xml配置的action中来处理,department_list,对应的method为list.所以去执行list方法.
<!-- 部门管理 -->
<action name="department_*" class="departmentAction" method="{1}">
	<result name="list">/WEB-INF/jsp/departmentAction/list.jsp</result>
	<result name="saveUI">/WEB-INF/jsp/departmentAction/saveUI.jsp</result>
	<result name="toList" type="redirectAction">department_list?parentId=${parentId}</result>
</action>
     在DepartmentAction类中的list方法,将传递过来的parent.parent.id作为parentId来处理.所以经过else的处理,会显示上上级的子部门即上级.其中在else处理的时候,将上上级的部门也回显到了页面上.是因为,若在当前页面没有上上级部门对象回显到页面上,是获取不到上上级部门的id的,那么就没法传递参数了.
private Long parentId;
/**
 * 列表
 * @return
 * @throws Exception
 */
public String list() throws Exception {
	 //回显到前台的部门列表
	 List<Department> departmentList = null;
	 
	 //根据传递上级部门id是否为空,查询所有顶级部门还是该上级部门的所有子部门.
	 if(parentId == null) {
		 departmentList = departmentService.findTopList();
	 }else {
		 departmentList = departmentService.findChildren(parentId);
		 //根据该Id,获取上级部门对象,并设置到值栈的map中.
		 Department parent = departmentService.getById(parentId);
		 ActionContext.getContext().put("parent", parent);
	 }
	
	 //将部门列表页设置到map中,到前台回显
	 ActionContext.getContext().put("departmentList", departmentList);
	 return "list";
}

public Long getParentId() {
	return parentId;
}

public void setParentId(Long parentId) {
	this.parentId = parentId;

}
     最后返回"list"的result,根据action的result标签处理,转到list.jsp页面,将上级部门列表显示.效果就是这样。

    从第二级 点击返回上一级到顶级部门

懒加载的问题OpenSessionInViewFilter

    懒加载的问题原因是因为hibernate允许关联对象,而为了提高效率,所以默认这种都是带有延迟加载的.若Service层返回了一个启动了懒加载功能的对象给web层,当web层访问到那些需要延迟加载的数据时,由于Session 已经关闭了,所以没法在用hibernate的级联查询来获取值,导致延迟加载的数据访问异常.

    图像表示就是上图,在Action中需要调用Service,在Service中会开启和关闭Session,并会返回一个Result,而对于带有懒加载功能的Result,若在页面上使用,此时session已经关闭,则访问异常.所以只要session的不关闭,问题就可以解决了.当然去掉懒加载问题也可以解决,只是懒加载在提高性能方面有很好的效果,关掉实在可惜。      
    解决的图像就是,将session的关闭延迟到Filter或者是Interceptor结束之后再关闭.

    OpenSessionInViewFilter的处理,就是在web.xml文件中配置一个过滤器,就可以实现了.只是要注意这个filter一定要在struts2的过滤器前面.
<!-- 配置spring的用于解决懒加载问题的过滤器 -->
<filter>
	<filter-name>OpenSessionInViewFilter</filter-name>
	<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>

<filter-mapping>
	<filter-name>OpenSessionInViewFilter</filter-name>
	<url-pattern>*.action</url-pattern>
</filter-mapping>

递归的树形结构

    递归,感觉就是不停的调用自己.而什么情况下,会用递归,我也挺晕的,不过据说树形结构中使用递归是很方便.

    如需按照层次打印各个节点的名称.就可以将根节点传入,然后先打印根节点的名称,再用getChildren获取根节点的0个或多个子节点,遍历各个子节点,可以再来一遍,将子节点传入,打印子节点的名称,在获取子子节点.
/**
 * 显示一颗部门树中所有节点的信息
 * 
 * @param top
 *            树的顶点(根节点)
 */
private void showTree(Department top) {
	// 顶点
	System.out.println(top.getName());
	// 子树
	for (Department child : top.getChildren()) {
		showTree(child);
	}
}
     也可以直接处理多棵树,传入根节点的list,遍历list,先打印根节点的名称,然后再来一遍,传入子节点list,再打印子节点中的根节点的名称,一直递归到没有子节点.
/**
 * 显示多颗树的所有节点的信息
 * 
 * @param topList
 */
private void showTreeList(Collection<Department> topList) {
	for (Department top : topList) {
		// 顶点
		System.out.println(top.getName());
		// 子树
		showTreeList(top.getChildren());
	}
}
     其中,这样的结果是没有层次的,要加上层次,可以带上前缀.在递归的方法中,多加一个参数,在最开始调用的时候写上需要的前缀"┣",而每往下调用深一层,加上前缀空格"    ",
/**
 * 练习二:打印所有顶层部门及其子孙部门的信息(名称),用不同的缩进表示层次(使用全角空格)。<br>
 * 子部门的名称前比上级部门多一个空格,最顶层部门的名字前没有空格。 提示:假设有一个打印部门集合中所有部门信息的方法
 * 
 * 要求打印如下效果:
 * 
 * <pre>
 * ┣市场部
 *    ┣宣传部
 *    ┣业务部
 *       ┣业务一部
 *       ┣业务二部
 * ┣开发部
 *    ┣开发一部
 *    ┣开发二部
 * </pre>
 */
@Test
public void printAllDepts_2() {
	List<Department> topList = findTopLevelDepartmentList();

	showTreeList_2(topList, "┣");
}

// 显示树
private void showTreeList_2(Collection<Department> topList, String prefix) {
	for (Department top : topList) {
		// 顶点
		System.out.println(prefix + top.getName());
		// 子树
		showTreeList_2(top.getChildren(), "    " + prefix);//全角字符
	}
}
     而显示到界面是需要在下拉框中显示,效果是这样的

     其中显示的代码是这样的,接收到回显的部门列表数据,id作为key,name作为value显示到下拉框中。
 <tr><td width="100">上级部门<br></td>
	<td>
		<s:select name="parentId" cssClass="SelectStyle" 
			list="#departmentList" listKey="id" listValue="name"
			headerKey="" headerValue="==请选择部门=="/>
		 
	<br></td>
</tr>
     所以需要控制从后台传递过来的部门列表数据,其中name的值应该是" ┣21"这样类似显示的,所以将代码中的打印名称,改为setName,department.setName((prefix + top.getName()); 
    并且由于department的getChildren()的结果类型是Set类型,是无序的,所以在显示下级部门的时候,顺序是不定的.不过,只要在实体的配置文件中,加上order-by属性就可以解决了
.
<!-- children属性,本类与Department(下级)的一对多 -->
<set name="children" cascade="delete" order-by="id ASC"  >
	<key column="parentId"></key>
	<one-to-many class="Department"/>
</set>
     这样执行的sql语句的效果就是这样的,在最后加上了order by id asc.
Hibernate: select children0_.parentId as parentId3_1_, children0_.id as id1_, children0_.id as id3_0_, children0_.name as name3_0_, children0_.description as descript3_3_0_, children0_.parentId as parentId3_0_ from itcast_department children0_ where children0_.parentId=? order by children0_.id asc

抽取BaseAction 

    由于RoleAction和DepartmentAction,都需要继承ActionSupport和实现ModelDriven,并实现getModel方法,以及需要实例化相应的Service.Action虽然是多例的,并且Action中可以有1个或多个Service,但是Service并没有设置他们的scope是多例的,所以他们是单例的,只要在BaseAction中实例化一次,那么子类就可以用,完全可以做到公用.
    代码就是如下,主要就是需要使用泛型,在BaseAction的构造函数中,通过反射创建model的实例.
    先是获取this也就是BaseAction的子类,如DepartmentAction的对象,getClass().getGenerisSuperClass()获取DepartmentAction传入的泛型的参数类型,其中对于实体来说参数只有1个,对于键值对key,value,参数有两个.所以这里只需要取第一个参数的类型,就是泛型实体的真正类型.
public abstract class BaseAction<T> extends ActionSupport implements ModelDriven<T> {

	//=============Service实例的声明=============
	@Resource
	protected DepartmentService departmentService;
	@Resource
	protected RoleService roleService;
	
	
	//=============ModelDrvien的支持=============
	protected T model;
	
	public BaseAction() {
		
		//通过反射获取model的真实类型
		//通过反射创建model的实例
		try {
			ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
			Class<T> clazz = (Class<T>)pt.getActualTypeArguments()[0];
			model = clazz.newInstance();
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public T getModel() {
		
		return model;
	}
	
}

JS和CSS样式导入的公共代码抽取

    由于每个页面都需要引入js脚本文件和css样式,以及taglib的标签,所以将他们提取出来放到一个公共的片段文件中,叫common.jspf.
<%@ taglib prefix="s" uri="/struts-tags" %>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script language="javascript" src="${pageContext.request.contextPath}/script/jquery.js"></script>
<script language="javascript" src="${pageContext.request.contextPath}/script/pageCommon.js" charset="utf-8"></script>
<script language="javascript" src="${pageContext.request.contextPath}/script/PageUtils.js" charset="utf-8"></script>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/style/blue/pageCommon.css" />
<script type="text/javascript">
</script>
     而原来的jsp页面,只需要引入该jspf,就可以引入这些脚本和样式和标签.使用include file.
<head>
    <title>部门列表</title>
	<%@ include file="/WEB-INF/jsp/public/commons.jspf" %>
</head>
     今天学习的内容就是这些.其中对于树形结构,递归的使用,需要多多练习,虽然知道递归,但是一般的时候都想不起来用,并且就算想起来,也不能一次写成功,一般都是一遍一遍的测,然后才能把代码写对.感觉自己需要学习的还有很多.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 内容概要 《计算机网络》文档包含了70个关于计算机网络基础知识的单项选择题,内容涉及互联网起源、网络协议、IP地址、DNS服务、电子邮件、网络拓扑结构、网络设备、网络连接方式、网络速度等多个方面。每个问题后面都提供了正确答案,适合作为学习和测试材料。 ### 适用人群 本文档适合以下人群: - 计算机科学与技术、信息技术、网络工程等专业的在校学生。 - 准备计算机网络相关考试或认证的专业人士。 - 对计算机网络基础知识感兴趣的自学者。 - 信息技术教师,作为教学资源或测试材料。 ### 使用场景及目标 1. **学习测试**:作为学生学习计算机网络理论知识后的测试工具,检验学习效果。 2. **教学辅助**:教师可以用于课堂教学,作为课后作业或课堂小测验,增强学生的理解和记忆。 3. **自学检验**:个人自学者可以通过这些题目检验自己对计算机网络基础知识的掌握程度。 4. **职业发展**:职场人士可以通过学习和测试,提升自己在计算机网络领域的专业能力。 5. **竞赛准备**:适合准备计算机网络相关竞赛的学生,作为强化训练材料。 文档的目标是通过这些精心设计的题目,帮助读者全面了解和掌握计算机网络的基本概念、原理和应用,提高解决实际问题的能力。通过学习和练习,读者将能够更加深入地理解计算机网络的工作原理,为进一步的专业学习或职业发展打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值