提交 04f6bbc7 编写于 作者: F fengyongwei

修改工程名称

上级 bb4f36cb
...@@ -361,9 +361,9 @@ ...@@ -361,9 +361,9 @@
<!-- 课程管理 --> <!-- 课程管理 -->
<module>roncoo-education-course</module> <module>roncoo-education-course</module>
<!-- 定时任务 --> <!-- 定时任务 -->
<module>roncoo-education-crontab-plan</module> <module>roncoo-education-job</module>
<!-- 网关接口 --> <!-- 网关接口 -->
<module>roncoo-education-gateway-api</module> <module>roncoo-education-gateway</module>
<!-- 管理后台 --> <!-- 管理后台 -->
<module>roncoo-education-web-boss</module> <module>roncoo-education-web-boss</module>
</modules> </modules>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>roncoo-education-crontab-plan</artifactId>
<name>roncoo-education-crontab-plan</name>
<dependencies>
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-course-feign</artifactId>
</dependency>
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-user-feign</artifactId>
</dependency>
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-system-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>crontab-plan</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 定时任务
*/
@EnableScheduling
@EnableFeignClients
@SpringCloudApplication
public class CrontabPlanApplication {
public static void main(String[] args) {
SpringApplication.run(CrontabPlanApplication.class, args);
}
}
package com.roncoo.education.crontab;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.roncoo.education.system.feign.IBossMsg;
import com.roncoo.education.util.base.BaseController;
/**
* 站内信-定时发送
*
* @author wuyun
*
*/
@Component
public class MsgSendCrontab extends BaseController {
private static final Object KEY = new Object();
private static boolean taskFlag = false;
@Autowired
private IBossMsg bossMsg;
/**
* 定时任务,一小时启动一次
*
* @author wuyun
*/
@Scheduled(fixedRate = 60000)
public void pushCancel() {
synchronized (KEY) {
if (MsgSendCrontab.taskFlag) {
logger.warn("站内信-定时发送已经启动");
return;
}
MsgSendCrontab.taskFlag = true;
}
try {
bossMsg.push();
} catch (Exception e) {
logger.error("站内信-定时发送-执行出错", e);
}
MsgSendCrontab.taskFlag = false;
logger.warn("站内信-定时发送-任务完成");
}
}
package com.roncoo.education.crontab;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.roncoo.education.course.feign.IBossOrderInfo;
import com.roncoo.education.util.base.BaseController;
/**
* 定时任务-订单处理
*
* @author wuyun
*/
@Component
public class OrderCrontab extends BaseController {
private static final Object KEY = new Object();
private static boolean taskFlag = false;
@Autowired
private IBossOrderInfo bossOrderInfo;
/**
* 定时任务每分钟执行一次
*/
@Scheduled(fixedRate = 60000)
public void orderCancel() {
synchronized (KEY) {
if (OrderCrontab.taskFlag) {
logger.warn("订单处理-任务已经启动");
return;
}
OrderCrontab.taskFlag = true;
}
logger.warn("订单处理-定时任务开始");
try {
bossOrderInfo.handleScheduledTasks();
} catch (Exception e) {
logger.error("定时任务-订单处理-执行出错", e);
}
OrderCrontab.taskFlag = false;
}
}
package com.roncoo.education.crontab;
import java.io.File;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.roncoo.education.course.feign.IBossCourseVideo;
import com.roncoo.education.util.base.BaseController;
import com.roncoo.education.util.config.SystemUtil;
import com.xiaoleilu.hutool.io.FileUtil;
/**
* 定时任务-视频处理
*
* @author wuyun
*/
@Component
public class VideoCrontab extends BaseController {
private static final Object KEY = new Object();
private static boolean taskFlag = false;
@Autowired
private IBossCourseVideo bossCourseVideo;
/**
* 定时任务每分钟执行一次 <br/>
* 注意:每个course服务都必须要对应有一个定时任务,针对服务器
*/
@Scheduled(fixedRate = 60000)
public void orderCancel() {
synchronized (KEY) {
if (VideoCrontab.taskFlag) {
logger.warn("视频处理-任务已经启动");
return;
}
VideoCrontab.taskFlag = true;
}
int videoSum = 0;
File file = new File(SystemUtil.PERIOD_VIDEO_PATH);
if (file.isDirectory()) {// isDirectory是否文件夹
File[] files = file.listFiles();// listFiles是获取该目录下所有文件和目录的绝对路径
for (File targetFile : files) {
if (targetFile.isFile() && targetFile.exists()) {
if (FileUtil.newerThan(targetFile, (System.currentTimeMillis() - 7200000))) {// 上传两个小时内
try {
bossCourseVideo.handleScheduledTasks(targetFile);
videoSum = videoSum + 1;
} catch (Exception e) {
logger.error("视频定时任务处理失败", e);
}
}
}
}
}
VideoCrontab.taskFlag = false;
logger.warn("视频处理-定时任务完成,处理视频数={}", videoSum);
}
}
# info
info.eureka.host=localhost
info.eureka.port=5761
# profile
spring.profiles.active=dev
# eureka
eureka.client.serviceUrl.defaultZone=http://${info.eureka.host}:${info.eureka.port}/eureka/
# server
server.port=5910
# application
spring.application.name=roncoo-education-crontab-plan
# spring cloud config client
spring.cloud.config.profile=${spring.profiles.active}
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=roncoo-education-server-config
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>roncoo-education-gateway-api</artifactId>
<name>roncoo-education-gateway-api</name>
<dependencies>
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-util</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency> -->
</dependencies>
<build>
<finalName>gateway-api</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import com.roncoo.education.gateway.api.common.FilterError;
import com.roncoo.education.gateway.api.common.FilterPost;
import com.roncoo.education.gateway.api.common.FilterPre;
/**
* 服务网关
*
* @author wujing
*/
@EnableZuulProxy
@SpringCloudApplication
public class GatewayApiApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApiApplication.class, args);
}
@Bean
public FilterError filterError() {
return new FilterError();
}
@Bean
public FilterPre filterPre() {
return new FilterPre();
}
@Bean
public FilterPost filterPost() {
return new FilterPost();
}
}
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.gateway.api.common;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.roncoo.education.util.base.Result;
import com.roncoo.education.util.tools.JSONUtil;
/**
* 出现错误时执行
*/
public class FilterError extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(FilterError.class);
@Override
public String filterType() {
return FilterConstants.ERROR_TYPE;
}
@Override
public int filterOrder() {
return -1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
Throwable throwable = ctx.getThrowable();
if (throwable != null) {
logger.warn(ReflectionToStringBuilder.toString(throwable, ToStringStyle.MULTI_LINE_STYLE));
ctx.getResponse().setCharacterEncoding("UTF-8");
ctx.setResponseBody(JSONUtil.toJSONString(Result.error("系统异常")));
}
return null;
}
}
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.gateway.api.common;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.roncoo.education.util.base.Result;
import com.roncoo.education.util.tools.JSONUtil;
/**
* 请求处理完成后执行
*/
public class FilterPost extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
// 异常处理
if (ctx.getResponseStatusCode() != 200) {
ctx.getResponse().setCharacterEncoding("UTF-8");
ctx.setResponseBody(JSONUtil.toJSONString(Result.error(99, "服务异常,请重试")));
}
return false;
}
@Override
public Object run() {
return null;
}
}
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.gateway.api.common;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.roncoo.education.util.base.BaseException;
import com.roncoo.education.util.base.Result;
import com.roncoo.education.util.enums.ResultEnum;
import com.roncoo.education.util.tools.JSONUtil;
import com.roncoo.education.util.tools.JWTUtil;
/**
* 请求开始前执行
*/
public class FilterPre extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(FilterPre.class);
private static final String TOKEN = "token";
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
String uri = RequestContext.getCurrentContext().getRequest().getServletPath();
if (uri.startsWith("/callback")) {
// 回调使用
return false;
}
if (uri.startsWith("/zuul")) {
// 文件上传
return false;
}
if (!uri.startsWith("/auth")) {
// 非token校验
return false;
}
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
Long userNo = null;
try {
userNo = getUserNoByToken(request);
} catch (BaseException e) {
logger.error("系统异常", e.getMessage());
resp(ctx, e.getMessage(), e.getCode());
}
// 参数封装
try {
ctx.setRequest(requestWrapper(request, userNo));
} catch (IOException e) {
logger.error("封装参数异常", e.getMessage());
resp(ctx, "系统异常,请重试");
}
return null;
}
/**
* token 拦截功能
*/
private Long getUserNoByToken(HttpServletRequest request) {
String token = request.getHeader(TOKEN); // 检验token
if (StringUtils.isEmpty(token)) { // token不存在,则从报文里面获取
throw new BaseException("token不存在,请重新登录");
}
// 解析 token
DecodedJWT jwt = null;
try {
jwt = JWTUtil.verify(token);
} catch (Exception e) {
logger.error("token异常,token={}", token.toString());
throw new BaseException(ResultEnum.TOKEN_ERROR);
}
// 校验token
if (null == jwt) {
throw new BaseException(ResultEnum.TOKEN_ERROR);
}
Long userNo = JWTUtil.getUserNo(jwt);
if (userNo <= 0) {
throw new BaseException(ResultEnum.TOKEN_ERROR);
}
// 单点登录处理,注意,登录的时候必须要放入缓存
/*if (!stringRedisTemplate.hasKey(userNo.toString())) {
// 不存在,则登录异常,有效期为1小时
throw new BaseException(ResultEnum.TOKEN_PAST);
}
// 存在,判断是否token相同
String tk = stringRedisTemplate.opsForValue().get(userNo.toString());
if (!token.equals(tk)) {
// 不同则为不同的用户登录,这时候提示异地登录
throw new BaseException(ResultEnum.REMOTE_ERROR);
}*/
// 更新时间,使token不过期
stringRedisTemplate.opsForValue().set(userNo.toString(), token, 1, TimeUnit.HOURS);
return userNo;
}
private HttpServletRequestWrapper requestWrapper(HttpServletRequest request, Long userNo) throws IOException {
Map<String, Object> map = getParamMap(request);
if (null == map) {
map = new HashMap<>();
}
if (userNo != null) {
map.put("userNo", userNo);
}
String newBody = JSONUtil.toJSONString(map);
logger.info("转发参数={}", newBody);
final byte[] reqBodyBytes = newBody.getBytes();
return new HttpServletRequestWrapper(request) {
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(reqBodyBytes);
}
@Override
public int getContentLength() {
return reqBodyBytes.length;
}
@Override
public long getContentLengthLong() {
return reqBodyBytes.length;
}
};
}
private void resp(RequestContext ctx, String msg) {
ctx.getResponse().setCharacterEncoding("UTF-8");
ctx.setResponseBody(JSONUtil.toJSONString(Result.error(msg)));
}
private void resp(RequestContext ctx, String msg, int code) {
ctx.getResponse().setCharacterEncoding("UTF-8");
ctx.setResponseBody(JSONUtil.toJSONString(Result.error(code, msg)));
}
@SuppressWarnings("unchecked")
private static TreeMap<String, Object> getParamMap(HttpServletRequest request) {
TreeMap<String, Object> paramMap = new TreeMap<>();
Map<String, String[]> map = request.getParameterMap();
for (String key : map.keySet()) {
paramMap.put(key, map.get(key)[0]);
}
if (paramMap.isEmpty()) {
DataInputStream in = null;
try {
in = new DataInputStream(request.getInputStream());
byte[] buf = new byte[request.getContentLength()];
in.readFully(buf);
String t = new String(buf, "UTF-8");
if (StringUtils.hasText(t)) {
return new TreeMap<>(JSONUtil.parseObject(t, TreeMap.class));
}
} catch (Exception e) {
logger.warn("获取不到任何参数");
} finally {
if (null != in)
try {
in.close();// 关闭数据流
} catch (IOException e) {
}
}
}
return paramMap;
}
}
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.gateway.api.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class IndexController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
return "index";
}
}
# info
info.eureka.host=localhost
info.eureka.port=5761
# profile
spring.profiles.active=dev
# eureka
eureka.client.serviceUrl.defaultZone=http://${info.eureka.host}:${info.eureka.port}/eureka/
# server
server.port=5840
# application
spring.application.name=roncoo-education-gateway-api
# spring cloud config client
spring.cloud.config.profile=${spring.profiles.active}
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=roncoo-education-server-config
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>接口文档</title>
</head>
<body>
<div style="margin:0 auto;text-align:center;">
<br/>
<a href="http://192.168.1.181:5710/doc.html" target="_blanck">课程API</a>
<br/>
<br/>
<a href="http://192.168.1.181:5720/doc.html" target="_blanck">用户API</a>
<br/>
<br/>
<a href="http://192.168.1.181:5730/doc.html" target="_blanck">系统API</a>
</div>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册