openmeetings-db模块的结束

2021SC@SDUSC

在上一篇文章中开始了db模块下dao目录的分析,完成了basic子目录的全部源码分析和user子目录的部分源码分析。在本文中,我将会尽力完成user子目录的分析,并且发现dao目录下源码的规律,为进一步分析dto目录做准备。

根据之前的分析经验,由于我负责分析的源码部分代码量太大,之前分析得又比较仔细,导致节奏偏慢,因此在以后的源码中将会着重选择代码相对新奇、技术相对陌生的部分,其他部分只简单提及,以保证能够完成源码分析的任务。

目录

dao/user目录的结束

UserContactDao.java

User目录的总结

dao目录下其他子目录

db模块下manager目录

IClientManager.java

IStreamClientManager.java

IWhiteboardManager.java

db模块下dto目录

dto/basic目录

Health.java

info.java

SearchResult.java

ServiceResult.java

dto/user目录

UserDTO.java

GroupDTO.java

dto/user目录总结

dto目录总结

总结


dao/user目录的结束

UserContactDao.java

UserContactDao的意思是用户之间联系的数据访问对象,也就是会话的数据访问对象,这意味着可能会涉及多个用户之间的关系。首先看引入的内容:

openmeetings-db模块的结束_第1张图片

前面引入的是之前分析过的db模块util目录下的DaoHelper类的setLimits方法、util模块下OpenmeetingsVariables类定义的final字段PARAM_USER_ID和OpenmeetingsVariables类的getWebAppRootKey方法,这些都在之前的分析中见过。然后引入的是Date和List类,不再多说。接着引入的是上篇文章里提到的persistence类中的内容,最后还引入了日志相关、事务管理相关的内容。

看类的定义:

openmeetings-db模块的结束_第2张图片

首先一共有三个字段。第一个是老生常谈的log,第二个是持久化数据相关的EntityManager对象em, 最后一个是上一篇文章分析过的UserDao对象。这些变量都是见过的,没有什么特别的。

在UserContactDao.java中存在着许多之前分析过的方法,如get、delete、update等使用类和工具进行数据库操作的方法,这里都不作讨论。其余的方法逻辑都比较简单,例如add方法:

openmeetings-db模块的结束_第3张图片

在add方法中,形参有Long userId、Long ownerId、boolean pending,分别是用户的id、会话的owner的id、布尔变量pending。这其中,首先初始化一个UserContact对象,它是在之前分析过的db模块下entity目录下的UserContact类。然后根据形参对它进行初始化,然后返回该对象。因此,add方法的作用就是新建一个UserContact对象。

类里面的方法都诸如此类,难度较低,因此不再多说。附上全部源码:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.db.dao.user;

