服务端demo新增webrtc信令接口示例

This commit is contained in:
远方夕阳 2022-08-30 11:50:26 +08:00
parent a0ddbe47c5
commit c93ac73e80
20 changed files with 1101 additions and 7 deletions

View File

@ -0,0 +1,2 @@
如果你不想搭建服务端也可以使用,公共的服务器做测试喔
具体信息参见https://www.yuque.com/yuanfangxiyang/ma4ytb/vvy3iz#yC5Vq

View File

@ -48,6 +48,11 @@
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>

View File

@ -1,3 +1,3 @@
#! /bin/bash
java -Dcom.sun.akuma.Daemon=daemonized -Dspring.profiles.active=pro -jar ./cim-boot-server-4.2.0.jar &
java -Dcom.sun.akuma.Daemon=daemonized -Dspring.profiles.active=dev -Dserver.port=9090 -jar ./cim-boot-server-4.2.0.jar &

View File

@ -0,0 +1,35 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用户标注通过 token查到的用户账号注入到Controller参数里面
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessToken {
}

View File

@ -0,0 +1,4 @@
package com.farsunset.cim.annotation;
public @interface CreateAction {
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用户标注通过 token查到的用户账号注入到Controller参数里面
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface UID {
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.component.redis;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class TokenRedisTemplate extends StringRedisTemplate {
private static final String TOKEN_CACHE_PREFIX = "TOKEN_%s";
public TokenRedisTemplate(RedisConnectionFactory connectionFactory) {
super(connectionFactory);
}
public void save(String token, String uid) {
String key = String.format(TOKEN_CACHE_PREFIX,token);
super.boundValueOps(key).set(uid);
}
public String get(String token) {
String key = String.format(TOKEN_CACHE_PREFIX,token);
return super.boundValueOps(key).get();
}
public void remove(String token) {
String key = String.format(TOKEN_CACHE_PREFIX,token);
super.delete(key);
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.config;
import com.farsunset.cim.mvc.resolver.TokenArgumentResolver;
import com.farsunset.cim.mvc.resolver.UidArgumentResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import java.util.List;
@Configuration
public class MvcConfig implements WebMvcConfigurer{
@Resource
private HandlerInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/webrtc/**");
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new UidArgumentResolver());
argumentResolvers.add(new TokenArgumentResolver());
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOriginPattern("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.setAllowCredentials(true);
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
}
}

View File

@ -26,10 +26,14 @@ import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.List;
@EnableOpenApi
@Configuration
public class SwaggerConfig {
@ -38,10 +42,12 @@ public class SwaggerConfig {
public Docket userApiDocket(ApiInfo apiInfo) {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo)
.groupName("APP接口")
.groupName("客户端接口")
.select()
.apis(RequestHandlerSelectors.basePackage("com.farsunset.cim.mvc.controller.api"))
.build();
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
@Bean
@ -49,8 +55,27 @@ public class SwaggerConfig {
return new ApiInfoBuilder()
.title("CIM Push Service APIs.")
.description("CIM客户端接口文档")
.version("2.0")
.version("3.0")
.build();
}
private List<SecurityScheme> securitySchemes() {
List<SecurityScheme> schemeList = new ArrayList<>();
schemeList.add(new ApiKey("access-token", "access-token", "header"));
return schemeList;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> securityContextList = new ArrayList<>();
List<SecurityReference> securityReferenceList = new ArrayList<>();
securityReferenceList.add(new SecurityReference("access-token", new AuthorizationScope[]{new AuthorizationScope("global", "accessAnything")}));
securityContextList.add(SecurityContext
.builder()
.securityReferences(securityReferenceList)
.operationSelector(operationContext -> true)
.build()
);
return securityContextList;
}
}

View File

@ -0,0 +1,165 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.constants;
public interface MessageAction {
/*
* 系统定制消息---语音通话请求
*/
String ACTION_900 = "900";
/*
* 系统定制消息---视频通话请求
*/
String ACTION_901 = "901";
/*
* 系统定制消息---通话接受
*/
String ACTION_902 = "902";
/*
* 系统定制消息---通话拒绝
*/
String ACTION_903 = "903";
/*
* 系统定制消息---对方正忙
*/
String ACTION_904 = "904";
/*
* 系统定制消息---对方挂断
*/
String ACTION_905 = "905";
/*
* 系统定制消息---取消呼叫
*/
String ACTION_906 = "906";
/*
* 系统定制消息---同步ICE SPD
*/
String ACTION_907 = "907";
/*
* 系统定制消息---同步Offer
*/
String ACTION_908 = "908";
/*
* 系统定制消息---同步Answer
*/
String ACTION_909 = "909";
/*
* 系统定制消息---多人语音通话请求
*/
String ACTION_910 = "910";
/*
* 系统定制消息---多人视频通话请求
*/
String ACTION_911 = "911";
/*
*系统定制消息---多人通话-同意
*/
String ACTION_912 = "912";
/*
*系统定制消息---多人通话-拒绝
*/
String ACTION_913 = "913";
/*
*系统定制消息---多人通话-忙线
*/
String ACTION_914 = "914";
/*
*系统定制消息---多人通话-开麦开关
*/
String ACTION_915 = "915";
/*
*系统定制消息---多人通话-摄像头开关
*/
String ACTION_916 = "916";
/*
*系统定制消息---多人通话-加人
*/
String ACTION_917 = "917";
/*
*系统定制消息---多人通话-退出
*/
String ACTION_918 = "918";
/*
*系统定制消息---多人通话-取消呼叫
*/
String ACTION_919 = "919";
/*
* 系统定制消息---多人通话-同步Offer
*/
String ACTION_920 = "920";
/*
* 系统定制消息---多人通话-同步Answer
*/
String ACTION_921 = "921";
/*
* 系统定制消息---多人通话-同步ICE
*/
String ACTION_922 = "922";
/*
*系统定制消息---多人通话-未响应
*/
String ACTION_923 = "923";
/*
*系统定制消息---多人通话-结束会议
*/
String ACTION_924 = "924";
/*
*系统定制消息---多人通话-全员静音
*/
String ACTION_925 = "925";
/*
*系统定制消息---多人通话-取消全员静音
*/
String ACTION_926 = "926";
/*
*系统定制消息---多人通话-有人再次被呼叫
*/
String ACTION_927 = "927";
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.mvc.controller.api;
import com.farsunset.cim.annotation.AccessToken;
import com.farsunset.cim.mvc.response.ResponseEntity;
import com.farsunset.cim.service.AccessTokenService;
import io.swagger.annotations.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/user")
@Api(produces = "application/json", tags = "用户登录接口" )
@Validated
public class UserController {
@Resource
private AccessTokenService accessTokenService;
@ApiOperation(httpMethod = "POST", value = "模拟登录")
@ApiImplicitParams({
@ApiImplicitParam(name = "telephone", value = "手机号码", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "password", value = "密码", paramType = "query", dataTypeClass = String.class),
})
@PostMapping(value = "/login")
public ResponseEntity<?> login(@RequestParam String telephone) {
Map<String,Object> body = new HashMap<>();
body.put("id",Long.parseLong(telephone));
body.put("name","测试用户");
body.put("telephone","telephone");
ResponseEntity<Map<String,Object>> result = new ResponseEntity<>();
result.setData(body);
result.setToken(accessTokenService.generate(telephone));
result.setTimestamp(System.currentTimeMillis());
return result;
}
@ApiOperation(httpMethod = "GET", value = "退出登录")
@GetMapping(value = "/logout")
public ResponseEntity<Void> logout(@ApiParam(hidden = true) @AccessToken String token) {
accessTokenService.delete(token);
return ResponseEntity.make();
}
}

View File

@ -0,0 +1,189 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.mvc.controller.api;
import com.farsunset.cim.annotation.UID;
import com.farsunset.cim.component.push.DefaultMessagePusher;
import com.farsunset.cim.constants.MessageAction;
import com.farsunset.cim.model.Message;
import com.farsunset.cim.mvc.request.WebrtcRequest;
import com.farsunset.cim.mvc.response.ResponseEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/webrtc")
@Api(produces = "application/json", tags = "单人通话信令推送接口" )
public class WebrtcController {
@Resource
private DefaultMessagePusher defaultMessagePusher;
@ApiOperation(httpMethod = "POST", value = "发起单人语音通话")
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
@PostMapping(value = {"/voice"})
public ResponseEntity<Void> voice(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
Message message = new Message();
message.setAction(MessageAction.ACTION_900);
message.setSender(uid);
message.setReceiver(targetId);
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "发起单人视频通话")
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
@PostMapping(value = {"/video"})
public ResponseEntity<Void> video(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
Message message = new Message();
message.setAction(MessageAction.ACTION_901);
message.setSender(uid);
message.setReceiver(targetId);
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "接受通话")
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
@PostMapping(value = {"/accept"})
public ResponseEntity<Void> accept(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
Message message = new Message();
message.setAction(MessageAction.ACTION_902);
message.setSender(uid);
message.setReceiver(targetId);
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "拒绝通话")
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
@PostMapping(value = {"/reject"})
public ResponseEntity<Void> reject(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
Message message = new Message();
message.setAction(MessageAction.ACTION_903);
message.setSender(uid);
message.setReceiver(targetId);
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "反馈正忙")
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
@PostMapping(value = {"/busy"})
public ResponseEntity<Void> busy(@ApiParam(hidden = true) @UID String uid, @RequestParam String targetId) {
Message message = new Message();
message.setAction(MessageAction.ACTION_904);
message.setSender(uid);
message.setReceiver(targetId);
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "挂断通话")
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
@PostMapping(value = {"/hangup"})
public ResponseEntity<Void> hangup(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
Message message = new Message();
message.setAction(MessageAction.ACTION_905);
message.setSender(uid);
message.setReceiver(targetId);
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "取消呼叫")
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
@PostMapping(value = {"/cancel"})
public ResponseEntity<Void> cancel(@ApiParam(hidden = true) @UID String uid, @RequestParam String targetId) {
Message message = new Message();
message.setAction(MessageAction.ACTION_906);
message.setSender(uid);
message.setReceiver(targetId);
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "同步IceCandidate")
@PostMapping(value = {"/transmit/ice"})
public ResponseEntity<Void> ice(@ApiParam(hidden = true) @UID String uid,
@RequestBody WebrtcRequest request
) {
Message message = new Message();
message.setAction(MessageAction.ACTION_907);
message.setSender(uid);
message.setContent(request.getContent());
message.setReceiver(request.getUid());
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "同步offer")
@PostMapping(value = {"/transmit/offer"})
public ResponseEntity<Void> offer(@ApiParam(hidden = true) @UID String uid,
@RequestBody WebrtcRequest request
) {
Message message = new Message();
message.setAction(MessageAction.ACTION_908);
message.setSender(uid);
message.setContent(request.getContent());
message.setReceiver(request.getUid());
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
@ApiOperation(httpMethod = "POST", value = "同步answer")
@PostMapping(value = {"/transmit/answer"})
public ResponseEntity<Void> answer(@ApiParam(hidden = true) @UID String uid,
@RequestBody WebrtcRequest request
) {
Message message = new Message();
message.setAction(MessageAction.ACTION_909);
message.setSender(uid);
message.setContent(request.getContent());
message.setReceiver(request.getUid());
defaultMessagePusher.push(message);
return ResponseEntity.make();
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.mvc.interceptor;
import com.farsunset.cim.annotation.AccessToken;
import com.farsunset.cim.annotation.UID;
import com.farsunset.cim.service.AccessTokenService;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 在此鉴权获得UID
*/
@Component
public class TokenInterceptor implements HandlerInterceptor {
private static final String HEADER_TOKEN = "access-token";
@Resource
private AccessTokenService accessTokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
String token = request.getHeader(HEADER_TOKEN);
String uid = accessTokenService.getUid(token);
/*
* 直接拒绝无token的接口调用请求或者token没有查询到对应的登录用户
*/
if (uid == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
request.setAttribute(UID.class.getName(), uid);
request.setAttribute(AccessToken.class.getName(), token);
return true;
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.mvc.request;
import com.farsunset.cim.annotation.CreateAction;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@ApiModel("单人通话ice、offer、answer同步请求体")
public class WebrtcRequest implements Serializable {
@NotNull(message = "UID不能为空",groups = CreateAction.class)
@ApiModelProperty("对方UID")
private String uid;
@NotEmpty(message = "content不能超过2000个字符",groups = CreateAction.class)
@ApiModelProperty("ice信息json、offer或者answer的sdp")
private String content;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.mvc.resolver;
import com.farsunset.cim.annotation.AccessToken;
import com.farsunset.cim.annotation.UID;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
public class TokenArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(AccessToken.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
return webRequest.getAttribute(AccessToken.class.getName(),RequestAttributes.SCOPE_REQUEST);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.mvc.resolver;
import com.farsunset.cim.annotation.UID;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
public class UidArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(UID.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
return webRequest.getAttribute(UID.class.getName(),RequestAttributes.SCOPE_REQUEST);
}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.mvc.response;
import org.springframework.http.HttpStatus;
public class ResponseEntity<T> {
private int code = HttpStatus.OK.value();
private String message;
private T data;
private String token;
private Long timestamp;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getToken() {
return token;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public void setToken(String token) {
this.token = token;
}
public static ResponseEntity<Void> make(){
return new ResponseEntity<>();
}
public static ResponseEntity<Void> make(int code){
return make(code,null);
}
public static <T> ResponseEntity<T> make(int code,String message){
ResponseEntity<T> result = new ResponseEntity<>();
result.setCode(code);
result.setMessage(message);
return result;
}
public static ResponseEntity<Void> make(HttpStatus status){
ResponseEntity<Void> result = new ResponseEntity<>();
result.setCode(status.value());
result.setMessage(status.getReasonPhrase());
return result;
}
public static <Q> ResponseEntity<Q> make(HttpStatus status,String message){
ResponseEntity<Q> result = new ResponseEntity<>();
result.setCode(status.value());
result.setMessage(message);
return result;
}
public static <Q> ResponseEntity<Q> ok(Q data){
ResponseEntity<Q> result = new ResponseEntity<>();
result.setData(data);
return result;
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.service;
public interface AccessTokenService {
String generate(String uid);
String getUid(String token);
void delete(String value);
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.service.impl;
import com.farsunset.cim.component.redis.TokenRedisTemplate;
import com.farsunset.cim.service.AccessTokenService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.UUID;
@Service
public class AccessTokenServiceImpl implements AccessTokenService {
@Resource
private TokenRedisTemplate tokenRedisTemplate;
@Override
public String getUid(String token) {
if (StringUtils.isBlank(token)){
return null;
}
return tokenRedisTemplate.get(token);
}
@Override
public void delete(String token) {
tokenRedisTemplate.delete(token);
}
/**
* 方便调试这里生成token为永不过期
* @param uid
* @return
*/
@Override
public String generate(String uid) {
String newToken = UUID.randomUUID().toString().replace("-","");
tokenRedisTemplate.save(newToken, uid);
return newToken;
}
}

View File

@ -1,5 +1,7 @@
server.port=8080
spring.jackson.default-property-inclusion=non_empty
#单台服务器可设置为dev广播消息走本地消息事件(参见SignalRedisTemplate.java)
#多台服务器集群环境设置为prd广播消息走三方消息队列
spring.profiles.active=dev
@ -9,8 +11,8 @@ spring.profiles.active=dev
# JDBC Config #
##################################################################
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/cim?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.username = cim
spring.datasource.password = f8HYPmssXL6XmZeK
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver