├── .gitignore ├── README.md ├── pom.xml ├── sql └── easty_im_v1.sql └── src ├── main ├── java │ └── me │ │ └── xiezefan │ │ └── easyim │ │ └── server │ │ ├── common │ │ ├── JPushHelper.java │ │ └── ServiceException.java │ │ ├── dao │ │ ├── FriendshipDao.java │ │ ├── MessageDao.java │ │ ├── OfflineMessageDao.java │ │ └── UserDao.java │ │ ├── filter │ │ └── ClientAuthorizationFilter.java │ │ ├── model │ │ ├── Friendship.java │ │ ├── Message.java │ │ ├── MessageStatus.java │ │ ├── OfflineMessage.java │ │ └── User.java │ │ ├── resource │ │ ├── FriendshipResource.java │ │ ├── MessageResource.java │ │ ├── UploadTokenResource.java │ │ ├── UserResource.java │ │ ├── form │ │ │ ├── FriendshipAddForm.java │ │ │ ├── LoginForm.java │ │ │ ├── MessageSendForm.java │ │ │ ├── MessageStatusUpdateForm.java │ │ │ ├── RegisterFrom.java │ │ │ └── UserUpdateForm.java │ │ └── vo │ │ │ ├── MessageVo.java │ │ │ ├── ResponseBuilder.java │ │ │ └── UserVo.java │ │ ├── service │ │ ├── FriendshipService.java │ │ ├── MessageService.java │ │ ├── UpdateTokenService.java │ │ └── UserService.java │ │ ├── util │ │ ├── FileUtil.java │ │ ├── JsonUtil.java │ │ └── StringUtil.java │ │ └── web │ │ └── Application.java ├── resources │ ├── applicationContext.xml │ ├── log4j.properties │ ├── mapper │ │ ├── FriendshipDao.xml │ │ ├── MessageDao.xml │ │ ├── OfflineMessageDao.xml │ │ └── UserDao.xml │ └── mybatis-configuration.xml └── webapp │ ├── WEB-INF │ └── web.xml │ ├── index.html │ └── index.jsp └── test └── java └── me └── xiezefan └── easyim └── server ├── Main.java ├── common └── Contact.java └── dao ├── FriendshipDaoTest.java ├── MessageDaoTest.java ├── OfflineMessageDaoTest.java └── UserDaoTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | .idea 15 | *.iml 16 | target 17 | logs -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #EasyIM-Server 2 | 3 | EasyIM是一个移动即时通讯应用。是我的本科毕业设计。 4 | 5 | 因为实习占用了大四的大部分时间,导致EasyIM只完成了部分功能便参与答辩。虽然最终侥幸过了毕设答辩,但效果与自己期望的相去甚远。 6 | 7 | 开始工作后,有比较多的空闲时间,我打算慢慢完善该项目,并将近期所学习的一些新技术应用到该项目中。 8 | 9 | 10 | ## 简述 11 | 12 | 该项目分为两部分: 13 | 14 | * [EasyIM-Server][1] : EasyIM服务端 15 | * [EasyIM-Android][2] : EasyIM Android端 16 | 17 | EasyIM-Server主要完成一下功能: 18 | 19 | * 用户基础功能 20 | * 好友功能 21 | * 点对点的消息发送功能 22 | * 离线消息功能 23 | 24 | ### 目录结构 25 | 26 | ``` 27 | . 28 | ├── README.md 29 | ├── pom.xml 30 | ├── sql 数据库文件 31 | └── src 32 |    ├── main/java/me/xiezefan/easyim/server 33 |    │   │   ├── common --- 业务公共类 34 |    │   │   ├── dao ------ 数据持久化层 35 |    │   │   ├── filter --- 权限过滤 36 |    │   │   ├── model ---- 实体类 37 |    │   │   ├── resource - Restful API层 38 |    │   │   ├── service -- 逻辑业务层 39 |    │   │   ├── util ----- 工具类 40 |    │   │   └── web ------ Web相关 41 |    │   ├── resources 42 |    │   │   ├── applicationContext.xml 43 |    │   │   ├── log4j.properties 44 |    │   │   ├── mapper --- MyBatis映射文件 45 |    │   │   └── mybatis-configuration.xml 46 |    │   └── webapp/WEB-INF 47 |    └── test 48 | 49 | ``` 50 | 51 | ### 快速运行 52 | 53 | 前置条件: 54 | 55 | * 安装Mysql 56 | * 安装Maven 57 | 58 | 运行步骤: 59 | 60 | 1. 创建数据库`easyim`,并导入`sql/easy_im_v1.sql` 61 | 2. 修改`src/main/resources/applicationContext.xml`中mysql的配置 62 | 3. 在`EasyIM-Server`根目录执行`maven jetty:run` 63 | 4. 使用Post请求`localhost:8080/users/register`确定服务是否正常启动 64 | 65 | 66 | ### 框架与技术 67 | 68 | EasyIM Server 主要为EasyIM客户端提供Restful API。 主要使用了以下框架及第三方服务: 69 | 70 | * Jersey 主要提供Restful支持 71 | * Jetty Server运行的容器(亦支持Tomcat) 72 | * Spring 提供依赖注入 73 | * MyBatis 数据库映射框架 74 | * MySQL 75 | * RabbitMQ 主要做消息发送队列用(暂未实行) 76 | * 七牛云 用户发送的图片,语言存储服务 77 | * JPush 提供最核心的消息推送支持 78 | 79 | ### API 80 | 81 | #### Authoirzation 82 | 83 | EasyIM使用Basic认证, 除了用户登录,注册接口外,其余接口都需要将用户名`username`,密码`password`依照以下规制生成`authcode`,在每次API请求时,附带在`headers`中的`Authorization`中。 84 | 85 | ``` 86 | authcode = "Basic " + Base64(username:md5(password)) 87 | ``` 88 | (一种更合理的设计应该是,第一次鉴权后,生成一个有一定时限的`access_token`来作为`authcode`) 89 | 90 | #### User 用户接口 91 | 92 | **POST ~/users/login** 用户登录 93 | **POST ~/users/register** 用户注册 94 | **GET ~/users** 获取用户列表 95 | **GET ~/users/search** 用户搜索 96 | **GET ~/users/{user_id}** 获取指定用户的信息 97 | **PUT ~/users/self** 更新个人信息 98 | 99 | #### Friendship 好友接口 100 | 101 | **POST ~/friends** 添加好友关系 102 | **DELETE ~/friends/{friend_id}** 删除指定好友关系 103 | **GET ~/friends** 获取当前用户的好友列表 104 | 105 | #### Message 消息发送接口 106 | 107 | **POST /mesasges/send** 发送消息(加好友,文本,图文) 108 | **GET /messages/offline** 获取离线消息 109 | **PUT /messages/status** 批量更新消息状态(主要为标记离线/未读消息) 110 | **PUT /messages/status/{mid}** 更新指定消息状态 111 | 112 | 113 | 114 | [1]:https://github.com/xiezefan/EasyIM-Server 115 | [2]:https://github.com/xiezefan/EasyIM-Android -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | me.xiezefan.easyim.server 8 | EasyIM-Server 9 | v1 10 | war 11 | 12 | 13 | 4.2.5.RELEASE 14 | 2.22.2 15 | 9.2.10.v20150310 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 2.0.2 25 | 26 | 1.8 27 | 1.8 28 | 29 | 30 | 31 | 32 | org.eclipse.jetty 33 | jetty-maven-plugin 34 | 9.3.9.M1 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.eclipse.jetty 49 | jetty-servlet 50 | ${jetty.version} 51 | 52 | 53 | org.eclipse.jetty 54 | jetty-servlets 55 | ${jetty.version} 56 | 57 | 58 | 59 | 60 | org.slf4j 61 | slf4j-log4j12 62 | 1.7.5 63 | 64 | 65 | org.slf4j 66 | slf4j-api 67 | 1.7.5 68 | 69 | 70 | 71 | 72 | cn.jpush.api 73 | jpush-client 74 | 3.2.3 75 | 76 | 77 | 78 | 79 | com.google.code.gson 80 | gson 81 | 2.2.4 82 | 83 | 84 | 85 | 86 | javax.servlet 87 | javax.servlet-api 88 | 3.0.1 89 | provided 90 | 91 | 92 | 93 | 94 | org.glassfish.jersey.containers 95 | jersey-container-servlet-core 96 | ${jersey.version} 97 | 98 | 99 | 100 | 101 | org.glassfish.jersey.core 102 | jersey-client 103 | ${jersey.version} 104 | 105 | 106 | org.glassfish.jersey.core 107 | jersey-server 108 | ${jersey.version} 109 | 110 | 111 | 112 | org.glassfish.jersey.bundles 113 | jaxrs-ri 114 | ${jersey.version} 115 | 116 | 117 | 118 | 119 | org.glassfish.jersey.media 120 | jersey-media-multipart 121 | ${jersey.version} 122 | 123 | 124 | org.glassfish.jersey.media 125 | jersey-media-json-jackson 126 | ${jersey.version} 127 | 128 | 129 | 130 | org.glassfish.jersey.ext 131 | jersey-spring3 132 | ${jersey.version} 133 | 134 | 135 | 136 | 137 | 138 | 139 | org.springframework 140 | spring-core 141 | ${spring.version} 142 | 143 | 144 | org.springframework 145 | spring-context 146 | ${spring.version} 147 | 148 | 149 | org.springframework 150 | spring-jdbc 151 | ${spring.version} 152 | 153 | 154 | org.springframework 155 | spring-beans 156 | ${spring.version} 157 | 158 | 159 | 160 | 161 | 162 | org.mybatis 163 | mybatis-spring 164 | 1.2.1 165 | 166 | 167 | org.mybatis 168 | mybatis 169 | 3.2.6 170 | 171 | 172 | 173 | 174 | mysql 175 | mysql-connector-java 176 | 5.1.35 177 | 178 | 179 | 180 | 181 | 182 | com.rabbitmq 183 | amqp-client 184 | 3.4.3 185 | 186 | 187 | commons-lang 188 | commons-lang 189 | 2.6 190 | 191 | 192 | 193 | 194 | com.qiniu 195 | qiniu-java-sdk 196 | [7.0.0, 7.0.99] 197 | 198 | 199 | 200 | 201 | junit 202 | junit 203 | 4.11 204 | test 205 | 206 | 207 | org.springframework 208 | spring-test 209 | ${spring.version} 210 | test 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /sql/easty_im_v1.sql: -------------------------------------------------------------------------------- 1 | 2 | use easyim; 3 | 4 | drop table if exists tb_user; 5 | drop table if exists tb_friendship; 6 | drop table if exists tb_message; 7 | drop table if exists tb_offline_message; 8 | 9 | drop index if exists idx_uid_status_on_offline_message; 10 | 11 | create table tb_user 12 | ( 13 | id varchar(40) primary key, 14 | username varchar(50) not null, 15 | password varchar(256) not null, 16 | nickname varchar(50), 17 | avatar varchar (200), 18 | description varchar(500), 19 | location varchar(500), 20 | sex varchar(10), 21 | device_id varchar(40), 22 | create_time datetime 23 | ); 24 | 25 | 26 | create table tb_friendship 27 | ( 28 | id varchar(40) primary key , 29 | user_id varchar(40) not null, 30 | friend_id varchar(40) not null 31 | ); 32 | 33 | create table tb_message 34 | ( 35 | id varchar(40) primary key , 36 | from_id varchar(40) not null, 37 | to_id varchar(40) not null, 38 | type varchar(40) not null, 39 | content varchar(2000) not null, 40 | create_time datetime not null 41 | ); 42 | 43 | create table tb_offline_message 44 | ( 45 | id varchar(40) primary key, 46 | user_id varchar(40) not null, 47 | message_id varchar(40) not null, 48 | status varchar(20) not null, 49 | create_time datetime not null 50 | ); 51 | 52 | create index idx_uid_status_on_offline_message on tb_offline_message(user_id, status); 53 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/common/JPushHelper.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.common; 2 | 3 | import cn.jpush.api.JPushClient; 4 | import cn.jpush.api.push.model.Message; 5 | import cn.jpush.api.push.model.Platform; 6 | import cn.jpush.api.push.model.PushPayload; 7 | import cn.jpush.api.push.model.audience.Audience; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * Message Push Common Helper 13 | * Created by xiezefan-pc on 2015/4/7 0007. 14 | */ 15 | public class JPushHelper { 16 | 17 | private static JPushClient client = new JPushClient("4cf558267989ca0f526cb16d", "b732f0d3e5d71f6fd741f495"); 18 | 19 | 20 | public static void sendMsg(String targetAlias, String targetId, me.xiezefan.easyim.server.model.Message msg) { 21 | 22 | Message.Builder msgBuilder = Message.newBuilder() 23 | .setMsgContent(msg.getId()) 24 | .setTitle(targetId) 25 | .setContentType(msg.getType()); 26 | 27 | Map extras = msg.getContent(); 28 | for (String key : extras.keySet()) { 29 | Object value = extras.get(key); 30 | if (value instanceof String) { 31 | msgBuilder.addExtra(key, (String) value); 32 | } else if (value instanceof Number) { 33 | msgBuilder.addExtra(key, (Number) value); 34 | } else if (value instanceof Boolean) { 35 | msgBuilder.addExtra(key, (Boolean) value); 36 | } 37 | } 38 | 39 | 40 | PushPayload payload = PushPayload.newBuilder() 41 | .setPlatform(Platform.all()) 42 | .setAudience(Audience.alias(targetAlias)) 43 | .setMessage(msgBuilder.build()) 44 | .build(); 45 | 46 | try { 47 | client.sendPush(payload); 48 | } catch (Exception e) { 49 | // TODO retry 50 | e.printStackTrace(); 51 | } 52 | 53 | 54 | } 55 | 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/common/ServiceException.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.common; 2 | 3 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 4 | 5 | /** 6 | * Service 层统一异常类 7 | * Created by xiezefan-pc on 2015/3/31 0031. 8 | */ 9 | public class ServiceException extends Exception { 10 | private boolean logException; 11 | private ResponseBuilder responseBuilder; 12 | 13 | public ServiceException(ResponseBuilder responseBuilder) { 14 | super(responseBuilder.getMessage()); 15 | this.logException = false; 16 | this.responseBuilder = responseBuilder; 17 | } 18 | 19 | public ServiceException(ResponseBuilder responseBuilder, boolean logException) { 20 | super(responseBuilder.getMessage()); 21 | this.logException = logException; 22 | this.responseBuilder = responseBuilder; 23 | } 24 | 25 | public boolean isLogException() { 26 | return logException; 27 | } 28 | 29 | public void setLogException(boolean logException) { 30 | this.logException = logException; 31 | } 32 | 33 | public ResponseBuilder getResponseBuilder() { 34 | return responseBuilder; 35 | } 36 | 37 | public void setResponseBuilder(ResponseBuilder responseBuilder) { 38 | this.responseBuilder = responseBuilder; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/dao/FriendshipDao.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import me.xiezefan.easyim.server.model.Friendship; 4 | import org.apache.ibatis.annotations.Delete; 5 | import org.apache.ibatis.annotations.Insert; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Friend Ship Dao 13 | * Created by xiezefan-pc on 2015/4/1 0001. 14 | */ 15 | public interface FriendshipDao { 16 | @Insert("insert into tb_friendship(id, user_id, friend_id) values(#{id}, #{userId}, #{friend.id})") 17 | public void insert(Friendship friendship); 18 | 19 | 20 | @Delete("delete from tb_friendship where (user_id=#{user_id} and friend_id=#{friend_id}) or (user_id=#{friend_id} and friend_id=#{user_id})") 21 | public void deleteBoth(@Param("user_id")String userId, @Param("friend_id")String friendId); 22 | 23 | public List findByUserId(@Param("user_id")String userId); 24 | 25 | public Friendship findById(@Param("id")String id); 26 | 27 | @Select("select count(*) from tb_friendship where user_id=#{user_id} and friend_id=#{friend_id}") 28 | public Long validateExist(@Param("user_id")String userId, @Param("friend_id")String friendId); 29 | 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/dao/MessageDao.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import me.xiezefan.easyim.server.model.Message; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.ResultMap; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | /** 9 | * Message Dao 10 | * Created by xiezefan-pc on 2015/4/9 0009. 11 | */ 12 | public interface MessageDao { 13 | @Insert("insert into tb_message(id, from_id, to_id, type, content, create_time) values(#{id}, #{fromId}, #{toId}, #{type}, #{contentStr}, #{createTime})") 14 | public void save(Message message); 15 | 16 | @Select("select * from tb_message where id=#{id}") 17 | @ResultMap("MessageResultMap") 18 | public Message findById(String id); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/dao/OfflineMessageDao.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import me.xiezefan.easyim.server.model.OfflineMessage; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Update; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Offline Message Dao 11 | * Created by xiezefan-pc on 2015/4/9 0009. 12 | */ 13 | public interface OfflineMessageDao { 14 | @Insert("insert into tb_offline_message(id, user_id, message_id, status, create_time) values(#{id}, #{userId}, #{message.id}, #{status}, #{createTime})") 15 | public void save(OfflineMessage message); 16 | 17 | @Update("update tb_offline_message set status=#{status} where id=#{id}") 18 | public void updateStatus(OfflineMessage message); 19 | 20 | public OfflineMessage findById(String id); 21 | 22 | public List findOffline(String userId); 23 | 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import me.xiezefan.easyim.server.model.User; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.ResultMap; 7 | import org.apache.ibatis.annotations.Select; 8 | import org.apache.ibatis.annotations.Update; 9 | 10 | import javax.annotation.Resource; 11 | import java.util.List; 12 | 13 | /** 14 | * User Dao 15 | * Created by xiezefan-pc on 2015/3/29 0029. 16 | */ 17 | public interface UserDao { 18 | @Insert("insert into tb_user(id, username, password, nickname, avatar, device_id, create_time) values(#{id}, #{username}, #{password}, #{nickname}, #{avatar}, #{deviceId}, #{createTime})") 19 | public void insert(User user); 20 | 21 | @Update("update tb_user set nickname=#{nickname}, sex=#{sex}, avatar=#{avatar}, description=#{description}, location=#{location} where id=#{id}") 22 | public void update(User user); 23 | 24 | @Select("select * from tb_user where id=#{id}") 25 | @ResultMap("UserResultMap") 26 | public User findById(String id); 27 | 28 | @Select("select * from tb_user where username=#{username}") 29 | @ResultMap("UserResultMap") 30 | public User findByUsername(String username); 31 | 32 | @Update("update tb_user set device_id=#{user.deviceId} where id=#{user.id}") 33 | public void updateDeviceId(@Param("user")User user); 34 | 35 | @Select("select device_id from tb_user where id=#{id}") 36 | public String findDeviceByUserId(String id); 37 | 38 | @Select("select * from tb_user where id != #{user_id} and (username like #{query_text} or nickname like #{query_text}) order by create_time limit 0, 15") 39 | @ResultMap("UserResultMap") 40 | public List search(@Param("user_id")String userId, @Param("query_text")String queryText); 41 | 42 | @Select("select * from tb_user order by create_time limit #{start}, #{row}") 43 | @ResultMap("UserResultMap") 44 | public List list(@Param("start")int start, @Param("row")int row); 45 | 46 | @Select("select * from tb_user where id != #{user_id} order by create_time limit #{start}, #{row}") 47 | @ResultMap("UserResultMap") 48 | public List listExcludeUserId(@Param("user_id")String userId, @Param("start")int start, @Param("row")int row); 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/filter/ClientAuthorizationFilter.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.filter; 2 | 3 | 4 | import me.xiezefan.easyim.server.dao.UserDao; 5 | import me.xiezefan.easyim.server.model.User; 6 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 7 | import me.xiezefan.easyim.server.util.StringUtil; 8 | import org.glassfish.jersey.internal.util.Base64; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | 11 | import javax.annotation.Resource; 12 | import javax.ws.rs.container.ContainerRequestContext; 13 | import javax.ws.rs.container.ContainerRequestFilter; 14 | import javax.ws.rs.core.Response; 15 | import javax.ws.rs.ext.Provider; 16 | import java.io.IOException; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.regex.Pattern; 20 | 21 | /** 22 | * Client Authorization Filter 23 | * Created by xiezefan-pc on 2015/4/2 0002. 24 | */ 25 | @Provider 26 | public class ClientAuthorizationFilter implements ContainerRequestFilter { 27 | public static final List noFilterPattern; 28 | 29 | static { 30 | noFilterPattern = new ArrayList(); 31 | noFilterPattern.add(Pattern.compile("^(users/login)")); 32 | noFilterPattern.add(Pattern.compile("^(users/register)")); 33 | } 34 | 35 | @Autowired 36 | private UserDao userDao; 37 | 38 | @Override 39 | public void filter(ContainerRequestContext containerRequestContext) throws IOException { 40 | String path = containerRequestContext.getUriInfo().getPath(); 41 | for (Pattern pattern : noFilterPattern) { 42 | if (pattern.matcher(path).find()) { 43 | return; 44 | } 45 | } 46 | 47 | String authCode = containerRequestContext.getHeaders().getFirst("Authorization"); 48 | if (StringUtil.isEmpty(authCode)) { 49 | authFail(containerRequestContext); 50 | return; 51 | } 52 | 53 | String[] tempArray = authCode.split(" "); 54 | if (tempArray.length != 2) { 55 | authFail(containerRequestContext); 56 | return; 57 | } 58 | 59 | authCode = new String(Base64.decode(tempArray[1].getBytes())); 60 | tempArray = authCode.split(":"); 61 | if (tempArray.length != 2) { 62 | authFail(containerRequestContext); 63 | return; 64 | } 65 | 66 | 67 | User user = userDao.findByUsername(tempArray[0]); 68 | if (user == null || !user.getPassword().equals(tempArray[1])) { 69 | authFail(containerRequestContext); 70 | return; 71 | } 72 | 73 | containerRequestContext.getHeaders().add("User", user.getId()); 74 | } 75 | 76 | private void authFail(ContainerRequestContext containerRequestContext) { 77 | 78 | containerRequestContext.abortWith(Response 79 | .status(Response.Status.UNAUTHORIZED) 80 | .entity(ResponseBuilder.ERROR_AUTHORIZATION_FAIL) 81 | .build()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/model/Friendship.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.model; 2 | 3 | /** 4 | * Created by xiezefan-pc on 2015/4/1 0001. 5 | */ 6 | public class Friendship { 7 | private String id; 8 | private String userId; 9 | private User friend; 10 | 11 | public String getId() { 12 | return id; 13 | } 14 | 15 | public void setId(String id) { 16 | this.id = id; 17 | } 18 | 19 | public String getUserId() { 20 | return userId; 21 | } 22 | 23 | public void setUserId(String userId) { 24 | this.userId = userId; 25 | } 26 | 27 | public User getFriend() { 28 | return friend; 29 | } 30 | 31 | public void setFriend(User friend) { 32 | this.friend = friend; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/model/Message.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.model; 2 | 3 | import me.xiezefan.easyim.server.util.JsonUtil; 4 | 5 | import java.util.Date; 6 | import java.util.Map; 7 | 8 | /** 9 | * 消息对象 10 | * id 的构建方法为, s_ 代表单推消息, g_代表群推消息 11 | * content 字段为消息的Json字符串 12 | * Created by xiezefan-pc on 2015/4/9 0009. 13 | */ 14 | public class Message { 15 | private String id; 16 | private String fromId; 17 | private String toId; 18 | private String type; 19 | private String contentStr; 20 | private Map content; 21 | private Date createTime; 22 | 23 | public String getId() { 24 | return id; 25 | } 26 | 27 | public void setId(String id) { 28 | this.id = id; 29 | } 30 | 31 | public String getFromId() { 32 | return fromId; 33 | } 34 | 35 | public void setFromId(String fromId) { 36 | this.fromId = fromId; 37 | } 38 | 39 | public String getToId() { 40 | return toId; 41 | } 42 | 43 | public void setToId(String toId) { 44 | this.toId = toId; 45 | } 46 | 47 | public String getType() { 48 | return type; 49 | } 50 | 51 | public void setType(String type) { 52 | this.type = type; 53 | } 54 | 55 | 56 | public Date getCreateTime() { 57 | return createTime; 58 | } 59 | 60 | public void setCreateTime(Date createTime) { 61 | this.createTime = createTime; 62 | } 63 | 64 | public Map getContent() { 65 | return content; 66 | } 67 | 68 | public void setContent(Map content) { 69 | this.content = content; 70 | this.contentStr = JsonUtil.toJson(content); 71 | } 72 | 73 | public String getContentStr() { 74 | return contentStr; 75 | } 76 | 77 | public void setContentStr(String contentStr) { 78 | this.content = JsonUtil.formatToMap(contentStr); 79 | this.contentStr = contentStr; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/model/MessageStatus.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.model; 2 | 3 | /** 4 | * Message Receiver Status 5 | * Created by xiezefan-pc on 2015/4/9 0009. 6 | */ 7 | public enum MessageStatus { 8 | SEND, RECEIVER, READ; 9 | 10 | public static MessageStatus format(String name) { 11 | if ("SEND".equals(name)) { 12 | return SEND; 13 | } else if ("RECEIVER".equals(name)) { 14 | return RECEIVER; 15 | } else if ("READ".equals(name)) { 16 | return READ; 17 | } else { 18 | return null; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/model/OfflineMessage.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.model; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 离线消息对象 7 | * 此对象采用MySQL开发并不是非常理想的实现, 比较合适的做法是使用如Redis 8 | * 等内存,缓存数据库, 可以方便实现快速查找与定时过期的功能 9 | * 当status==READ表示此数据可以被删除了 10 | * Created by xiezefan-pc on 2015/4/9 0009. 11 | */ 12 | public class OfflineMessage { 13 | private String id; 14 | private String userId; 15 | private Message message; 16 | private MessageStatus status; 17 | private Date createTime; 18 | 19 | public String getId() { 20 | return id; 21 | } 22 | 23 | public void setId(String id) { 24 | this.id = id; 25 | } 26 | 27 | public String getUserId() { 28 | return userId; 29 | } 30 | 31 | public void setUserId(String userId) { 32 | this.userId = userId; 33 | } 34 | 35 | public Message getMessage() { 36 | return message; 37 | } 38 | 39 | public void setMessage(Message message) { 40 | this.message = message; 41 | } 42 | 43 | public MessageStatus getStatus() { 44 | return status; 45 | } 46 | 47 | public void setStatus(MessageStatus status) { 48 | this.status = status; 49 | } 50 | 51 | public Date getCreateTime() { 52 | return createTime; 53 | } 54 | 55 | public void setCreateTime(Date createTime) { 56 | this.createTime = createTime; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/model/User.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.model; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * User Model 7 | * Created by xiezefan-pc on 2015/3/29 0029. 8 | */ 9 | public class User { 10 | private String id; 11 | private String username; 12 | private String password; 13 | private String nickname; 14 | private String avatar; 15 | private String description; 16 | private String location; 17 | private String sex; 18 | 19 | private String deviceId; 20 | private Date createTime; 21 | 22 | public String getId() { 23 | return id; 24 | } 25 | 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | 30 | public String getUsername() { 31 | return username; 32 | } 33 | 34 | public void setUsername(String username) { 35 | this.username = username; 36 | } 37 | 38 | public String getPassword() { 39 | return password; 40 | } 41 | 42 | public void setPassword(String password) { 43 | this.password = password; 44 | } 45 | 46 | public String getNickname() { 47 | return nickname; 48 | } 49 | 50 | public void setNickname(String nickname) { 51 | this.nickname = nickname; 52 | } 53 | 54 | public String getDeviceId() { 55 | return deviceId; 56 | } 57 | 58 | public void setDeviceId(String deviceId) { 59 | this.deviceId = deviceId; 60 | } 61 | 62 | public Date getCreateTime() { 63 | return createTime; 64 | } 65 | 66 | public void setCreateTime(Date createTime) { 67 | this.createTime = createTime; 68 | } 69 | 70 | public String getAvatar() { 71 | return avatar; 72 | } 73 | 74 | public void setAvatar(String avatar) { 75 | this.avatar = avatar; 76 | } 77 | 78 | public String getDescription() { 79 | return description; 80 | } 81 | 82 | public void setDescription(String description) { 83 | this.description = description; 84 | } 85 | 86 | public String getLocation() { 87 | return location; 88 | } 89 | 90 | public void setLocation(String location) { 91 | this.location = location; 92 | } 93 | 94 | public String getSex() { 95 | return sex; 96 | } 97 | 98 | public void setSex(String sex) { 99 | this.sex = sex; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/FriendshipResource.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource; 2 | 3 | import me.xiezefan.easyim.server.common.ServiceException; 4 | import me.xiezefan.easyim.server.resource.form.FriendshipAddForm; 5 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 6 | import me.xiezefan.easyim.server.resource.vo.UserVo; 7 | import me.xiezefan.easyim.server.service.FriendshipService; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | 12 | 13 | import javax.ws.rs.Consumes; 14 | import javax.ws.rs.DELETE; 15 | import javax.ws.rs.GET; 16 | import javax.ws.rs.POST; 17 | import javax.ws.rs.Path; 18 | import javax.ws.rs.PathParam; 19 | import javax.ws.rs.Produces; 20 | import javax.ws.rs.core.Context; 21 | import javax.ws.rs.core.HttpHeaders; 22 | import javax.ws.rs.core.Response; 23 | import java.util.List; 24 | 25 | /** 26 | * User Friendship Resource 27 | * Created by xiezefan-pc on 2015/4/4 0004. 28 | */ 29 | @Path("/friends") 30 | public class FriendshipResource { 31 | private static final Logger LOG = LoggerFactory.getLogger(FriendshipResource.class); 32 | 33 | @Autowired 34 | private FriendshipService friendshipService; 35 | 36 | @POST 37 | @Consumes("application/json") 38 | @Produces("application/json") 39 | public Response save(FriendshipAddForm dataForm, @Context HttpHeaders headers) { 40 | try { 41 | friendshipService.save(dataForm, headers.getHeaderString("User")); 42 | return ResponseBuilder.SUCCESS.build(); 43 | } catch (IllegalArgumentException e) { 44 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 45 | } catch (ServiceException e) { 46 | if (e.isLogException()) { 47 | LOG.error("Business Error", e); 48 | } 49 | return e.getResponseBuilder().build(); 50 | } catch (Exception e) { 51 | LOG.error("Unknown Error", e); 52 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 53 | } 54 | } 55 | 56 | @DELETE 57 | @Path("/{friend_id}") 58 | @Produces("application/json") 59 | public Response delete(@PathParam("friend_id")String friend_id, @Context HttpHeaders headers) { 60 | try { 61 | friendshipService.delete(headers.getHeaderString("User"), friend_id); 62 | return ResponseBuilder.SUCCESS.build(); 63 | } catch (IllegalArgumentException e) { 64 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 65 | } catch (Exception e) { 66 | LOG.error("Unknown Error", e); 67 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 68 | } 69 | } 70 | 71 | @GET 72 | @Produces("application/json") 73 | public Response list(@Context HttpHeaders headers) { 74 | try { 75 | List friends = friendshipService.findByUserId(headers.getHeaderString("User")); 76 | return new ResponseBuilder(friends).build(); 77 | } catch (IllegalArgumentException e) { 78 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 79 | } catch (Exception e) { 80 | LOG.error("Unknown Error", e); 81 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 82 | } 83 | } 84 | 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/MessageResource.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource; 2 | 3 | import me.xiezefan.easyim.server.common.ServiceException; 4 | import me.xiezefan.easyim.server.resource.form.MessageSendForm; 5 | import me.xiezefan.easyim.server.resource.form.MessageStatusUpdateForm; 6 | import me.xiezefan.easyim.server.resource.vo.MessageVo; 7 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 8 | import me.xiezefan.easyim.server.service.MessageService; 9 | import me.xiezefan.easyim.server.util.JsonUtil; 10 | import org.apache.log4j.spi.LoggerFactory; 11 | import org.slf4j.Logger; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | 14 | import javax.ws.rs.Consumes; 15 | import javax.ws.rs.GET; 16 | import javax.ws.rs.POST; 17 | import javax.ws.rs.PUT; 18 | import javax.ws.rs.Path; 19 | import javax.ws.rs.PathParam; 20 | import javax.ws.rs.Produces; 21 | import javax.ws.rs.core.Context; 22 | import javax.ws.rs.core.HttpHeaders; 23 | import javax.ws.rs.core.Response; 24 | import java.util.List; 25 | 26 | /** 27 | * Message Dispatch Resource 28 | * Created by xiezefan-pc on 2015/4/7 0007. 29 | */ 30 | @Path("/messages") 31 | public class MessageResource { 32 | private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(MessageResource.class); 33 | 34 | @Autowired 35 | private MessageService messageService; 36 | 37 | @POST 38 | @Path("/send") 39 | @Consumes("application/json") 40 | @Produces("application/json") 41 | public Response send(MessageSendForm dataForm, @Context HttpHeaders headers) { 42 | try { 43 | MessageVo msg = messageService.send(headers.getHeaderString("User"), dataForm); 44 | return new ResponseBuilder(msg).build(); 45 | } catch (IllegalArgumentException e) { 46 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 47 | } catch (ServiceException e) { 48 | if (e.isLogException()) { 49 | LOG.error("Business Error", e); 50 | } 51 | return e.getResponseBuilder().build(); 52 | } catch (Exception e) { 53 | LOG.error("Unknown Error", e); 54 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 55 | } 56 | } 57 | 58 | 59 | @GET 60 | @Path("/offline") 61 | @Produces("application/json") 62 | public Response offline(@Context HttpHeaders headers) { 63 | try { 64 | List result = messageService.getOfflineMessage(headers.getHeaderString("User")); 65 | return new ResponseBuilder(result).build(); 66 | } catch (IllegalArgumentException e) { 67 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 68 | } catch (Exception e) { 69 | LOG.error("Unknown Error", e); 70 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 71 | } 72 | } 73 | 74 | 75 | @PUT 76 | @Path("/status") 77 | @Consumes("application/json") 78 | @Produces("application/json") 79 | public Response updateStatusBatch(MessageStatusUpdateForm[] dataForms, @Context HttpHeaders headers) { 80 | try { 81 | messageService.updateStatus(headers.getHeaderString("User"), dataForms); 82 | return ResponseBuilder.SUCCESS.build(); 83 | } catch (IllegalArgumentException e) { 84 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 85 | } catch (Exception e) { 86 | LOG.error("Unknown Error", e); 87 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 88 | } 89 | } 90 | 91 | @PUT 92 | @Path("/status/{mid}") 93 | @Consumes("application/json") 94 | @Produces("application/json") 95 | public Response updateStatus(MessageStatusUpdateForm dataForm, @PathParam("mid")String mid, @Context HttpHeaders headers) { 96 | try { 97 | messageService.updateStatus(headers.getHeaderString("User"), mid, dataForm); 98 | return ResponseBuilder.SUCCESS.build(); 99 | } catch (IllegalArgumentException e) { 100 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 101 | } catch (Exception e) { 102 | LOG.error("Unknown Error", e); 103 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 104 | } 105 | } 106 | 107 | 108 | 109 | 110 | 111 | 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/UploadTokenResource.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource; 2 | 3 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 4 | import me.xiezefan.easyim.server.service.UpdateTokenService; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import javax.ws.rs.GET; 10 | import javax.ws.rs.Path; 11 | import javax.ws.rs.Produces; 12 | import javax.ws.rs.core.Response; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | /** 17 | * 获取七牛云Upload Token的Resource 18 | * Created by xiezefan on 15/5/16. 19 | */ 20 | @Path("/tokens") 21 | public class UploadTokenResource { 22 | private static final Logger LOG = LoggerFactory.getLogger(UploadTokenResource.class); 23 | 24 | @Autowired 25 | public UpdateTokenService updateTokenService; 26 | 27 | @GET 28 | @Path("/generate") 29 | @Produces("application/json") 30 | public Response getToken() { 31 | try { 32 | String token = updateTokenService.createToken(); 33 | Map result = new HashMap<>(); 34 | result.put("token", token); 35 | return new ResponseBuilder(result).build(); 36 | } catch (IllegalArgumentException e) { 37 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 38 | } catch (Exception e) { 39 | LOG.error("Unknown Error", e); 40 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 41 | } 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/UserResource.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource; 2 | 3 | import me.xiezefan.easyim.server.common.ServiceException; 4 | import me.xiezefan.easyim.server.model.User; 5 | import me.xiezefan.easyim.server.resource.form.LoginForm; 6 | import me.xiezefan.easyim.server.resource.form.RegisterFrom; 7 | import me.xiezefan.easyim.server.resource.form.UserUpdateForm; 8 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 9 | import me.xiezefan.easyim.server.resource.vo.UserVo; 10 | import me.xiezefan.easyim.server.service.UserService; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.ws.rs.*; 17 | import javax.ws.rs.core.Context; 18 | import javax.ws.rs.core.HttpHeaders; 19 | import javax.ws.rs.core.Response; 20 | import java.util.List; 21 | 22 | 23 | /** 24 | * User Resource 25 | * Created by ZeFanXie on 15-3-26. 26 | */ 27 | @Path("/users") 28 | public class UserResource { 29 | private static final Logger LOG = LoggerFactory.getLogger(UserResource.class); 30 | 31 | @Autowired 32 | public UserService userService; 33 | 34 | @POST 35 | @Path("/login") 36 | @Consumes("application/json") 37 | @Produces("application/json") 38 | public Response login(LoginForm dataForm) { 39 | try { 40 | User user = userService.login(dataForm); 41 | return new ResponseBuilder(new UserVo(user)).build(); 42 | } catch (IllegalArgumentException e) { 43 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 44 | } catch (ServiceException e) { 45 | if (e.isLogException()) { 46 | LOG.error("Business Error", e); 47 | } 48 | return e.getResponseBuilder().build(); 49 | } catch (Exception e) { 50 | LOG.error("Unknown Error", e); 51 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 52 | } 53 | } 54 | 55 | @POST 56 | @Path("/register") 57 | @Consumes("application/json") 58 | @Produces("application/json") 59 | public Response register(RegisterFrom dataForm) { 60 | try { 61 | userService.register(dataForm); 62 | return ResponseBuilder.SUCCESS.build(); 63 | } catch (IllegalArgumentException e) { 64 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 65 | } catch (ServiceException e) { 66 | if (e.isLogException()) { 67 | LOG.error("Business Error", e); 68 | } 69 | return e.getResponseBuilder().build(); 70 | } catch (Exception e) { 71 | LOG.error("Unknown Error", e); 72 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 73 | } 74 | } 75 | 76 | @GET 77 | @Path("/") 78 | @Produces("application/json") 79 | public Response list(@QueryParam("start")int start, @QueryParam("row")int row, @Context HttpHeaders headers) { 80 | try { 81 | List list = userService.list(headers.getHeaderString("User"), start, row); 82 | return new ResponseBuilder(list).build(); 83 | } catch (IllegalArgumentException e) { 84 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 85 | } catch (Exception e) { 86 | LOG.error("Unknown Error", e); 87 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 88 | } 89 | } 90 | 91 | @GET 92 | @Path("/search") 93 | @Produces("application/json") 94 | public Response search(@QueryParam("q")String queryText, @Context HttpHeaders headers) { 95 | try { 96 | List list = userService.search(headers.getHeaderString("User"), queryText); 97 | return new ResponseBuilder(list).build(); 98 | } catch (IllegalArgumentException e) { 99 | return ResponseBuilder.ERROR_INVALID_PARAMETER.build(); 100 | } catch (Exception e) { 101 | LOG.error("Unknown Error", e); 102 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 103 | } 104 | } 105 | 106 | 107 | @GET 108 | @Path("/{user_id}") 109 | @Produces("application/json") 110 | public Response getUserInfo(@PathParam("user_id")String userId, @Context HttpHeaders headers) { 111 | try { 112 | UserVo user = userService.getUserInfo(userId); 113 | return new ResponseBuilder(user).build(); 114 | } catch (ServiceException e) { 115 | if (e.isLogException()) { 116 | LOG.error("Business Error", e); 117 | } 118 | return e.getResponseBuilder().build(); 119 | } catch (Exception e) { 120 | LOG.error("Unknown Error", e); 121 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 122 | } 123 | } 124 | 125 | @PUT 126 | @Path("/self") 127 | @Consumes("application/json") 128 | @Produces("application/json") 129 | public Response updateUser(UserUpdateForm dataForm, @Context HttpHeaders headers) { 130 | try { 131 | userService.updateUser(headers.getHeaderString("User"), dataForm); 132 | return ResponseBuilder.SUCCESS.build(); 133 | } catch (ServiceException e) { 134 | if (e.isLogException()) { 135 | LOG.error("Business Error", e); 136 | } 137 | return e.getResponseBuilder().build(); 138 | } catch (Exception e) { 139 | LOG.error("Unknown Error", e); 140 | return ResponseBuilder.ERROR_BAD_SERVER.build(); 141 | } 142 | } 143 | 144 | 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/form/FriendshipAddForm.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.form; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import me.xiezefan.easyim.server.util.StringUtil; 5 | 6 | /** 7 | * Friendship Add From 8 | * Created by xiezefan-pc on 2015/4/2 0002. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class FriendshipAddForm { 12 | public String friend_id; 13 | 14 | public boolean validate() { 15 | return !StringUtil.isEmpty(friend_id); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/form/LoginForm.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.form; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import me.xiezefan.easyim.server.util.StringUtil; 5 | 6 | /** 7 | * User Login Form 8 | * Created by xiezefan-pc on 2015/3/29 0029. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class LoginForm { 12 | public String device_id; 13 | public String username; 14 | public String password; 15 | 16 | public boolean validate() { 17 | return !StringUtil.isEmpty(username) 18 | && !StringUtil.isEmpty(password); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/form/MessageSendForm.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.form; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import me.xiezefan.easyim.server.util.StringUtil; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * Message Send Form 10 | * Created by xiezefan-pc on 2015/4/7 0007. 11 | */ 12 | @JsonIgnoreProperties(ignoreUnknown = true) 13 | public class MessageSendForm { 14 | public String to; 15 | public String type; 16 | public Map content; 17 | 18 | public boolean validate() { 19 | return !StringUtil.isEmpty(to) 20 | && !StringUtil.isEmpty(type) 21 | && content != null 22 | && content.size() > 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/form/MessageStatusUpdateForm.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.form; 2 | 3 | /** 4 | * Created by xiezefan-pc on 2015/4/11 0011. 5 | */ 6 | public class MessageStatusUpdateForm { 7 | public String id; 8 | public String status; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/form/RegisterFrom.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.form; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import me.xiezefan.easyim.server.util.StringUtil; 5 | 6 | /** 7 | * User Register Form 8 | * Created by xiezefan-pc on 2015/3/29 0029. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class RegisterFrom { 12 | public String username; 13 | public String password; 14 | 15 | public boolean validate() { 16 | return !StringUtil.isEmpty(username) && !StringUtil.isEmpty(password); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/form/UserUpdateForm.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.form; 2 | 3 | public class UserUpdateForm { 4 | public String avatar; 5 | public String nickname; 6 | public String sex; 7 | public String location; 8 | public String description; 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/vo/MessageVo.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.vo; 2 | 3 | import me.xiezefan.easyim.server.model.Message; 4 | import me.xiezefan.easyim.server.model.OfflineMessage; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by xiezefan-pc on 2015/4/11 0011. 10 | */ 11 | public class MessageVo { 12 | public String id; 13 | public String fromId; 14 | public String type; 15 | public Map content; 16 | public Long create_time; 17 | 18 | public MessageVo() { 19 | } 20 | 21 | 22 | public MessageVo(OfflineMessage msg) { 23 | this.id = msg.getId(); 24 | Message _msg = msg.getMessage(); 25 | this.fromId = _msg.getFromId(); 26 | this.type = _msg.getType(); 27 | this.content = _msg.getContent(); 28 | this.create_time = _msg.getCreateTime().getTime(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/vo/ResponseBuilder.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.vo; 2 | 3 | 4 | import javax.ws.rs.core.Response; 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | import javax.xml.transform.OutputKeys; 7 | 8 | /** 9 | * Success Vo 10 | * Created by xiezefan-pc on 2015/3/29 0029. 11 | */ 12 | @XmlRootElement 13 | public class ResponseBuilder { 14 | public static final int STATUS_OK = 200; 15 | public static final int STATUS_BAD_REQUEST = 400; 16 | public static final int STATUS_UNAUTHORIZED = 401; 17 | public static final int STATUS_FORBIDDEN = 403; 18 | public static final int STATUS_NOT_FOUND = 404; 19 | public static final int STATUS_INTERNAL_SERVER = 500; 20 | 21 | // error response 22 | public static final ResponseBuilder ERROR_BAD_SERVER = new ResponseBuilder(STATUS_INTERNAL_SERVER, 1000, "Bad Server"); 23 | public static final ResponseBuilder ERROR_AUTHORIZATION_FAIL = new ResponseBuilder(STATUS_UNAUTHORIZED, 1001, "Authorization Fail"); 24 | public static final ResponseBuilder ERROR_FORBIDDEN_FAIL = new ResponseBuilder(STATUS_FORBIDDEN, 1002, "Forbidden"); 25 | public static final ResponseBuilder ERROR_INVALID_PARAMETER = new ResponseBuilder(STATUS_BAD_REQUEST, 1003, "Invalid Parameter"); 26 | public static final ResponseBuilder ERROR_USER_EXIST = new ResponseBuilder(STATUS_BAD_REQUEST, 1004, "User Exist"); 27 | public static final ResponseBuilder ERROR_USER_NOT_FOUND = new ResponseBuilder(STATUS_BAD_REQUEST, 1005, "No Such User"); 28 | public static final ResponseBuilder ERROR_MESSAGE_NOT_FOUND = new ResponseBuilder(STATUS_BAD_REQUEST, 1006, "No Such Message"); 29 | 30 | 31 | 32 | // success response 33 | public static final ResponseBuilder SUCCESS = new ResponseBuilder(STATUS_OK, 3000, "Success"); 34 | 35 | 36 | private int status; 37 | private Object target; 38 | 39 | private int code; 40 | private String message; 41 | 42 | public ResponseBuilder() { 43 | } 44 | 45 | public ResponseBuilder(int status, int code, String message) { 46 | this.status = status; 47 | this.code = code; 48 | this.message = message; 49 | this.target = this; 50 | } 51 | 52 | public ResponseBuilder(Object target) { 53 | this.status = STATUS_OK; 54 | this.target = target; 55 | } 56 | 57 | 58 | 59 | public Response build() { 60 | return Response.status(status).entity(target).build(); 61 | } 62 | 63 | 64 | public int getCode() { 65 | return code; 66 | } 67 | 68 | public void setCode(int code) { 69 | this.code = code; 70 | } 71 | 72 | public String getMessage() { 73 | return message; 74 | } 75 | 76 | public void setMessage(String message) { 77 | this.message = message; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/resource/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.resource.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import me.xiezefan.easyim.server.model.User; 5 | 6 | /** 7 | * User View Model 8 | * Created by xiezefan-pc on 2015/4/1 0001. 9 | */ 10 | @JsonInclude(JsonInclude.Include.NON_NULL) 11 | public class UserVo { 12 | public String id; 13 | public String username; 14 | public String nickname; 15 | public String avatar; 16 | public String description; 17 | public String sex; 18 | public String location; 19 | 20 | public UserVo(User user) { 21 | this.id = user.getId(); 22 | this.username = user.getUsername(); 23 | this.nickname = user.getNickname(); 24 | this.avatar = user.getAvatar(); 25 | this.description = user.getDescription(); 26 | this.location = user.getLocation(); 27 | this.sex = user.getSex(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/service/FriendshipService.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.service; 2 | 3 | import me.xiezefan.easyim.server.common.ServiceException; 4 | import me.xiezefan.easyim.server.dao.FriendshipDao; 5 | import me.xiezefan.easyim.server.dao.UserDao; 6 | import me.xiezefan.easyim.server.model.Friendship; 7 | import me.xiezefan.easyim.server.model.User; 8 | import me.xiezefan.easyim.server.resource.form.FriendshipAddForm; 9 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 10 | import me.xiezefan.easyim.server.resource.vo.UserVo; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.UUID; 18 | 19 | /** 20 | * Friendship Service 21 | * Created by xiezefan-pc on 2015/4/1 0001. 22 | */ 23 | @Service 24 | public class FriendshipService { 25 | 26 | @Resource 27 | public FriendshipDao friendshipDao; 28 | @Resource 29 | public UserDao userDao; 30 | 31 | @Transactional 32 | public void save(FriendshipAddForm dataForm, String userId) throws ServiceException { 33 | if (!dataForm.validate()) { 34 | throw new IllegalArgumentException("Invalid Parameter"); 35 | } 36 | 37 | User user = findAndValidateUser(userId); 38 | User friend = userDao.findById(dataForm.friend_id); 39 | if (friend == null) { 40 | throw new ServiceException(ResponseBuilder.ERROR_USER_NOT_FOUND); 41 | } 42 | 43 | // validate user's friendship is exist 44 | Long count = friendshipDao.validateExist(userId, dataForm.friend_id); 45 | if (count > 0) { 46 | return; 47 | } 48 | 49 | Friendship friendship = new Friendship(); 50 | friendship.setId(UUID.randomUUID().toString()); 51 | friendship.setUserId(userId); 52 | friendship.setFriend(friend); 53 | friendshipDao.insert(friendship); 54 | 55 | // validate friend's friendship is exist 56 | count = friendshipDao.validateExist(dataForm.friend_id, userId); 57 | if (count > 0) { 58 | return; 59 | } 60 | Friendship anotherFriendship = new Friendship(); 61 | anotherFriendship.setId(UUID.randomUUID().toString()); 62 | anotherFriendship.setUserId(friend.getId()); 63 | anotherFriendship.setFriend(user); 64 | friendshipDao.insert(anotherFriendship); 65 | } 66 | 67 | public void delete(String userId, String friendId) { 68 | friendshipDao.deleteBoth(userId, friendId); 69 | } 70 | 71 | public List findByUserId(String userId) { 72 | List result = new ArrayList(); 73 | List friendshipList = friendshipDao.findByUserId(userId); 74 | for (Friendship friendship : friendshipList) { 75 | if (friendship.getFriend() == null) { 76 | continue; 77 | } 78 | result.add(new UserVo(friendship.getFriend())); 79 | } 80 | return result; 81 | } 82 | 83 | 84 | 85 | private User findAndValidateUser(String userId) throws ServiceException { 86 | User user = userDao.findById(userId); 87 | if (user == null) { 88 | throw new ServiceException(ResponseBuilder.ERROR_USER_EXIST); 89 | } 90 | return user; 91 | } 92 | 93 | 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/service/MessageService.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.service; 2 | 3 | import me.xiezefan.easyim.server.common.JPushHelper; 4 | import me.xiezefan.easyim.server.common.ServiceException; 5 | import me.xiezefan.easyim.server.dao.MessageDao; 6 | import me.xiezefan.easyim.server.dao.OfflineMessageDao; 7 | import me.xiezefan.easyim.server.dao.UserDao; 8 | import me.xiezefan.easyim.server.model.Message; 9 | import me.xiezefan.easyim.server.model.MessageStatus; 10 | import me.xiezefan.easyim.server.model.OfflineMessage; 11 | import me.xiezefan.easyim.server.model.User; 12 | import me.xiezefan.easyim.server.resource.form.MessageSendForm; 13 | import me.xiezefan.easyim.server.resource.form.MessageStatusUpdateForm; 14 | import me.xiezefan.easyim.server.resource.vo.MessageVo; 15 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 16 | import me.xiezefan.easyim.server.util.JsonUtil; 17 | import me.xiezefan.easyim.server.util.StringUtil; 18 | import org.springframework.stereotype.Service; 19 | 20 | import javax.annotation.Resource; 21 | import java.util.ArrayList; 22 | import java.util.Date; 23 | import java.util.List; 24 | import java.util.UUID; 25 | 26 | /** 27 | * Created by xiezefan-pc on 2015/4/11 0011. 28 | */ 29 | @Service 30 | public class MessageService { 31 | 32 | @Resource 33 | private UserDao userDao; 34 | @Resource 35 | private MessageDao messageDao; 36 | @Resource 37 | private OfflineMessageDao offlineMessageDao; 38 | 39 | public MessageVo send(String userId, MessageSendForm dataForm) throws ServiceException { 40 | if (!dataForm.validate()) { 41 | throw new IllegalArgumentException("Invalid Parameter"); 42 | } 43 | 44 | User user = findAndValidateUser(userId); 45 | 46 | char targetType = dataForm.to.charAt(0); 47 | 48 | Message msg = new Message(); 49 | msg.setId(UUID.randomUUID().toString()); 50 | msg.setFromId(user.getId()); 51 | msg.setToId(dataForm.to); 52 | msg.setType(dataForm.type); 53 | msg.setContent(dataForm.content); 54 | msg.setCreateTime(new Date()); 55 | messageDao.save(msg); 56 | 57 | if (targetType == 's') { 58 | return sendMsgToSingle(msg); 59 | } else if (targetType == 'g') { 60 | // un support , ignore 61 | } else { 62 | // ignore 63 | } 64 | 65 | 66 | return null; 67 | } 68 | 69 | private MessageVo sendMsgToSingle(Message msg) { 70 | String targetId = msg.getToId(); 71 | 72 | OfflineMessage offlineMsg = new OfflineMessage(); 73 | offlineMsg.setId(UUID.randomUUID().toString()); 74 | offlineMsg.setUserId(targetId); 75 | offlineMsg.setMessage(msg); 76 | offlineMsg.setStatus(MessageStatus.SEND); 77 | offlineMsg.setCreateTime(new Date()); 78 | offlineMessageDao.save(offlineMsg); 79 | JPushHelper.sendMsg(targetId, msg.getToId(), msg); 80 | return new MessageVo(offlineMsg); 81 | } 82 | 83 | 84 | public List getOfflineMessage(String userId) { 85 | List messages = offlineMessageDao.findOffline(userId); 86 | List result = new ArrayList(); 87 | for (OfflineMessage msg : messages) { 88 | result.add(new MessageVo(msg)); 89 | } 90 | return result; 91 | } 92 | 93 | public void updateStatus(String userId, MessageStatusUpdateForm... dataForms) { 94 | for (MessageStatusUpdateForm dataForm : dataForms) { 95 | OfflineMessage msg = offlineMessageDao.findById(dataForm.id); 96 | MessageStatus status = MessageStatus.format(dataForm.status); 97 | if (msg == null 98 | || status == null 99 | || !msg.getUserId().equals(userId) 100 | || msg.getStatus().ordinal() >= status.ordinal()) { 101 | continue; 102 | } 103 | msg.setStatus(status); 104 | offlineMessageDao.updateStatus(msg); 105 | } 106 | } 107 | 108 | public void updateStatus(String userId, String mid, MessageStatusUpdateForm dataForm) throws ServiceException { 109 | OfflineMessage msg = offlineMessageDao.findById(mid); 110 | MessageStatus status = MessageStatus.format(dataForm.status); 111 | if (msg == null) { 112 | throw new ServiceException(ResponseBuilder.ERROR_MESSAGE_NOT_FOUND); 113 | } 114 | if (status == null || msg.getStatus().ordinal() >= status.ordinal()) { 115 | throw new IllegalArgumentException("Invalid Parameter"); 116 | } 117 | if (!msg.getUserId().equals(userId)) { 118 | throw new ServiceException(ResponseBuilder.ERROR_FORBIDDEN_FAIL); 119 | } 120 | msg.setStatus(status); 121 | offlineMessageDao.updateStatus(msg); 122 | } 123 | 124 | 125 | 126 | private User findAndValidateUser(String userId) throws ServiceException { 127 | User user = userDao.findById(userId); 128 | if (user == null) { 129 | throw new ServiceException(ResponseBuilder.ERROR_USER_EXIST); 130 | } 131 | return user; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/service/UpdateTokenService.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.service; 2 | 3 | import com.qiniu.util.Auth; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * 七牛云 Token 生成 8 | * Created by xiezefan on 15/5/16. 9 | */ 10 | @Component 11 | public class UpdateTokenService { 12 | private static final String AK = "xKzCfC_k6hj-7QN_wBwKiSigawkqutKmh280cH8-"; 13 | private static final String SK = "wDiJw747BkWM_TuJtlr_1IQbf8RAeVYHsxr0rPGp"; 14 | private static final int DEFAULT_EXPIRES = 60 * 60 * 24 * 15; 15 | private static final String BUCKET = "easyim"; 16 | private Auth auth; 17 | 18 | public UpdateTokenService() { 19 | this.auth = Auth.create(AK, SK);; 20 | } 21 | 22 | public String createToken() { 23 | return auth.uploadToken(BUCKET, null, DEFAULT_EXPIRES, null); 24 | } 25 | 26 | public static void main(String[] args) { 27 | Auth auth2 = Auth.create(AK, SK); 28 | String url = auth2.privateDownloadUrl("http://7xj4ew.com1.z0.glb.clouddn.com/46.pic_hd.jpg"); 29 | System.out.println(url); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/service/UserService.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.service; 2 | 3 | import me.xiezefan.easyim.server.common.ServiceException; 4 | import me.xiezefan.easyim.server.dao.UserDao; 5 | import me.xiezefan.easyim.server.model.User; 6 | import me.xiezefan.easyim.server.resource.form.LoginForm; 7 | import me.xiezefan.easyim.server.resource.form.RegisterFrom; 8 | import me.xiezefan.easyim.server.resource.form.UserUpdateForm; 9 | import me.xiezefan.easyim.server.resource.vo.ResponseBuilder; 10 | import me.xiezefan.easyim.server.resource.vo.UserVo; 11 | import me.xiezefan.easyim.server.util.StringUtil; 12 | import org.springframework.stereotype.Component; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.ArrayList; 16 | import java.util.Date; 17 | import java.util.List; 18 | import java.util.UUID; 19 | 20 | /** 21 | * User Service 22 | * Created by xiezefan-pc on 2015/3/29 0029. 23 | */ 24 | @Component 25 | public class UserService { 26 | 27 | @Resource 28 | private UserDao userDao; 29 | 30 | public void register(RegisterFrom dataForm) throws ServiceException { 31 | if (!dataForm.validate()) { 32 | throw new IllegalArgumentException("Invalid Parameter"); 33 | } 34 | User user = userDao.findByUsername(dataForm.username); 35 | if (user != null) { 36 | throw new ServiceException(ResponseBuilder.ERROR_USER_EXIST); 37 | } 38 | user = new User(); 39 | user.setId("s_" + UUID.randomUUID().toString().replace("-", "0")); 40 | user.setUsername(dataForm.username); 41 | user.setPassword(dataForm.password); 42 | user.setCreateTime(new Date()); 43 | userDao.insert(user); 44 | } 45 | 46 | public User login(LoginForm dataForm) throws ServiceException { 47 | if (!dataForm.validate()) { 48 | throw new IllegalArgumentException("Invalid Parameter"); 49 | } 50 | 51 | User user = userDao.findByUsername(dataForm.username); 52 | if (user == null || !user.getPassword().equals(dataForm.password)) { 53 | throw new ServiceException(ResponseBuilder.ERROR_AUTHORIZATION_FAIL); 54 | } 55 | user.setDeviceId(dataForm.device_id); 56 | userDao.updateDeviceId(user); 57 | 58 | return user; 59 | } 60 | 61 | public List list(String userId, int start, int row) { 62 | if (start < 0 || row < 1) { 63 | throw new IllegalArgumentException("Invalid Parameter"); 64 | } 65 | 66 | List users = userDao.listExcludeUserId(userId, start, row); 67 | 68 | List result = new ArrayList(); 69 | for (User u : users) { 70 | result.add(new UserVo(u)); 71 | } 72 | 73 | return result; 74 | } 75 | 76 | public List search(String userId, String queryText) { 77 | if (StringUtil.isEmpty(queryText)) { 78 | throw new IllegalArgumentException("Invalid Parameter"); 79 | } 80 | String _queryText = "%" + queryText + "%"; 81 | List users = userDao.search(userId, _queryText); 82 | List result = new ArrayList(); 83 | for (User u : users) { 84 | result.add(new UserVo(u)); 85 | } 86 | return result; 87 | } 88 | 89 | public UserVo getUserInfo(String userId) throws ServiceException { 90 | User user = userDao.findById(userId); 91 | if (user == null) { 92 | throw new ServiceException(ResponseBuilder.ERROR_USER_NOT_FOUND); 93 | } 94 | return new UserVo(user); 95 | } 96 | 97 | public void updateUser(String userId, UserUpdateForm dataForm) throws ServiceException { 98 | User user = userDao.findById(userId); 99 | if (user == null) { 100 | throw new ServiceException(ResponseBuilder.ERROR_FORBIDDEN_FAIL); 101 | } 102 | 103 | if (!StringUtil.isEmpty(dataForm.avatar)) { 104 | user.setAvatar(dataForm.avatar); 105 | } 106 | if (!StringUtil.isEmpty(dataForm.description)) { 107 | user.setDescription(dataForm.description); 108 | } 109 | if (!StringUtil.isEmpty(dataForm.location)) { 110 | user.setLocation(dataForm.location); 111 | } 112 | if (!StringUtil.isEmpty(dataForm.nickname)) { 113 | user.setNickname(dataForm.nickname); 114 | } 115 | if (!StringUtil.isEmpty(dataForm.sex)) { 116 | user.setSex(dataForm.sex); 117 | } 118 | 119 | userDao.update(user); 120 | } 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | 8 | /** 9 | *         ┏┓   ┏┓+ + 10 | *        ┏┛┻━━━┛┻┓ + + 11 | *        ┃       ┃ 12 | *        ┃   ━   ┃ ++ + + + 13 | *        ████━████ ┃+ 14 | *        ┃       ┃ + 15 | *        ┃   ┻   ┃ 16 | *        ┃       ┃ + + 17 | *        ┗━┓   ┏━┛ 18 | *          ┃   ┃ 19 | *          ┃   ┃ + + + + 20 | *          ┃   ┃    Code is far away from bug with the animal protecting 21 | *          ┃   ┃ +     神兽保佑,代码无BUG 22 | *          ┃   ┃ 23 | *          ┃   ┃  + 24 | *          ┃    ┗━━━┓ + + 25 | *          ┃        ┣┓ 26 | *          ┃        ┏┛ 27 | *          ┗┓┓┏━┳┓┏┛ + + + + 28 | *           ┃┫┫ ┃┫┫ 29 | *           ┗┻┛ ┗┻┛+ + + + 30 | * Created by ZeFanXie on 14-8-26. 31 | */ 32 | public final class FileUtil { 33 | 34 | public static void createFolder(String path) { 35 | File file =new File(path); 36 | if (!file.exists() && !file.isDirectory()) { 37 | file.mkdir(); 38 | } 39 | } 40 | 41 | /** 42 | * 文件转化为字节数组 43 | * 44 | * @param file 45 | * @return 46 | */ 47 | public static byte[] getBytesFromFile(File file) { 48 | byte[] ret = null; 49 | try { 50 | if (file == null) { 51 | return null; 52 | } 53 | FileInputStream in = new FileInputStream(file); 54 | ByteArrayOutputStream out = new ByteArrayOutputStream(4096); 55 | byte[] b = new byte[4096]; 56 | int n; 57 | while ((n = in.read(b)) != -1) { 58 | out.write(b, 0, n); 59 | } 60 | in.close(); 61 | out.close(); 62 | ret = out.toByteArray(); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | return ret; 67 | } 68 | 69 | private FileUtil() {} 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.util; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.JsonSyntaxException; 6 | import com.google.gson.reflect.TypeToken; 7 | import com.google.gson.stream.JsonReader; 8 | 9 | import java.io.IOException; 10 | import java.io.StringReader; 11 | import java.util.*; 12 | 13 | /** 14 | * Created by xiezefan-pc on 14-8-9. 15 | */ 16 | public final class JsonUtil { 17 | private static Gson gson = new Gson(); 18 | private static GsonBuilder gsonBuilder = new GsonBuilder(); 19 | 20 | public static Gson getGson() { 21 | return gson; 22 | } 23 | 24 | public static T format(String data, Class cls) { 25 | if (StringUtil.isEmpty(data)) { 26 | throw new JsonSyntaxException("Invalid JSON string."); 27 | } 28 | return gson.fromJson(data, cls); 29 | } 30 | 31 | public static List formatToList(String data, Class cls) { 32 | return gson.fromJson(data, new TypeToken>() {}.getType()); 33 | } 34 | 35 | public static Set formatToSet(String data, Class cls) { 36 | return gson.fromJson(data, new TypeToken>() {}.getType()); 37 | } 38 | 39 | public static List formatToList(String data) { 40 | return gson.fromJson(data, new TypeToken>() {}.getType()); 41 | } 42 | 43 | 44 | public static Map formatToMap(String data) throws JsonSyntaxException { 45 | GsonBuilder gb = new GsonBuilder(); 46 | Gson g = gb.create(); 47 | Map map = g.fromJson(data, new TypeToken>() {}.getType()); 48 | return map; 49 | } 50 | 51 | public static List> formatToArrayMap(String data) throws IOException { 52 | List> result = new ArrayList>(); 53 | JsonReader reader = null; 54 | reader = new JsonReader(new StringReader(data)); 55 | reader.setLenient(true); 56 | reader.beginArray(); 57 | while(reader.hasNext()) { 58 | reader.beginObject(); 59 | Map mapObj = new HashMap(); 60 | while (reader.hasNext()) { 61 | mapObj.put(reader.nextName(), reader.nextString()); 62 | } 63 | result.add(mapObj); 64 | reader.endObject(); 65 | } 66 | reader.endArray(); 67 | return result; 68 | } 69 | 70 | 71 | public static String toJson(Object data) { 72 | return JsonUtil.gson.toJson(data); 73 | } 74 | 75 | public static JsonBuilder newBuilder() { 76 | return new JsonBuilder(); 77 | } 78 | 79 | public static class JsonBuilder { 80 | Map data = new HashMap(); 81 | 82 | public JsonBuilder addItem(String key, Object value) { 83 | data.put(key, value); 84 | return this; 85 | } 86 | 87 | public String build() { 88 | return JsonUtil.toJson(data); 89 | } 90 | } 91 | 92 | 93 | 94 | private JsonUtil() {} 95 | 96 | public static void main(String[] args) { 97 | String str = "{\"location\":\"珠海\",\"date\":\"1\",\"action\":\"深圳明天下雨\",\"mark\":\"weather\"}"; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/me/xiezefan/easyim/server/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.util.Date; 11 | import java.util.Random; 12 | import cn.jpush.api.utils.Base64; 13 | 14 | /** 15 | * Created by xiezefan-pc on 14-8-9. 16 | */ 17 | public final class StringUtil { 18 | private static final String base = "abcdefghijklmnopqrstuvwxyzQWERTYUIOPLKJHGFDSAZXCVBNM0123456789"; 19 | 20 | public static String getRandomString(int length) { 21 | Random random = new Random(); 22 | StringBuffer sb = new StringBuffer(); 23 | for (int i = 0; i < length; i++) { 24 | sb.append(base.charAt(random.nextInt(base.length()))); 25 | } 26 | return sb.toString(); 27 | } 28 | 29 | public static String getRandomNum(int length) { 30 | Random random = new Random(); 31 | StringBuffer sb = new StringBuffer(); 32 | for (int i = 0; i < length; i++) { 33 | sb.append(random.nextInt(10)); 34 | } 35 | return sb.toString(); 36 | } 37 | 38 | public static boolean isEmpty(String str) { 39 | if (str != null && str.length() > 0) { 40 | return false; 41 | } 42 | return true; 43 | } 44 | 45 | public static String base64(String ciphertext) throws IOException { 46 | return new String(Base64.encode(ciphertext.getBytes())); 47 | } 48 | 49 | public static String formatInputStream(InputStream inputStream) { 50 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 51 | StringBuilder sb = new StringBuilder(); 52 | String line; 53 | try { 54 | while ((line = reader.readLine()) != null) { 55 | sb.append(line); 56 | sb.append("\n"); 57 | } 58 | } catch (IOException e) { 59 | e.printStackTrace(); 60 | } finally { 61 | try { 62 | inputStream.close(); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | return sb.toString(); 68 | } 69 | 70 | public static String toMD5(String source) { 71 | if (null == source || "".equals(source)) return null; 72 | try { 73 | MessageDigest digest = MessageDigest.getInstance("MD5"); 74 | digest.update(source.getBytes()); 75 | return toHex(digest.digest()); 76 | } catch (NoSuchAlgorithmException e) { 77 | return null; 78 | } 79 | } 80 | 81 | public static String toMD5(File file) { 82 | if (null == file || !file.exists()) return null; 83 | try { 84 | MessageDigest digest = MessageDigest.getInstance("MD5"); 85 | digest.update(FileUtil.getBytesFromFile(file)); 86 | return toHex(digest.digest()); 87 | } catch (NoSuchAlgorithmException e) { 88 | return null; 89 | } 90 | 91 | 92 | } 93 | 94 | public static String toHex(byte[] buf) { 95 | if (buf == null) return ""; 96 | StringBuffer result = new StringBuffer(2 * buf.length); 97 | for (int i = 0; i < buf.length; i++) { 98 | appendHex(result, buf[i]); 99 | } 100 | return result.toString(); 101 | } 102 | 103 | 104 | private final static String HEX = "0123456789ABCDEF"; 105 | 106 | private static void appendHex(StringBuffer sb, byte b) { 107 | sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); 108 | } 109 | 110 | public static String unicodeEscaped(char ch) { 111 | if (ch < 0x10) { 112 | return "\\u000" + Integer.toHexString(ch); 113 | } else if (ch < 0x100) { 114 | return "\\u00" + Integer.toHexString(ch); 115 | } else if (ch < 0x1000) { 116 | return "\\u0" + Integer.toHexString(ch); 117 | } 118 | return "\\u" + Integer.toHexString(ch); 119 | } 120 | 121 | 122 | public static String unicodeEscaped(Character ch) { 123 | if (ch == null) { 124 | return null; 125 | } 126 | return unicodeEscaped(ch.charValue()); 127 | } 128 | 129 | public static String unicodeEscaped(String source) { 130 | StringBuilder retStr = new StringBuilder(); 131 | for (int i=0; i 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=DEBUG,CONSOLE,file 2 | 3 | 4 | log4j.logger.cn.jpush.alertme=DEBUG 5 | log4j.logger.org.eclipse.jetty=ERROR 6 | log4j.logger.org.freemarker=ERROR 7 | log4j.logger.com.mchange=ERROR 8 | log4j.logger.org.springframework=ERROR 9 | log4j.logger.org.apache.ibatis=ERROR 10 | log4j.logger.org.mybatis=ERROR 11 | log4j.logger.jndi=ERROR 12 | 13 | # 显示SQL语句部分 14 | log4j.logger.com.ibatis=ERROR 15 | log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=ERROR 16 | log4j.logger.com.ibatis.common.jdbc.ScriptRunner=ERROR 17 | log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=ERROR 18 | log4j.logger.java.sql.Connection=ERROR 19 | log4j.logger.java.sql.Statement=ERROR 20 | log4j.logger.java.sql.PreparedStatement=ERROR 21 | 22 | 23 | 24 | 25 | log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 26 | log4j.appender.CONSOLE.Target=System.out 27 | log4j.appender.CONSOLE.layout=org.apache.log4j.TTCCLayout 28 | log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c:%L - %m%n 29 | 30 | ### direct messages to file hibernate.log ### 31 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender 32 | #log4j.appender.file.File=${webapp.root}/WEB-INF/log/hibernate.log 33 | log4j.appender.file.File=logs/log_ 34 | log4j.appender.file.DatePattern=yyyy-MM-dd'.log' 35 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 36 | log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n 37 | 38 | 39 | #log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 40 | #log4j.appender.CONSOLE.Target=System.out 41 | #log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 42 | #log4j.appender.CONSOLE.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n -------------------------------------------------------------------------------- /src/main/resources/mapper/FriendshipDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 32 | 33 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/resources/mapper/MessageDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/mapper/OfflineMessageDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 38 | 39 | 62 | 63 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/mybatis-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | Jersey REST Service 11 | org.glassfish.jersey.servlet.ServletContainer 12 | 13 | 14 | javax.ws.rs.Application 15 | me.xiezefan.easyim.server.web.Application 16 | 17 | 27 | 31 | 35 | 36 | 37 | Jersey REST Service 38 | /* 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | contextConfigLocation 47 | classpath:applicationContext.xml 48 | 49 | 50 | 51 | org.springframework.web.context.ContextLoaderListener 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hello World... 9 | 10 | -------------------------------------------------------------------------------- /src/test/java/me/xiezefan/easyim/server/Main.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server; 2 | 3 | /** 4 | * Created by xiezefan-pc on 2015/3/30 0030. 5 | */ 6 | public class Main { 7 | } 8 | -------------------------------------------------------------------------------- /src/test/java/me/xiezefan/easyim/server/common/Contact.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.common; 2 | 3 | /** 4 | * Created by xiezefan-pc on 2015/3/31 0031. 5 | */ 6 | public class Contact { 7 | public static final String USER_ID = "f473d1fd-4543-4af1-81c8-e1e8863681a5"; 8 | public static final String USER_ID2 = "f62f537d-3694-4df7-a456-e0584bd62b46"; 9 | public static final String USER_ID3 = "3bdbc914-d6c9-43f5-a975-05d5f428a42a"; 10 | 11 | public static final String MESSAGE_ID1 = "0043B088-0A82-406D-7FBA-CFA47A091EFE"; 12 | public static final String MESSAGE_ID2 = "D09F7A9D-D6DA-55D5-5AA2-55384D6D2A48"; 13 | public static final String MESSAGE_ID3 = "F03CF3D6-D278-C912-D210-209FB81C136E"; 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/me/xiezefan/easyim/server/dao/FriendshipDaoTest.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import com.google.gson.JsonNull; 4 | import me.xiezefan.easyim.server.common.Contact; 5 | import me.xiezefan.easyim.server.model.Friendship; 6 | import me.xiezefan.easyim.server.model.User; 7 | import me.xiezefan.easyim.server.util.JsonUtil; 8 | import org.junit.Assert; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.test.context.ContextConfiguration; 14 | import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; 15 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 16 | 17 | import java.util.List; 18 | import java.util.UUID; 19 | 20 | /** 21 | * Friendship Dao Test 22 | * Created by xiezefan-pc on 2015/4/1 0001. 23 | */ 24 | @RunWith(SpringJUnit4ClassRunner.class) 25 | @ContextConfiguration(locations="classpath:applicationContext.xml") 26 | public class FriendshipDaoTest extends AbstractTransactionalJUnit4SpringContextTests { 27 | 28 | @Autowired 29 | public FriendshipDao friendshipDao; 30 | @Autowired 31 | public UserDao userDao; 32 | 33 | @Before 34 | public void before() { 35 | User user0 = new User(); 36 | user0.setId(Contact.USER_ID); 37 | user0.setUsername(UUID.randomUUID().toString()); 38 | user0.setPassword(UUID.randomUUID().toString()); 39 | user0.setNickname(UUID.randomUUID().toString()); 40 | user0.setDeviceId(UUID.randomUUID().toString()); 41 | user0.setAvatar(UUID.randomUUID().toString()); 42 | userDao.insert(user0); 43 | 44 | User user1 = new User(); 45 | user1.setId(Contact.USER_ID2); 46 | user1.setUsername(UUID.randomUUID().toString()); 47 | user1.setPassword(UUID.randomUUID().toString()); 48 | user1.setNickname(UUID.randomUUID().toString()); 49 | user1.setDeviceId(UUID.randomUUID().toString()); 50 | user1.setAvatar(UUID.randomUUID().toString()); 51 | userDao.insert(user1); 52 | 53 | User user2 = new User(); 54 | user2.setId(Contact.USER_ID3); 55 | user2.setUsername(UUID.randomUUID().toString()); 56 | user2.setPassword(UUID.randomUUID().toString()); 57 | user2.setNickname(UUID.randomUUID().toString()); 58 | user2.setAvatar(UUID.randomUUID().toString()); 59 | userDao.insert(user2); 60 | } 61 | 62 | @Test 63 | public void insertAndFindByIdTest() { 64 | User friend = userDao.findById(Contact.USER_ID2); 65 | 66 | Friendship friendship = new Friendship(); 67 | friendship.setId(UUID.randomUUID().toString()); 68 | friendship.setUserId(Contact.USER_ID); 69 | friendship.setFriend(friend); 70 | friendshipDao.insert(friendship); 71 | 72 | Friendship friendship2 = friendshipDao.findById(friendship.getId()); 73 | Assert.assertTrue(friendship.getUserId().equals(friendship2.getUserId())); 74 | } 75 | 76 | @Test 77 | public void findByUserIdTest() { 78 | User friend1 = userDao.findById(Contact.USER_ID2); 79 | User friend2 = userDao.findById(Contact.USER_ID3); 80 | 81 | Friendship friendship1 = new Friendship(); 82 | friendship1.setId(UUID.randomUUID().toString()); 83 | friendship1.setUserId(Contact.USER_ID); 84 | friendship1.setFriend(friend1); 85 | friendshipDao.insert(friendship1); 86 | 87 | Friendship friendship2 = new Friendship(); 88 | friendship2.setId(UUID.randomUUID().toString()); 89 | friendship2.setUserId(Contact.USER_ID); 90 | friendship2.setFriend(friend2); 91 | friendshipDao.insert(friendship2); 92 | 93 | List list = friendshipDao.findByUserId(Contact.USER_ID); 94 | Assert.assertTrue(list.size() == 2); 95 | 96 | 97 | } 98 | 99 | @Test 100 | public void validateExistTest() { 101 | User friend1 = userDao.findById(Contact.USER_ID2); 102 | 103 | Friendship friendship1 = new Friendship(); 104 | friendship1.setId(UUID.randomUUID().toString()); 105 | friendship1.setUserId(Contact.USER_ID); 106 | friendship1.setFriend(friend1); 107 | friendshipDao.insert(friendship1); 108 | 109 | Long count = friendshipDao.validateExist(Contact.USER_ID, Contact.USER_ID2); 110 | Assert.assertTrue(count == 1); 111 | 112 | count = friendshipDao.validateExist(Contact.USER_ID, Contact.USER_ID3); 113 | Assert.assertTrue(count == 0); 114 | } 115 | 116 | @Test 117 | public void deleteBothTest() { 118 | User friend1 = userDao.findById(Contact.USER_ID2); 119 | 120 | Friendship friendship1 = new Friendship(); 121 | friendship1.setId(UUID.randomUUID().toString()); 122 | friendship1.setUserId(Contact.USER_ID); 123 | friendship1.setFriend(friend1); 124 | friendshipDao.insert(friendship1); 125 | 126 | friendshipDao.deleteBoth(Contact.USER_ID, Contact.USER_ID2); 127 | Long count = friendshipDao.validateExist(Contact.USER_ID, Contact.USER_ID2); 128 | Assert.assertTrue(count == 0); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/me/xiezefan/easyim/server/dao/MessageDaoTest.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import me.xiezefan.easyim.server.model.Message; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.test.context.ContextConfiguration; 8 | import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.Date; 13 | import java.util.UUID; 14 | 15 | /** 16 | * Created by xiezefan-pc on 2015/4/11 0011. 17 | */ 18 | @RunWith(SpringJUnit4ClassRunner.class) 19 | @ContextConfiguration(locations="classpath:applicationContext.xml") 20 | public class MessageDaoTest extends AbstractTransactionalJUnit4SpringContextTests { 21 | @Resource 22 | private MessageDao messageDao; 23 | 24 | @Test 25 | public void saveAndFindByIdTest() { 26 | // save 27 | Message msg = new Message(); 28 | msg.setId(UUID.randomUUID().toString()); 29 | msg.setFromId(UUID.randomUUID().toString()); 30 | msg.setToId(UUID.randomUUID().toString()); 31 | msg.setType(UUID.randomUUID().toString()); 32 | msg.setContentStr(UUID.randomUUID().toString()); 33 | msg.setCreateTime(new Date()); 34 | messageDao.save(msg); 35 | 36 | // findById 37 | Message msg2 = messageDao.findById(msg.getId()); 38 | Assert.assertTrue(msg2.getId().equals(msg.getId())); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/me/xiezefan/easyim/server/dao/OfflineMessageDaoTest.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import me.xiezefan.easyim.server.common.Contact; 4 | import me.xiezefan.easyim.server.model.Message; 5 | import me.xiezefan.easyim.server.model.MessageStatus; 6 | import me.xiezefan.easyim.server.model.OfflineMessage; 7 | import org.junit.Assert; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.test.context.ContextConfiguration; 12 | import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; 13 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 14 | 15 | import javax.annotation.Resource; 16 | import java.util.Date; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.UUID; 21 | 22 | /** 23 | * Created by xiezefan-pc on 2015/4/11 0011. 24 | */ 25 | @RunWith(SpringJUnit4ClassRunner.class) 26 | @ContextConfiguration(locations="classpath:applicationContext.xml") 27 | public class OfflineMessageDaoTest extends AbstractTransactionalJUnit4SpringContextTests { 28 | 29 | @Resource 30 | private OfflineMessageDao offlineMessageDao; 31 | @Resource 32 | private MessageDao messageDao; 33 | 34 | @Before 35 | public void before() { 36 | Message msg = new Message(); 37 | msg.setId(Contact.MESSAGE_ID1); 38 | msg.setFromId(UUID.randomUUID().toString()); 39 | msg.setToId(UUID.randomUUID().toString()); 40 | msg.setType(UUID.randomUUID().toString()); 41 | Map content = new HashMap(); 42 | content.put("key1", "value1"); 43 | content.put("key2", "value2"); 44 | msg.setContent(content); 45 | msg.setCreateTime(new Date()); 46 | messageDao.save(msg); 47 | } 48 | 49 | @Test 50 | public void saveAndFindByIdTest() { 51 | Message msg = messageDao.findById(Contact.MESSAGE_ID1); 52 | 53 | // save 54 | OfflineMessage offlineMsg = new OfflineMessage(); 55 | offlineMsg.setId(UUID.randomUUID().toString()); 56 | offlineMsg.setUserId(UUID.randomUUID().toString()); 57 | offlineMsg.setMessage(msg); 58 | offlineMsg.setStatus(MessageStatus.SEND); 59 | offlineMsg.setCreateTime(new Date()); 60 | offlineMessageDao.save(offlineMsg); 61 | 62 | // findById 63 | OfflineMessage offlineMsg2 = offlineMessageDao.findById(offlineMsg.getId()); 64 | Assert.assertTrue(offlineMsg2.getMessage().getId().equals(msg.getId())); 65 | 66 | } 67 | 68 | 69 | @Test 70 | public void updateStatusTest() { 71 | Message msg = messageDao.findById(Contact.MESSAGE_ID1); 72 | 73 | OfflineMessage offlineMsg = new OfflineMessage(); 74 | offlineMsg.setId(UUID.randomUUID().toString()); 75 | offlineMsg.setUserId(UUID.randomUUID().toString()); 76 | offlineMsg.setMessage(msg); 77 | offlineMsg.setStatus(MessageStatus.SEND); 78 | offlineMsg.setCreateTime(new Date()); 79 | offlineMessageDao.save(offlineMsg); 80 | 81 | offlineMsg.setStatus(MessageStatus.READ); 82 | offlineMessageDao.updateStatus(offlineMsg); 83 | 84 | OfflineMessage offlineMsg2 = offlineMessageDao.findById(offlineMsg.getId()); 85 | Assert.assertTrue(offlineMsg2.getStatus() == MessageStatus.READ); 86 | 87 | 88 | } 89 | 90 | @Test 91 | public void findOfflineTest() { 92 | Message msg = messageDao.findById(Contact.MESSAGE_ID1); 93 | 94 | Message msg2 = new Message(); 95 | msg2.setId(Contact.MESSAGE_ID2); 96 | msg2.setFromId(UUID.randomUUID().toString()); 97 | msg2.setToId(UUID.randomUUID().toString()); 98 | msg2.setType(UUID.randomUUID().toString()); 99 | Map content = new HashMap(); 100 | content.put("key1", "value1"); 101 | content.put("key2", "value2"); 102 | msg2.setContent(content); 103 | msg2.setCreateTime(new Date()); 104 | messageDao.save(msg2); 105 | 106 | Message msg3 = new Message(); 107 | msg3.setId(Contact.MESSAGE_ID3); 108 | msg3.setFromId(UUID.randomUUID().toString()); 109 | msg3.setToId(UUID.randomUUID().toString()); 110 | msg3.setType(UUID.randomUUID().toString()); 111 | msg3.setContent(content); 112 | msg3.setCreateTime(new Date()); 113 | messageDao.save(msg3); 114 | 115 | OfflineMessage offlineMsg = new OfflineMessage(); 116 | offlineMsg.setId(UUID.randomUUID().toString()); 117 | offlineMsg.setUserId(Contact.USER_ID); 118 | offlineMsg.setMessage(msg); 119 | offlineMsg.setStatus(MessageStatus.SEND); 120 | offlineMsg.setCreateTime(new Date()); 121 | offlineMessageDao.save(offlineMsg); 122 | 123 | OfflineMessage offlineMsg2 = new OfflineMessage(); 124 | offlineMsg2.setId(UUID.randomUUID().toString()); 125 | offlineMsg2.setUserId(Contact.USER_ID); 126 | offlineMsg2.setMessage(msg2); 127 | offlineMsg2.setStatus(MessageStatus.READ); 128 | offlineMsg2.setCreateTime(new Date()); 129 | offlineMessageDao.save(offlineMsg2); 130 | 131 | OfflineMessage offlineMsg3 = new OfflineMessage(); 132 | offlineMsg3.setId(UUID.randomUUID().toString()); 133 | offlineMsg3.setUserId(Contact.USER_ID); 134 | offlineMsg3.setMessage(msg3); 135 | offlineMsg3.setStatus(MessageStatus.SEND); 136 | offlineMsg3.setCreateTime(new Date()); 137 | offlineMessageDao.save(offlineMsg3); 138 | 139 | List list = offlineMessageDao.findOffline(Contact.USER_ID); 140 | 141 | Assert.assertTrue(list.size() == 2); 142 | } 143 | 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/test/java/me/xiezefan/easyim/server/dao/UserDaoTest.java: -------------------------------------------------------------------------------- 1 | package me.xiezefan.easyim.server.dao; 2 | 3 | import me.xiezefan.easyim.server.common.Contact; 4 | import me.xiezefan.easyim.server.model.User; 5 | import me.xiezefan.easyim.server.util.JsonUtil; 6 | import me.xiezefan.easyim.server.util.StringUtil; 7 | import org.junit.Assert; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.test.context.ContextConfiguration; 13 | import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; 14 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 15 | 16 | import java.util.Date; 17 | import java.util.List; 18 | import java.util.UUID; 19 | 20 | 21 | /** 22 | * User Dao Test 23 | * Created by xiezefan-pc on 2015/3/30 0030. 24 | */ 25 | @RunWith(SpringJUnit4ClassRunner.class) 26 | @ContextConfiguration(locations="classpath:applicationContext.xml") 27 | public class UserDaoTest extends AbstractTransactionalJUnit4SpringContextTests { 28 | 29 | 30 | @Autowired 31 | public UserDao userDao; 32 | 33 | @Before 34 | public void before() { 35 | User user = new User(); 36 | user.setId(Contact.USER_ID); 37 | user.setUsername(UUID.randomUUID().toString()); 38 | user.setPassword(UUID.randomUUID().toString()); 39 | user.setNickname(UUID.randomUUID().toString()); 40 | user.setDeviceId(UUID.randomUUID().toString()); 41 | userDao.insert(user); 42 | } 43 | 44 | @Test 45 | public void insertAndFindByIdTest() { 46 | // insert 47 | User user = new User(); 48 | user.setId(UUID.randomUUID().toString()); 49 | user.setUsername(UUID.randomUUID().toString()); 50 | user.setPassword(UUID.randomUUID().toString()); 51 | user.setNickname(UUID.randomUUID().toString()); 52 | user.setDeviceId(UUID.randomUUID().toString()); 53 | user.setCreateTime(new Date()); 54 | userDao.insert(user); 55 | 56 | // find by id 57 | User user2 = userDao.findById(user.getId()); 58 | Assert.assertTrue(user2.getUsername().equals(user.getUsername())); 59 | 60 | } 61 | 62 | @Test 63 | public void updateDeviceIdTest() { 64 | User user = userDao.findById(Contact.USER_ID); 65 | String newDeviceId = StringUtil.getRandomString(8); 66 | user.setDeviceId(newDeviceId); 67 | userDao.updateDeviceId(user); 68 | User user2 = userDao.findById(user.getId()); 69 | Assert.assertTrue(user2.getDeviceId().equals(newDeviceId)); 70 | } 71 | 72 | @Test 73 | public void findDeviceByUserIdTest() { 74 | String deviceId = userDao.findDeviceByUserId(Contact.USER_ID); 75 | Assert.assertTrue(!StringUtil.isEmpty(deviceId)); 76 | } 77 | 78 | @Test 79 | public void listText() { 80 | List result = userDao.list(0, 15); 81 | Assert.assertTrue(result.size() > 1); 82 | } 83 | 84 | @Test 85 | public void searchText() { 86 | User user = new User(); 87 | user.setId(Contact.USER_ID2); 88 | user.setUsername("kdsjaskdhjaksjdh"); 89 | user.setPassword(UUID.randomUUID().toString()); 90 | user.setNickname("hjcvxkhjvsdfsdf"); 91 | user.setDeviceId(UUID.randomUUID().toString()); 92 | userDao.insert(user); 93 | 94 | List result1 = userDao.search(Contact.USER_ID3, "%skdhja%"); 95 | List result2 = userDao.search(Contact.USER_ID3, "%hjcvxkhjvsdfsdf%"); 96 | List result3 = userDao.search(Contact.USER_ID3, "%not_exist%"); 97 | 98 | Assert.assertTrue(result1.size() == 1); 99 | Assert.assertTrue(result2.size() == 1); 100 | Assert.assertTrue(result3.size() == 0); 101 | } 102 | 103 | @Test 104 | public void listExcludeUserIdText() { 105 | User user = new User(); 106 | user.setId(Contact.USER_ID2); 107 | user.setUsername("kdsjaskdhjaksjdh"); 108 | user.setPassword(UUID.randomUUID().toString()); 109 | user.setNickname("hjcvxkhjvsdfsdf"); 110 | user.setDeviceId(UUID.randomUUID().toString()); 111 | userDao.insert(user); 112 | 113 | List result1 = userDao.listExcludeUserId(Contact.USER_ID2, 0, 15); 114 | List result2 = userDao.list(0, 15); 115 | Assert.assertTrue(result2.size() - result1.size() == 1); 116 | } 117 | 118 | @Test 119 | public void updateTest() { 120 | User user = userDao.findById(Contact.USER_ID); 121 | user.setNickname("Nickname"); 122 | user.setLocation("Location"); 123 | user.setSex("Sex"); 124 | user.setDescription("Description"); 125 | user.setAvatar("Avatar"); 126 | userDao.update(user); 127 | 128 | User user2 = userDao.findById(Contact.USER_ID); 129 | Assert.assertEquals("Nickname", user2.getNickname()); 130 | Assert.assertEquals("Location", user2.getLocation()); 131 | Assert.assertEquals("Sex", user2.getSex()); 132 | Assert.assertEquals("Description", user2.getDescription()); 133 | Assert.assertEquals("Avatar", user2.getAvatar()); 134 | } 135 | 136 | } 137 | --------------------------------------------------------------------------------