import static org.apache.openmeetings.db.util.DaoHelper.setLimits;
import static org.apache.openmeetings.util.OpenmeetingsVariables.PARAM_USER_ID;
import static org.apache.openmeetings.util.OpenmeetingsVariables.getWebAppRootKey;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import org.apache.openmeetings.db.entity.user.UserContact;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class UserContactDao {
	private static final Logger log = Red5LoggerFactory.getLogger(UserContactDao.class, getWebAppRootKey());
	@PersistenceContext
	private EntityManager em;
	@Autowired
	private UserDao userDao;

	public UserContact add(Long userId, Long ownerId, boolean pending) {
		try {
			UserContact userContact = new UserContact();
			userContact.setInserted(new Date());
			userContact.setOwner(userDao.get(ownerId));
			userContact.setContact(userDao.get(userId));
			userContact.setPending(pending);

			userContact = update(userContact);

			return userContact;
		} catch (Exception e) {
			log.error("[addUserContact]",e);
		}
		return null;
	}

	/**
	 * @param id - id of item to delete
	 */
	public void delete(Long id) {
		em.createNamedQuery("deleteUserContact").setParameter("id", id).executeUpdate();
	}

	/**
	 * @param ownerId - id of owner
	 * @return rowcount of update
	 */
	public Integer deleteAllUserContacts(Long ownerId) {
		return em.createNamedQuery("deleteAllUserContacts").setParameter("ownerId",ownerId).executeUpdate();
	}

	public UserContact get(Long userId, Long ownerId) {
		List ll = em.createNamedQuery("getContactByUserOwner", UserContact.class)
				.setParameter(PARAM_USER_ID, userId)
				.setParameter("ownerId", ownerId)
				.getResultList();
		log.info("number of contacts:: " + (ll == null ? null : ll.size()));
		return ll != null && ll.size() == 1 ? ll.get(0) : null;
	}

	public boolean isContact(Long userId, Long ownerId) {
		UserContact c = get(userId, ownerId);
		return c == null ? false : !c.isPending();
	}

	public List get(long ownerId, long first, long count) {
		return setLimits(
				em.createNamedQuery("getContactsByUser", UserContact.class).setParameter(PARAM_USER_ID, ownerId)
				, first, count).getResultList();
	}

	public long count(long ownerId) {
		TypedQuery q = em.createNamedQuery("countContactsByUser", Long.class);
		q.setParameter(PARAM_USER_ID, ownerId);
		return q.getSingleResult();
	}

	public List getContactsByUserAndStatus(Long ownerId, boolean pending) {
		return em.createNamedQuery("getContactsByUserAndStatus", UserContact.class)
				.setParameter("ownerId", ownerId)
				.setParameter("pending", pending)
				.getResultList();
	}

	public List getContactRequestsByUserAndStatus(Long userId, boolean pending) {
		return em.createNamedQuery("getContactRequestsByUserAndStatus", UserContact.class)
				.setParameter(PARAM_USER_ID, userId)
				.setParameter("pending", pending)
				.getResultList();
	}

	public UserContact get(Long id) {
		List list = em.createNamedQuery("getUserContactsById", UserContact.class)
				.setParameter("id", id).getResultList();
		return list.size() == 1 ? list.get(0) : null;
	}

	public List get() {
		return em.createNamedQuery("getUserContacts", UserContact.class).getResultList();
	}

	public Long updateContactStatus(Long id, boolean pending) {
		try {
			UserContact uc = get(id);
			uc.setPending(pending);
			update(uc);
			return id;
		} catch (Exception e) {
			log.error("[updateContactStatus]",e);
		}
		return null;
	}

	public UserContact update(UserContact c) {
		if (c.getId() == null) {
			c.setInserted(new Date());
			em.persist(c);
		} else {
			c.setUpdated(new Date());
			c = em.merge(c);
		}
		return c;
	}
}

User目录的总结

经过前面的分析可以得出,在user目录下,所有的数据访问对象的定义方式和源码内容格式几乎都是一样的,除去其功能的不同之外并没有太大的差别。因此,user目录下的其他源码就不再多说,如果在源码其他部分引用到时再按需查找其作用。

dao目录下其他子目录

进一步发现,在dao目录下的类和接口均是定义各种角色数据访问的类,例如record目录下是对用户的会话记录进行访问、room目录下是对房间的信息进行访问等,源码结构几乎完全相同。因此执行相同的策略,不再进行详细的分析,只在日后的分析中引用到时再进行详细地解释即可。

至此,db模块下dao目录的分析结束。

db模块下manager目录

manager目录提供了三个接口:

openmeetings-db模块的结束_第4张图片

可以看到,这三个接口分别定义了对客户、对客户的流信息以及白板的管理。接下来,我们将快速分析这三个接口。 

IClientManager.java

openmeetings-db模块的结束_第5张图片

整个接口的实现非常简单。前面引入的除了Collection、List、Set三个类之外,就是之前分析过的在entity目录下的Client类和IClient接口了,其中Client类实现了IClient接口。

在接口的定义中,定义了get、getBySid等方法,等待实现类去实现。最后还定义了getActiveRoomIds方法,返回一个Long类型的集合Set,目的是得到系统中所有有用户的房间的Id。

IStreamClientManager.java

前面见过,StreamClient类是可以被配置为存储到数据库或者内存中的、与房间中对用户信息的操作选项相关的类。因此,IStreamClientManager接口应该也实现了类似的功能。先看其引入的内容:

openmeetings-db模块的结束_第6张图片

前面引入的两个类分别是List和Set,而后面两个则是IClient和StreamClient类。

在接口的定义中,有比较完整的注释:

openmeetings-db模块的结束_第7张图片

首先可以看到的是,接口定义了一些在会话或者记录中添加、获取或移除StreamClient的方法。比如第一个add方法,可以将形参StreamClient c添加到会话中,后面的list和get方法都是获取一系列或者单个StreamClient对象。 

再下面:

openmeetings-db模块的结束_第8张图片

update、remove等方法都是基于这个作用定义的方法。后面的getRecordingCount是获取该房间中正在记录(视频或声音)的用户的个数;getPublishingCount是获取现在正在分享屏幕的用户的个数。

