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目录总结
总结
UserContactDao的意思是用户之间联系的数据访问对象,也就是会话的数据访问对象,这意味着可能会涉及多个用户之间的关系。首先看引入的内容:
前面引入的是之前分析过的db模块util目录下的DaoHelper类的setLimits方法、util模块下OpenmeetingsVariables类定义的final字段PARAM_USER_ID和OpenmeetingsVariables类的getWebAppRootKey方法,这些都在之前的分析中见过。然后引入的是Date和List类,不再多说。接着引入的是上篇文章里提到的persistence类中的内容,最后还引入了日志相关、事务管理相关的内容。
看类的定义:
首先一共有三个字段。第一个是老生常谈的log,第二个是持久化数据相关的EntityManager对象em, 最后一个是上一篇文章分析过的UserDao对象。这些变量都是见过的,没有什么特别的。
在UserContactDao.java中存在着许多之前分析过的方法,如get、delete、update等使用类和工具进行数据库操作的方法,这里都不作讨论。其余的方法逻辑都比较简单,例如add方法:
在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目录下的其他源码就不再多说,如果在源码其他部分引用到时再按需查找其作用。
进一步发现,在dao目录下的类和接口均是定义各种角色数据访问的类,例如record目录下是对用户的会话记录进行访问、room目录下是对房间的信息进行访问等,源码结构几乎完全相同。因此执行相同的策略,不再进行详细的分析,只在日后的分析中引用到时再进行详细地解释即可。
至此,db模块下dao目录的分析结束。
manager目录提供了三个接口:
可以看到,这三个接口分别定义了对客户、对客户的流信息以及白板的管理。接下来,我们将快速分析这三个接口。
整个接口的实现非常简单。前面引入的除了Collection、List、Set三个类之外,就是之前分析过的在entity目录下的Client类和IClient接口了,其中Client类实现了IClient接口。
在接口的定义中,定义了get、getBySid等方法,等待实现类去实现。最后还定义了getActiveRoomIds方法,返回一个Long类型的集合Set,目的是得到系统中所有有用户的房间的Id。
前面见过,StreamClient类是可以被配置为存储到数据库或者内存中的、与房间中对用户信息的操作选项相关的类。因此,IStreamClientManager接口应该也实现了类似的功能。先看其引入的内容:
前面引入的两个类分别是List和Set,而后面两个则是IClient和StreamClient类。
在接口的定义中,有比较完整的注释:
首先可以看到的是,接口定义了一些在会话或者记录中添加、获取或移除StreamClient的方法。比如第一个add方法,可以将形参StreamClient c添加到会话中,后面的list和get方法都是获取一系列或者单个StreamClient对象。
再下面:
update、remove等方法都是基于这个作用定义的方法。后面的getRecordingCount是获取该房间中正在记录(视频或声音)的用户的个数;getPublishingCount是获取现在正在分享屏幕的用户的个数。
最后的两个方法分别是getBroadcastingCount和getActiveRoomIds。前者是获取房间中正在分析音频或者视频数据给服务器的用户个数;后者是获取在特定的服务器上正在工作的房间的个数。
由此可见,IStreamClientManager定义了一系列与用户、房间状态相关的操作。
IWhiteboardManager接口就相对简单些了,它主要是对白板的状态进行控制。直接看接口的定义:
它引入了db模块下还没分析的dto目录下的Whiteboards类,但这并不影响我们分析。 在接口中,定义了get方法,可以根据Long roomId获取白板,还有remove方法,可以根据roomId移除对应的白板,非常简单。
至此,db模块下的manager目录分析结束。在这个目录里定义了三个接口,对用户、房间、白板等角色的状态进行了控制与管理。
至此,在db模块还有最后一个目录,即dto目录。之前提到过,dto的意思是Data Transfer Object,即数据传输对象。因此,在dto目录下的类和接口等应该都是与数据的传输相关。看其结构:
相比entity目录、dao目录,dto目录的结构更加简单,每个子目录下面不再有进一步的子目录。它的命名与dao目录很相似,包括user、basic、calendar等。按照分析dao目录的经验,如果dto目录下的源码都存在一定程度的相似性,则也可以直接略过,等到在其他源码中引用到时再进行详解。接下来,就展开dto目录下子目录的分析。为了与dao目录形成对比,先进行basic和user两个子目录的分析。
在basic目录下,存在4个java文件:
分别是Health.java、Info.java、SearchResult.java、ServiceResult.java,依次进行这些源码的分析。
Health的字面意思是健康,这意味着Health.java可能与用户的使用情况或系统的状况有关系。看其引入的内容:
前面引入的两个分别是util模块下的OpenmeetingsVariables的isInitComplete方法和Serializable接口,都比较熟悉。而后面的三个则是相对陌生的javax.xml.bind.annotation下的类。
关于javax.xml.bind.annotation包,简要做一下说明(参考自总结javax.xml.bind.annotation (Java SE 9 & JDK 9 )):
之前介绍过关于xml模式的映射注解的类,因此这里也不再特别详细地说,只简单提一下引用到的几个类的作用,了解即可,详细用法再遇到可以到该网站查询。
关于XmlAccessorType:
其作用是控制默认情况下是否序列化字段或 Javabean 属性。
关于XmlRootElement:
其作用是将类或枚举类型映射到 XML 元素。
看类的定义:
首先使用了@XmlRootElement和@XmlAccessorType两个注解。然后说明,Health类实现了Serializable接口,即可序列化。
类的第一个字段是常见的serialVersionUID(序列化版本号)。此外,最后是三个布尔变量,分别是inited、installed和dbOk,对应判断是否已初始化、已安装、数据库是否正常。这里就已经可以看出,需要对系统的状况做一些判断,为之后数据的传输做准备。而第二个字段,是一个static final变量INSTANCE,它的类型也是Health,这中定义有点像链表的定义,但它是一个静态变量,意味着所有的Health对象都共享这一个实例。
再往下看:
首先看到的是构造器。在构造器中,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是信息的意思,所以在info.java中应该是对信息相关的一些操作。看其引入的内容:
引入的内容都是见过的,包括Serializable、中间的三个以及最后util模块下的Version类。
直接看类的定义:
Info类也实现了Serializable接口,也是可序列化的。在其中的字段中,保存了包括serialVersionUID,以及三个String类型变量,分别是version、revision、buildDate,意思是版本、修改、创建日期,用来保存系统的版本信息、更新信息和创建的日期。而这些都是final变量,因此是不可修改的,所以Info类只有getters,没有setters。
至此,Info类分析完毕,保存了系统的一系列信息。源码已经全在图里,所以不再给出。
SearchResult是搜索的结果。这部分的内容也不难,看源码:
源码只引入了一个Collection类。类还是一个模板定义,用T类型决定字段中Collection类对象的元素类型。
在类体内,定义了四个字段,全都是private的,分别是String objectName、Long records、Collection
最后的方法都是getters和setters,没有什么好说的。至此,SearchResult.java分析结束。源码在图中,也不再附上。
ServiceResult是服务的结果,应该是在系统进行某个操作结束后作出的一些结果。
看其引入的内容:
先引入了Serializable接口,中间的部分同样也是annotation包里的相关的注解,最后是util模块下的异常类OmException。
看类的定义:
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目录定义了功能启动前的准备、服务过程中的一些结果,为数据传输做准备。
接下来我们看user子目录,其结构如下:
一共有5个java文件。
UserDTO.java是用户信息的数据传输对象。看其引入的内容:
首先引入的是db模块下util目录下DtoHelper类下面的三个方法,用来确定形参的对象是否含有某个属性,并且进一步进行一些判断。接下来引入的是Serializable、ArrayList、HashSet、List、Set,都是经常见到的了。再下面是annotation包下面的XmlRootElement注解。后面引入的是db模块下dao目录的UserDao类,以及entity目录下的一些内容。最后引入的是JSONObject。
看类的定义:
UserDTO实现了Serializable接口。类的字段中,除了serialVersionUID,就是诸如id、login、password、firstname、lastname等,这就代表了用户的一系列信息。
再下面:
这里是UserDTO类的构造器。除了默认的空构造器,还有根据User对象初始化UserDTO对象的构造器,即直接获取User对象的各个字段值,用它来初始化UserDTO。
继续往下看:
下面是一个get方法,返回值类型是User,传入的形参是UserDao userDao。新建一个User u,如果id为空,则new一个User对象赋值给u,否则根据userDao的内容根据this.id获取User对象赋值给u。接下来,将u的各项信息赋值为当前UserDTO对象的对应信息。总的来看,get方法是通过UserDTO类初始化一个User对象,并且返回。
接下来是list方法,传入的参数是List
接下来的部分就只是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的意思应该是群组的数据传输对象。看其引入的内容:
引入的内容包括Serializable、ArrayList、List、XmlRootElement类,还有db模块下dao目录下的GroupDao类和entity目录下的Group类,都是见过的。
看类的定义:
首先,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;
}
}
分析了user目录下的以上两个文件,发现所有java文件都具有相似性。所以,user目录其他的3个java文件就不再继续分析了,只需认清其基本含义即可。
再进一步分析发现,在dto目录下的类,都是以数据传输为目的,通过定义一系列可以与entity目录下的各个角色相对应的数据传输类,完成数据的封装,实现数据在数据库和网络之间的传输。这个观点在详细查看各个类的源码后得以验证,因此dto目录可以认为已经分析结束。
在本文中,结束了db模块下dao目录的分析,又完成了manager目录和dto目录的分析,这样就结束了整个db模块的分析。在db模块中,java源码完成了java对象和数据库实体之间的映射,也完成了数据库中数据的调用与传输封装。整个模块的源代码量非常大,遇到的新的知识也非常多。经过对这个模块的分析,我也学习到了许多。
完成了db模块的分析后,就要展开core模块的分析了。在core模块中,我将仍然采用只分析重难点、新颖点的分析方法,忽略重复性分析,加快分析速度,保证能够在最后日期之前结束分析。