openmeetings-db模块的结束_第9张图片最后的两个方法分别是getBroadcastingCount和getActiveRoomIds。前者是获取房间中正在分析音频或者视频数据给服务器的用户个数;后者是获取在特定的服务器上正在工作的房间的个数。

由此可见,IStreamClientManager定义了一系列与用户、房间状态相关的操作。

IWhiteboardManager.java

IWhiteboardManager接口就相对简单些了,它主要是对白板的状态进行控制。直接看接口的定义:

openmeetings-db模块的结束_第10张图片

它引入了db模块下还没分析的dto目录下的Whiteboards类,但这并不影响我们分析。 在接口中,定义了get方法,可以根据Long roomId获取白板,还有remove方法,可以根据roomId移除对应的白板,非常简单。

至此,db模块下的manager目录分析结束。在这个目录里定义了三个接口,对用户、房间、白板等角色的状态进行了控制与管理。

db模块下dto目录

至此,在db模块还有最后一个目录,即dto目录。之前提到过,dto的意思是Data Transfer Object,即数据传输对象。因此,在dto目录下的类和接口等应该都是与数据的传输相关。看其结构:

openmeetings-db模块的结束_第11张图片

相比entity目录、dao目录,dto目录的结构更加简单,每个子目录下面不再有进一步的子目录。它的命名与dao目录很相似,包括user、basic、calendar等。按照分析dao目录的经验,如果dto目录下的源码都存在一定程度的相似性,则也可以直接略过,等到在其他源码中引用到时再进行详解。接下来,就展开dto目录下子目录的分析。为了与dao目录形成对比,先进行basic和user两个子目录的分析。

dto/basic目录

在basic目录下,存在4个java文件:

openmeetings-db模块的结束_第12张图片

分别是Health.java、Info.java、SearchResult.java、ServiceResult.java,依次进行这些源码的分析。

Health.java

Health的字面意思是健康,这意味着Health.java可能与用户的使用情况或系统的状况有关系。看其引入的内容:

openmeetings-db模块的结束_第13张图片

前面引入的两个分别是util模块下的OpenmeetingsVariables的isInitComplete方法和Serializable接口,都比较熟悉。而后面的三个则是相对陌生的javax.xml.bind.annotation下的类。


关于javax.xml.bind.annotation包,简要做一下说明(参考自总结javax.xml.bind.annotation (Java SE 9 & JDK 9 )):

openmeetings-db模块的结束_第14张图片

之前介绍过关于xml模式的映射注解的类,因此这里也不再特别详细地说,只简单提一下引用到的几个类的作用,了解即可,详细用法再遇到可以到该网站查询。

关于XmlAccessorType:

openmeetings-db模块的结束_第15张图片

 其作用是控制默认情况下是否序列化字段或 Javabean 属性。

关于XmlRootElement:

openmeetings-db模块的结束_第16张图片

其作用是将类或枚举类型映射到 XML 元素。


看类的定义:

openmeetings-db模块的结束_第17张图片首先使用了@XmlRootElement和@XmlAccessorType两个注解。然后说明,Health类实现了Serializable接口,即可序列化。

类的第一个字段是常见的serialVersionUID(序列化版本号)。此外,最后是三个布尔变量,分别是inited、installed和dbOk,对应判断是否已初始化、已安装、数据库是否正常。这里就已经可以看出,需要对系统的状况做一些判断,为之后数据的传输做准备。而第二个字段,是一个static final变量INSTANCE,它的类型也是Health,这中定义有点像链表的定义,但它是一个静态变量,意味着所有的Health对象都共享这一个实例。

再往下看:

openmeetings-db模块的结束_第18张图片

首先看到的是构造器。在构造器中,inited变量被赋值为调用引入的isInitComplete方法来确定。由此可见,util模块下的isInitComplete方法是检查系统是否初始化成功。

接下来的三个都是getters和setters,没有什么好说的,值得注意的是setters的返回值都是this,而不是void。

至此,Health.java分析完毕。它主要完成了对系统的准备配置的检查。附上源码:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.db.dto.basic;
import static org.apache.openmeetings.util.OpenmeetingsVariables.isInitComplete;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Health implements Serializable {
	private static final long serialVersionUID = 1L;
	public static final Health INSTANCE = new Health();
	private boolean inited;
	private boolean installed;
	private boolean dbOk;

	public Health() {
		inited = isInitComplete();
	}

	public boolean isInited() {
		return inited;
	}

	public Health setInited(boolean inited) {
		this.inited = inited;
		return this;
	}

	public boolean isInstalled() {
		return installed;
	}

	public Health setInstalled(boolean installed) {
		this.installed = installed;
		return this;
	}

	public boolean isDbOk() {
		return dbOk;
	}

	public Health setDbOk(boolean dbOk) {
		this.dbOk = dbOk;
		return this;
	}
}

info.java

info是信息的意思,所以在info.java中应该是对信息相关的一些操作。看其引入的内容:

openmeetings-db模块的结束_第19张图片

引入的内容都是见过的,包括Serializable、中间的三个以及最后util模块下的Version类。

直接看类的定义:

openmeetings-db模块的结束_第20张图片

Info类也实现了Serializable接口,也是可序列化的。在其中的字段中,保存了包括serialVersionUID,以及三个String类型变量,分别是version、revision、buildDate,意思是版本、修改、创建日期,用来保存系统的版本信息、更新信息和创建的日期。而这些都是final变量,因此是不可修改的,所以Info类只有getters,没有setters。

至此,Info类分析完毕,保存了系统的一系列信息。源码已经全在图里,所以不再给出。

SearchResult.java

SearchResult是搜索的结果。这部分的内容也不难,看源码:

openmeetings-db模块的结束_第21张图片

源码只引入了一个Collection类。类还是一个模板定义,用T类型决定字段中Collection类对象的元素类型。

在类体内,定义了四个字段,全都是private的,分别是String objectName、Long records、Collection result、String errorKey。 它们对应搜索得到的对象名、记录、结果集合、错误关键字。其具体应用场景比较难以界定,但逻辑很容易。

最后的方法都是getters和setters,没有什么好说的。至此,SearchResult.java分析结束。源码在图中,也不再附上。

ServiceResult.java

ServiceResult是服务的结果,应该是在系统进行某个操作结束后作出的一些结果。

看其引入的内容:

openmeetings-db模块的结束_第22张图片

先引入了Serializable接口,中间的部分同样也是annotation包里的相关的注解,最后是util模块下的异常类OmException。 

看类的定义:

openmeetings-db模块的结束_第23张图片

ServiceResult类首先实现了Serializable接口。其中的字段,serialVersionUID是常见的了。后面有两个static final变量,类型也是ServiceResult,分别是UNKNOWN和NO_PERMISSION,这也是所有ServiceResult对象共享的。后面两个是String message和String type,是服务结果的消息和类型。最后一个定义了枚举类型Type,其中两个字段是ERROR和SUCCESS。字段的内容也比较简单。

下面的方法都是构造器、getters和setters,都比较容易,所以没什么好说的。ServiceResult类的应用场景也比较难确定,但也很简单,所以等到具体应用时再具体情况具体分析即可。

附上源码:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.db.dto.basic;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.apache.openmeetings.util.OmException;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ServiceResult implements Serializable {
	private static final long serialVersionUID = 1L;
	public static final ServiceResult UNKNOWN = new ServiceResult(OmException.UNKNOWN.getKey(), Type.ERROR);
	public static final ServiceResult NO_PERMISSION = new ServiceResult("error.notallowed", Type.ERROR);
	private String message;
	private String type;
	@XmlType(namespace="org.apache.openmeetings.db.dto.basic.type")
	public enum Type {
		ERROR
		, SUCCESS
	}

	public ServiceResult() {
		//def constructor
	}

	public ServiceResult(String message, String type) {
		super();
		this.message = message;
		this.type = type;
	}

	public ServiceResult(String message, Type type) {
		this(message, type.name());
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
}

到这里,dto目录下的basic子目录已经分析结束。basic目录定义了功能启动前的准备、服务过程中的一些结果,为数据传输做准备。

dto/user目录

接下来我们看user子目录,其结构如下:

openmeetings-db模块的结束_第24张图片

一共有5个java文件。

UserDTO.java

UserDTO.java是用户信息的数据传输对象。看其引入的内容:

openmeetings-db模块的结束_第25张图片

首先引入的是db模块下util目录下DtoHelper类下面的三个方法,用来确定形参的对象是否含有某个属性,并且进一步进行一些判断。接下来引入的是Serializable、ArrayList、HashSet、List、Set,都是经常见到的了。再下面是annotation包下面的XmlRootElement注解。后面引入的是db模块下dao目录的UserDao类,以及entity目录下的一些内容。最后引入的是JSONObject。

看类的定义:

openmeetings-db模块的结束_第26张图片

UserDTO实现了Serializable接口。类的字段中,除了serialVersionUID,就是诸如id、login、password、firstname、lastname等,这就代表了用户的一系列信息。

再下面:

openmeetings-db模块的结束_第27张图片 

这里是UserDTO类的构造器。除了默认的空构造器,还有根据User对象初始化UserDTO对象的构造器,即直接获取User对象的各个字段值,用它来初始化UserDTO。

继续往下看:

openmeetings-db模块的结束_第28张图片

下面是一个get方法,返回值类型是User,传入的形参是UserDao userDao。新建一个User u,如果id为空,则new一个User对象赋值给u,否则根据userDao的内容根据this.id获取User对象赋值给u。接下来,将u的各项信息赋值为当前UserDTO对象的对应信息。总的来看,get方法是通过UserDTO类初始化一个User对象,并且返回。

接下来是list方法,传入的参数是List l,使用l中的每个User对象初始化UserDTO对象,放到一个List中,并且返回。它的作用可见是根据User类型的List初始化一系列UserDao对象。

接下来的部分就只是getters和setters,此外还有一个static的get方法,其逻辑也比较简单,不再多提。

至此,UserDTO.java分析完毕。它可以在User对象和本身之间进行一系列转换,便于数据的传输。附上源码:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.db.dto.user;

import static org.apache.openmeetings.db.util.DtoHelper.optEnum;
import static org.apache.openmeetings.db.util.DtoHelper.optEnumList;
import static org.apache.openmeetings.db.util.DtoHelper.optLong;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.bind.annotation.XmlRootElement;

import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.user.Address;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.db.entity.user.User.Right;
import org.apache.openmeetings.db.entity.user.User.Type;

import com.github.openjson.JSONObject;

@XmlRootElement
public class UserDTO implements Serializable {
	private static final long serialVersionUID = 1L;
	private Long id;
	private String login;
	private String password;
	private String firstname;
	private String lastname;
	private Set rights = new HashSet<>();
	private Long languageId;
	private Address address = new Address();
	private String timeZoneId;
	private String externalId;
	private String externalType;
	private String pictureUri;
	private Type type = Type.user;

	public UserDTO() {
		//def constructor
	}

	public UserDTO(User u) {
		id = u.getId();
		firstname = u.getFirstname();
		lastname = u.getLastname();
		rights = u.getRights();
		login = u.getLogin();
		languageId = u.getLanguageId();
		address = u.getAddress();
		timeZoneId = u.getTimeZoneId();
		type = u.getType();
		externalId = u.getExternalId();
		externalType = u.getExternalType();
		pictureUri = u.getPictureUri();
	}

	public User get(UserDao userDao) {
		User u = id == null ? new User() : userDao.get(id);
		u.setLogin(login);
		u.setFirstname(firstname);
		u.setLastname(lastname);
		u.setRights(rights);
		u.setLanguageId(languageId);
		u.setAddress(address);
		u.setTimeZoneId(timeZoneId);
		u.setExternalId(externalId);
		u.setExternalType(externalType);
		u.setType(type);
		u.setPictureUri(pictureUri);
		return u;
	}

	public static List list(List l) {
		List uList = new ArrayList<>();
		if (l != null) {
			for (User u : l) {
				uList.add(new UserDTO(u));
			}
		}
		return uList;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getFirstname() {
		return firstname;
	}

	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}

	public String getLastname() {
		return lastname;
	}

	public void setLastname(String lastname) {
		this.lastname = lastname;
	}

	public Set getRights() {
		return rights;
	}

	public void setRights(Set rights) {
		this.rights = rights;
	}

	public String getLogin() {
		return login;
	}

	public void setLogin(String login) {
		this.login = login;
	}

	public Long getLanguageId() {
		return languageId;
	}

	public void setLanguageId(Long languageId) {
		this.languageId = languageId;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public String getTimeZoneId() {
		return timeZoneId;
	}

	public void setTimeZoneId(String timeZoneId) {
		this.timeZoneId = timeZoneId;
	}

	public Type getType() {
		return type;
	}

	public void setType(Type type) {
		this.type = type;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getExternalId() {
		return externalId;
	}

	public void setExternalId(String externalId) {
		this.externalId = externalId;
	}

	public String getExternalType() {
		return externalType;
	}

	public void setExternalType(String externalType) {
		this.externalType = externalType;
	}

	public String getPictureUri() {
		return pictureUri;
	}

	public void setPictureUri(String pictureUri) {
		this.pictureUri = pictureUri;
	}

	public static UserDTO fromString(String s) {
		return get(new JSONObject(s));
	}

	public static UserDTO get(JSONObject o) {
		if (o == null) {
			return null;
		}
		UserDTO u = new UserDTO();
		u.id = optLong(o, "id");
		u.login = o.optString("login");
		u.password = o.optString("password");
		u.firstname = o.optString("firstname");
		u.lastname = o.optString("lastname");
		u.rights.addAll(optEnumList(Right.class, o.optJSONArray("rights")));
		u.languageId = o.optLong("languageId");
		JSONObject a = o.optJSONObject("address");
		if (a != null) {
			u.address.setId(optLong(a, "id"));
			u.address.setCountry(a.optString("country"));
			u.address.setEmail(a.optString("email"));
		}
		u.timeZoneId = o.optString("timeZoneId");
		u.externalId = o.optString("externalId", null);
		u.externalType = o.optString("externalType", null);
		u.type = optEnum(Type.class, o, "type");
		u.pictureUri = o.optString("pictureUri", null);
		return u;
	}

	@Override
	public String toString() {
		return new JSONObject(this).toString();
	}
}

GroupDTO.java

GroupDTO的意思应该是群组的数据传输对象。看其引入的内容:

openmeetings-db模块的结束_第29张图片

引入的内容包括Serializable、ArrayList、List、XmlRootElement类,还有db模块下dao目录下的GroupDao类和entity目录下的Group类,都是见过的。

看类的定义:

openmeetings-db模块的结束_第30张图片

首先,GroupDTO实现了Serializable接口。类的字段包括Long id、String name、String tag,分别是群组的id、名字、标签。在构造器中,GroupDTO类是通过Group类对象g初始化的,将g的字段值分别赋值给GroupDTO的相关字段。可见,它仍然起到了数据转换的作用。

后面也提供了与UserDTO类相似的get、list方法,最后还有getters和setters等一系列方法。

附上全部源码:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.db.dto.user;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

import org.apache.openmeetings.db.dao.user.GroupDao;
import org.apache.openmeetings.db.entity.user.Group;

@XmlRootElement
public class GroupDTO implements Serializable {
	private static final long serialVersionUID = 1L;
	private Long id;
	private String name;
	private String tag;

	public GroupDTO() {
		//def constructor
	}

	public GroupDTO(Group g) {
		id = g.getId();
		name = g.getName();
		tag = g.getTag();
	}

	public Group get(GroupDao groupDao) {
		Group g = id == null ? new Group() : groupDao.get(id);
		g.setName(name);
		g.setTag(tag);
		return g;
	}

	public static List list(List l) {
		List gList = new ArrayList<>();
		if (l != null) {
			for (Group g : l) {
				gList.add(new GroupDTO(g));
			}
		}
		return gList;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTag() {
		return tag;
	}

	public void setTag(String tag) {
		this.tag = tag;
	}
}

dto/user目录总结

分析了user目录下的以上两个文件,发现所有java文件都具有相似性。所以,user目录其他的3个java文件就不再继续分析了,只需认清其基本含义即可。

dto目录总结

再进一步分析发现,在dto目录下的类,都是以数据传输为目的,通过定义一系列可以与entity目录下的各个角色相对应的数据传输类,完成数据的封装,实现数据在数据库和网络之间的传输。这个观点在详细查看各个类的源码后得以验证,因此dto目录可以认为已经分析结束。

总结

在本文中,结束了db模块下dao目录的分析,又完成了manager目录和dto目录的分析,这样就结束了整个db模块的分析。在db模块中,java源码完成了java对象和数据库实体之间的映射,也完成了数据库中数据的调用与传输封装。整个模块的源代码量非常大,遇到的新的知识也非常多。经过对这个模块的分析,我也学习到了许多。

完成了db模块的分析后,就要展开core模块的分析了。在core模块中,我将仍然采用只分析重难点、新颖点的分析方法,忽略重复性分析,加快分析速度,保证能够在最后日期之前结束分析。

你可能感兴趣的:(软件工程应用与实践,java,maven,intellij,idea)