Repository: nosqlcoco/springboot-weapp-demo
Branch: master
Commit: c843e2b69204
Files: 44
Total size: 69.4 KB
Directory structure:
gitextract_c7s5u6lo/
├── README.md
├── pom.xml
└── src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── weapp/
│ │ ├── Application.java
│ │ ├── SwaggerConfig.java
│ │ ├── aop/
│ │ │ └── ApiAspect.java
│ │ ├── common/
│ │ │ ├── aes/
│ │ │ │ └── AES.java
│ │ │ ├── annotation/
│ │ │ │ └── Api.java
│ │ │ ├── constant/
│ │ │ │ └── ApiConstant.java
│ │ │ ├── properties/
│ │ │ │ └── WxAuth.java
│ │ │ └── util/
│ │ │ ├── HttpRequest.java
│ │ │ └── MongoPageable.java
│ │ ├── controller/
│ │ │ ├── AppUserController.java
│ │ │ ├── BaseController.java
│ │ │ ├── UploadController.java
│ │ │ ├── WxAuthController.java
│ │ │ └── WxClubController.java
│ │ ├── entity/
│ │ │ ├── app/
│ │ │ │ └── TUser.java
│ │ │ ├── auth/
│ │ │ │ ├── AccessLog.java
│ │ │ │ ├── ApiInfo.java
│ │ │ │ └── AppKey.java
│ │ │ └── wxclub/
│ │ │ └── Article.java
│ │ ├── interceptor/
│ │ │ ├── ApiInterceptor.java
│ │ │ └── ApiWebConfigure.java
│ │ ├── listener/
│ │ │ └── ApiServletContextListener.java
│ │ ├── redis/
│ │ │ ├── MyRedisCacheConfig.java
│ │ │ └── RedisUtil.java
│ │ ├── repository/
│ │ │ ├── AccessLogRepository.java
│ │ │ ├── ApiInfoRepository.java
│ │ │ ├── AppKeyRepository.java
│ │ │ └── WxClubRepository.java
│ │ ├── service/
│ │ │ ├── AccessLogService.java
│ │ │ ├── ApiInfoService.java
│ │ │ ├── AppKeyService.java
│ │ │ ├── WxClubService.java
│ │ │ └── WxService.java
│ │ ├── webconfig/
│ │ │ └── WebConfigurer.java
│ │ └── websocket/
│ │ ├── ChatWebSocketHandler.java
│ │ ├── WebSocketConfig.java
│ │ └── WebSocketHandshakeInterceptor.java
│ └── resources/
│ ├── application.properties
│ ├── error_code.properties
│ └── log4j.properties
└── test/
├── java/
│ └── com/
│ └── weapp/
│ └── ApplicationTest.java
└── resources/
└── application-test.properties
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# springboot-weapp-demo
微信小程序服务端接口,支持普通Http请求、上传文件、长连接,微信登录及敏感数据解密。后台服务使用springboot框架搭建,mongodb做数据库,redis做缓存。
运行环境:JDK8+
<font color="red">注意:如果你是本地运行,需要修改为你本地对应的主机和端口。</font>
长连接需使用ws协议
####更新日志:
- 2016-12-18
- 拦截器记录口访问日志存储mongodb
- 2016-11-24
- 小程序code换取session_key和openid
- 小程序登录用户敏感数据解密
- 2016-11-22
- 配置Https
- 2016-11-18
- 重写小程序http测试和上传文件接口
- 统一接口返回返回状态码和格式
- 2016-11-20
- 添加Redis缓存
- 添加微信登录状态维护和用户数据解密接口
#### 一、测试小程序wx.request接口
```javascript
wx.request({
url: 'http://localhost:9090/weappservice/api/v1/user/get/{id}',
data: {appId: 'JWEJIJ345QHWJKENVKF', apiName: 'GET_USER'},
method: 'GET',
//return JSON format,like: {"id":"{id}"}
success: function(res){
console.log(res.data);
},
fail: function(res){
},
complete: function(res){
}
});
```
#### 二、测试小程序wx.uploadFile接口,单张上传
```javascript
wx.uploadFile({
url: 'http://localhost:9090/weappservice/api/v1/upload/image',
//文件临时路径
filePath: tempFilePath,
name: 'file',
header: {},
formData: {appId: 'JWEJIJ345QHWJKENVKF', apiName: 'UPLOAD_IMAGE'},
success: function(res){
console.log(res.data)
},
fail: function(res){
},
complete: function(res){
}
});
```
<table>
<tr>
<th>状态码(errcode)</th>
<th>说明(msg)</th>
</tr>
<tr>
<td>0</td>
<td>图片路径</td>
</tr>
<tr>
<td>40010</td>
<td>请选择上传文件!</td>
</tr>
<tr>
<td>40011</td>
<td>文件上传失败</td>
</tr>
</table>
#### 三、测试小程序websocket相关接口
```javascript
//发起websocket连接
wx.connectSocket({
url: 'ws://localhost:9090/weappservice/websocket?name=xiaoqiang',
//这里写了参数,但是参数没有发送出去,大家可以试试,已经邮件反馈微信团队了,等待回复。所以把参数拼接在url后面。
data: {
'name1': 'xiaoqiang1'
}
}),
//监听打开事件
wx.onSocketOpen(function(res) {
console.log('WebSocket连接已打开!');
}),
//接收消息,接收的消息是json字符串,需要JSON.parse转成JSON对象
wx.onSocketMessage(function(res){
var data = JSON.parse(res.data);
console.log(data);
}),
//发送消息,消息对象属性key(user和content)不能自定义。
wx.sendSocketMessage({
data: JSON.stringify({
user: 'xiaoqaing',
content: 'Hi, My name is xiaoqiang'
}),
success: function(res){
console.log('消息发送成功!')
}
})
```
我的微信小程序DEMO:[weixin_smallexe](https://github.com/cocoli/weixin_smallexe)
PS:我的公众号:

================================================
FILE: pom.xml
================================================
<?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>
<groupId>com.wxapp</groupId>
<artifactId>wxapp</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>wxchatdemo1.0.0</name>
<description>wechat app API Project</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<bcprov.version>1.54</bcprov.version>
<swagger2.version>2.2.2</swagger2.version>
<jsoup.version>1.8.3</jsoup.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 长连接 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- mongoDB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- alibaba fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- google guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<!-- http -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bcprov.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
================================================
FILE: src/main/java/com/weapp/Application.java
================================================
package com.weapp;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.SocketUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.weapp.common.constant.ApiConstant;
import com.weapp.common.properties.WxAuth;
import com.weapp.entity.auth.AppKey;
import com.weapp.repository.AppKeyRepository;
/**
*
* @author Shanqiang Ke
* @version 1.0.0
* @blog http://nosqlcoco.cnblogs.com
* @since 2016-10-15
*/
@SpringBootApplication
@ComponentScan(value = "com.weapp")
@EnableConfigurationProperties(value={WxAuth.class})
public class Application implements CommandLineRunner{
@Autowired
private AppKeyRepository repository;
private static ImmutableMap<String, String>errorCodeMap = null;
static {
try {
Properties prop = PropertiesLoaderUtils.loadAllProperties("error_code.properties");
errorCodeMap = Maps.fromProperties(prop);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... arg0) throws Exception {
repository.deleteAll();
String[] apiNames = new String[]{ApiConstant.GET_USER,ApiConstant.POST_USER,ApiConstant.PUT_USER,
ApiConstant.DELETE_USER,ApiConstant.WX_CODE,ApiConstant.WX_DECODE_USERINFO,
ApiConstant.WX_CLUB_ARTICLES,ApiConstant.WX_CLUB_SEARCH};
Map<String, Map<String,Integer>> apiMap = Maps.newHashMap();
for(String apiName : apiNames){
Map<String,Integer>tmpMap = new HashMap<String,Integer>();
tmpMap.put("calltimes", 0);
tmpMap.put("alltimes", 10000);
apiMap.put(apiName, tmpMap);
}
repository.save(new AppKey("JWEJIJ345QHWJKENVKF", "sdsd", new Date(), new Date(), "1", false, apiMap));
}
@Bean
public ImmutableMap<String, String> errorCodeMap(){
return errorCodeMap;
}
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
@Bean
public Integer port() {
return SocketUtils.findAvailableTcpPort();
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(port());
return connector;
}
}
================================================
FILE: src/main/java/com/weapp/SwaggerConfig.java
================================================
package com.weapp;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Value("${server.context-path}")
private String pathMapping;
@Bean
public Docket createRestApi() {
System.out.println("http://localhost:8080" + pathMapping + "/swagger-ui.html");
return new Docket(DocumentationType.SWAGGER_2)
.groupName("test")
.genericModelSubstitutes(ResponseEntity.class)
.useDefaultResponseMessages(true)
.forCodeGeneration(false)
.pathMapping(pathMapping)
.select()
.apis(RequestHandlerSelectors.basePackage("com.weapp.controller"))
.paths(PathSelectors.any())
.build();
//.apiInfo(apiInfo());
}
// private ApiInfo apiInfo() {
// return new ApiInfoBuilder()
// .title("微信小程序后台服务API")
// .description("更多小程序知识,请关注微信公众号『柯善强的随思笔记』")
// .termsOfServiceUrl("http://www.cnblogs.com/nosqlcoco/")
// .contact("柯善强")
// .version("1.0").build();
// }
}
================================================
FILE: src/main/java/com/weapp/aop/ApiAspect.java
================================================
package com.weapp.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
@Aspect
@Component
public class ApiAspect {
@Pointcut(value="@annotation(com.weapp.common.annotation.Api)")
public void apiAspect(){
}
@Around("apiAspect()")
public Object doAround(ProceedingJoinPoint pjp) throws Exception{
Object result = null;
StopWatch sw = new StopWatch(getClass().getSimpleName());
try {
sw.start(pjp.getSignature().getName());
result = pjp.proceed();
} catch(Throwable e){
e.printStackTrace();
}finally {
sw.stop();
}
return result;
}
}
================================================
FILE: src/main/java/com/weapp/common/aes/AES.java
================================================
package com.weapp.common.aes;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class AES {
public static boolean initialized = false;
/**
* AES解密
* @param content 密文
* @return
* @throws InvalidAlgorithmParameterException
* @throws NoSuchProviderException
*/
public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
initialize();
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
byte[] result = cipher.doFinal(content);
return result;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void initialize(){
if (initialized) return;
Security.addProvider(new BouncyCastleProvider());
initialized = true;
}
//生成iv
public static AlgorithmParameters generateIV(byte[] iv) throws Exception{
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
}
================================================
FILE: src/main/java/com/weapp/common/annotation/Api.java
================================================
package com.weapp.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* API注解,使用在Controller控制器方法上
* @author xiaoqiang
*
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Api {
/*接口名称*/
String name();
/*每天上限*/
int accessLimit() default 10000;
/*接口版本*/
String version() default "v1";
/*接口禁用*/
boolean disabled() default false;
/*参数解密算法*/
String algorithm() default "none";
}
================================================
FILE: src/main/java/com/weapp/common/constant/ApiConstant.java
================================================
package com.weapp.common.constant;
/**
* API常量
* @author xiaoqiang
*
*/
public class ApiConstant {
/*测试*/
public final static String TEST_HTTP = "TEST_HTTP";
/*获取用户信息*/
public final static String GET_USER = "GET_USER";
/*创建用户信息*/
public final static String POST_USER = "POST_USER";
/*更新用户信息*/
public final static String PUT_USER = "PUT_USER";
/*删除用户信息*/
public final static String DELETE_USER = "DELETE_USER";
/*上传图片*/
public final static String UPLOAD_IMAGE = "UPLOAD_IMAGE";
/*微信code*/
public static final String WX_CODE = "WX_CODE";
/*校验微信用户信息完整性*/
public static final String WX_CHECK_USER = "WX_CHECK_USER";
/*解密用户信息*/
public static final String WX_DECODE_USERINFO = "WX_DECODE_USERINFO";
/* club社区专栏 */
public static final String WX_CLUB_ARTICLES = "WX_CLUB_ARTICLES";
/* club社区专栏文章搜索 */
public static final String WX_CLUB_SEARCH = "WX_CLUB_SEARCH";
}
================================================
FILE: src/main/java/com/weapp/common/properties/WxAuth.java
================================================
package com.weapp.common.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
@ConfigurationProperties(prefix = "wxapp")
@Data
public class WxAuth {
private String appId;
private String secret;
private String grantType;
private String sessionHost;
}
================================================
FILE: src/main/java/com/weapp/common/util/HttpRequest.java
================================================
/**
*
* @project ApiService
* @filename HttpRequest.java
* @date 2015年8月16日
* @author KeShanqiang
*
*/
package com.weapp.common.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
public class HttpRequest {
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("authorization", "Authorization: Basic token=0abf1040cda747f1bd724719fd2c8496");
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}
================================================
FILE: src/main/java/com/weapp/common/util/MongoPageable.java
================================================
package com.weapp.common.util;
import java.io.Serializable;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
public class MongoPageable implements Serializable, Pageable{
/**
* mongodb分页
*/
private static final long serialVersionUID = 1L;
// 当前页
private Integer pagenumber = 1;
// 当前页面条数
private Integer pagesize = 10;
@Override
public int getPageNumber() {
return 0;
}
@Override
public int getPageSize() {
return 0;
}
@Override
public int getOffset() {
return 0;
}
@Override
public Pageable next() {
return null;
}
@Override
public Pageable previousOrFirst() {
return null;
}
@Override
public Pageable first() {
return null;
}
@Override
public boolean hasPrevious() {
return false;
}
public Integer getPagenumber() {
return pagenumber;
}
public void setPagenumber(Integer pagenumber) {
this.pagenumber = pagenumber;
}
public Integer getPagesize() {
return pagesize;
}
public void setPagesize(Integer pagesize) {
this.pagesize = pagesize;
}
@Override
public Sort getSort() {
return null;
}
}
================================================
FILE: src/main/java/com/weapp/controller/AppUserController.java
================================================
package com.weapp.controller;
import java.util.Map;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.ImmutableMap;
import com.weapp.common.annotation.Api;
import com.weapp.common.constant.ApiConstant;
@RestController
@RequestMapping
public class AppUserController {
@Api(name=ApiConstant.GET_USER)
@RequestMapping(value = "/api/v1/user/{id}", method = RequestMethod.GET, produces = "application/json")
public Map<String, String> get(@PathVariable String id){
ImmutableMap<String, String> map = ImmutableMap.of("id", id);
return map;
}
@Api(name=ApiConstant.POST_USER)
@RequestMapping(value = "/api/v1/user/{id}", method = RequestMethod.POST, produces = "application/json")
public Map<String, String> post(@PathVariable String id){
ImmutableMap<String, String> map = ImmutableMap.of("id", id);
return map;
}
@Api(name=ApiConstant.PUT_USER)
@RequestMapping(value = "/api/v1/user/{id}", method = RequestMethod.PUT, produces = "application/json")
public Map<String, String> put(@PathVariable String id){
ImmutableMap<String, String> map = ImmutableMap.of("id", id);
return map;
}
@Api(name=ApiConstant.DELETE_USER)
@RequestMapping(value = "/api/v1/user/{id}", method = RequestMethod.DELETE, produces = "application/json")
public Map<String, String> delete(@PathVariable String id){
ImmutableMap<String, String> map = ImmutableMap.of("id", id);
return map;
}
}
================================================
FILE: src/main/java/com/weapp/controller/BaseController.java
================================================
package com.weapp.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.common.collect.ImmutableMap;
@Component
public abstract class BaseController {
@Autowired
private ImmutableMap<String, String> errorCodeMap;
/**
* 接口数据返回
* @param errorCode
* @param data
* @return
*/
protected Map<String,Object> rtnParam(Integer errorCode,Object data) {
//正常的业务逻辑
if(errorCode == 0){
return ImmutableMap.of("errorCode", errorCode,"data", (data == null)? new Object() : data);
}else{
return ImmutableMap.of("errorCode", errorCode, "msg", errorCodeMap.get(String.valueOf(errorCode)));
}
}
}
================================================
FILE: src/main/java/com/weapp/controller/UploadController.java
================================================
package com.weapp.controller;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.google.common.collect.ImmutableMap;
import com.weapp.common.annotation.Api;
import com.weapp.common.constant.ApiConstant;
@RestController
public class UploadController extends BaseController{
//文件存储路径
@Value("${img.local.path}")
private String imgLocalPath;
//文件网络访问路径
@Value("${img.host}")
private String imgHost;
/**
* 上传文件
* @param file
* @return
*/
@Api(name = ApiConstant.UPLOAD_IMAGE)
@RequestMapping(value = "/api/v1/upload/image", method = RequestMethod.POST, produces = "application/json")
public Map<String,Object> uploadImage(@RequestParam(required=true,value="file")MultipartFile file){
if(null == file){
return rtnParam(40010, null);
}
String random = RandomStringUtils.randomAlphabetic(16);
String fileName = random + ".jpg";
try {
String uploadDirName = imgLocalPath.substring(imgLocalPath.lastIndexOf("/"), imgLocalPath.length());
FileCopyUtils.copy(file.getBytes(), new File(imgLocalPath + "/", fileName));
return rtnParam(0, ImmutableMap.of("url", imgHost + uploadDirName + "/" + fileName));
} catch (IOException e) {
e.printStackTrace();
}
return rtnParam(40011, null);
}
}
================================================
FILE: src/main/java/com/weapp/controller/WxAuthController.java
================================================
package com.weapp.controller;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.util.Arrays;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.ImmutableMap;
import com.weapp.common.aes.AES;
import com.weapp.common.annotation.Api;
import com.weapp.common.constant.ApiConstant;
import com.weapp.redis.RedisUtil;
import com.weapp.service.WxService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
/**
* 微信用户认证相关
* @author xiaoqiang
*
*/
@RestController
public class WxAuthController extends BaseController{
@Autowired
private WxService wxService;
@Autowired
private RedisUtil redisUtil;
/**
* 根据客户端传过来的code从微信服务器获取appid和session_key,然后生成3rdkey返回给客户端,后续请求客户端传3rdkey来维护客户端登录态
* @param wxCode 小程序登录时获取的code
* @return
*/
@ApiOperation(value = "获取sessionId", notes = "小用户允许登录后,使用code 换取 session_key api,将 code 换成 openid 和 session_key")
@ApiImplicitParam(name = "code", value = "用户登录回调内容会带上 ", required = true, dataType = "String")
@Api(name = ApiConstant.WX_CODE)
@RequestMapping(value = "/api/v1/wx/getSession", method = RequestMethod.GET, produces = "application/json")
public Map<String,Object> createSssion(@RequestParam(required = true,value = "code")String wxCode){
Map<String,Object> wxSessionMap = wxService.getWxSession(wxCode);
if(null == wxSessionMap){
return rtnParam(50010, null);
}
//获取异常
if(wxSessionMap.containsKey("errcode")){
return rtnParam(50020, null);
}
String wxOpenId = (String)wxSessionMap.get("openid");
String wxSessionKey = (String)wxSessionMap.get("session_key");
System.out.println(wxSessionKey);
Long expires = Long.valueOf(String.valueOf(wxSessionMap.get("expires_in")));
String thirdSession = wxService.create3rdSession(wxOpenId, wxSessionKey, expires);
return rtnParam(0, ImmutableMap.of("sessionId",thirdSession));
}
/**
* 验证用户信息完整性
* @param rawData 微信用户基本信息
* @param signature 数据签名
* @param sessionId 会话ID
* @return
*/
@Api(name = ApiConstant.WX_CHECK_USER)
@RequestMapping(value = "/api/v1/wx/checkUserInfo", method = RequestMethod.GET, produces = "application/json")
public Map<String,Object> checkUserInfo(@RequestParam(required = true,value = "rawData")String rawData,
@RequestParam(required = true,value = "signature")String signature,
@RequestParam(required = true,defaultValue = "sessionId")String sessionId){
Object wxSessionObj = redisUtil.get(sessionId);
if(null == wxSessionObj){
return rtnParam(40008, null);
}
String wxSessionStr = (String)wxSessionObj;
String sessionKey = wxSessionStr.split("#")[0];
StringBuffer sb = new StringBuffer(rawData);
sb.append(sessionKey);
byte[] encryData = DigestUtils.sha1(sb.toString());
byte[] signatureData = signature.getBytes();
Boolean checkStatus = Arrays.equals(encryData, signatureData);
return rtnParam(0, ImmutableMap.of("checkPass", checkStatus));
}
/**
* 获取用户openId和unionId数据(如果没绑定微信开放平台,解密数据中不包含unionId)
* @param encryptedData 加密数据
* @param iv 加密算法的初始向量
* @param sessionId 会话ID
* @return
*/
@Api(name = ApiConstant.WX_DECODE_USERINFO)
@RequestMapping(value = "/api/v1/wx/decodeUserInfo", method = RequestMethod.GET, produces = "application/json")
public Map<String,Object> decodeUserInfo(@RequestParam(required = true,value = "encryptedData")String encryptedData,
@RequestParam(required = true,defaultValue = "iv")String iv,
@RequestParam(required = true,defaultValue = "sessionId")String sessionId){
System.out.println(encryptedData);
System.out.println(iv);
//从缓存中获取session_key
Object wxSessionObj = redisUtil.get(sessionId);
if(null == wxSessionObj){
return rtnParam(40008, null);
}
String wxSessionStr = (String)wxSessionObj;
String sessionKey = wxSessionStr.split("#")[0];
try {
AES aes = new AES();
byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
if(null != resultByte && resultByte.length > 0){
String userInfo = new String(resultByte, "UTF-8");
return rtnParam(0, userInfo);
}
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return rtnParam(50021, null);
}
}
================================================
FILE: src/main/java/com/weapp/controller/WxClubController.java
================================================
package com.weapp.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.weapp.common.annotation.Api;
import com.weapp.common.constant.ApiConstant;
import com.weapp.common.util.MongoPageable;
import com.weapp.entity.wxclub.Article;
import com.weapp.service.WxClubService;
/**
* 微信小程序Club专栏文章接口
* @site http://www.wxappclub.com
* @author xiaoqiang
*
*/
@RestController
public class WxClubController extends BaseController{
@Autowired
private WxClubService wxClubService;
/**
* 专栏文章列表
* @param id
* @param page
* @return
*/
@Api(name = ApiConstant.WX_CLUB_ARTICLES)
@RequestMapping(value = "/api/v1/wxclub/column/{id}/{page}", method = RequestMethod.GET, produces = "application/json")
public Map<String, ? extends Object>getArticles(@PathVariable String id,@PathVariable Integer page){
List<Article>list = wxClubService.getByGroupPath("/column/" + id);
return rtnParam(0, list);
}
/**
* 文章搜索
* @param pageNo
* @param searchText
* @return
*/
@Api(name = ApiConstant.WX_CLUB_SEARCH)
@RequestMapping(value = "/api/v1/wxclub/column/search/{pageNo}", method = RequestMethod.GET, produces = "application/json")
public Map<String, ? extends Object>getArticles(@PathVariable(value="pageNo",required=false) Integer pageNo,
@RequestParam(required=false,value="text",defaultValue="")String searchText){
MongoPageable page = new MongoPageable();
page.setPagenumber(pageNo);
List<Article>list = wxClubService.getByTitle(searchText, page);
return rtnParam(0, list);
}
}
================================================
FILE: src/main/java/com/weapp/entity/app/TUser.java
================================================
package com.weapp.entity.app;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* App用户实体类
* @author xiaoqiang
*
*/
@Document(collection="t_users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TUser {
@Id
private String id;
private String appId;
private String password;
private String realName;
private String nickName;
private String gender;
private String avatar;
private String signature;
private String wxOpenId;
private String wxUnionId;
private String birthday;
private String address;
private String createDate;
private String updateDate;
private String lastLoginDate;
private Boolean disabled;
private String phone;
private Boolean isPhoneActive;
private String email;
private Boolean isEmailActive;
}
================================================
FILE: src/main/java/com/weapp/entity/auth/AccessLog.java
================================================
package com.weapp.entity.auth;
import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* API访问日志
* @author xiaoqiang
*
*/
@Document(collection="t_access_logs")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AccessLog {
@Id
private String id;
/*api名称*/
private String apiName;
/*接口路径*/
private String uri;
/*访问时间*/
private Date accessDate;
/*请求参数*/
private String reqParam;
/*返回参数*/
private String resParam;
/*异常内容*/
private String exp;
public AccessLog(String apiName, String uri, Date accessDate, String reqParam, String resParam, String exp) {
super();
this.apiName = apiName;
this.uri = uri;
this.accessDate = accessDate;
this.reqParam = reqParam;
this.resParam = resParam;
this.exp = exp;
}
}
================================================
FILE: src/main/java/com/weapp/entity/auth/ApiInfo.java
================================================
package com.weapp.entity.auth;
import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* API接口管理
* @author xiaoqiang
*
*/
@Document(collection="t_apis")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ApiInfo {
@Id
private String id;
/*接口名称*/
private String name;
/*接口地址*/
private String uri;
/*权限之和
* Get = 1
* POST = 2
* PUT = 4
* DELETE = 8
*/
private Integer crud;
/*每天调用次数上限*/
private Integer accessLimit;
/*版本号*/
private String version;
/*是否可用*/
private boolean disabled;
/*解密算法*/
private String algorithm;
private Date createDate;
public ApiInfo(String name,String uri, Integer accessLimit, String version, boolean disabled, String algorithm, Date createDate) {
super();
this.name = name;
this.uri = uri;
this.accessLimit = accessLimit;
this.version = version;
this.disabled = disabled;
this.algorithm = algorithm;
this.createDate = createDate;
}
}
================================================
FILE: src/main/java/com/weapp/entity/auth/AppKey.java
================================================
package com.weapp.entity.auth;
import java.util.Date;
import java.util.Map;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* app认证实体
* @author xiaoqiang
*
*/
@Document(collection="t_appkeys")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AppKey {
@Id
private String id;
/*分发的应用ID*/
private String appId;
/*密钥*/
private String secretKey;
/*创建日期*/
private Date createDate;
/*有效截止日期,为2030-01-01 00:00:00表示无日期限制*/
private Date validDate;
/*应用权限等级*/
private String appGrade;
/*是否禁用*/
private Boolean disabled;
/*拥有的api,及调用次数上限*/
private Map<String, Map<String,Integer>> apis;
public AppKey(String appId, String secretKey, Date createDate, Date validDate, String appGrade, Boolean disabled,
Map<String, Map<String,Integer>> apis) {
super();
this.appId = appId;
this.secretKey = secretKey;
this.createDate = createDate;
this.validDate = validDate;
this.appGrade = appGrade;
this.disabled = disabled;
this.apis = apis;
}
}
================================================
FILE: src/main/java/com/weapp/entity/wxclub/Article.java
================================================
package com.weapp.entity.wxclub;
import java.util.Map;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Document(collection="t_articles")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Article {
@Id
private String id;
private String path;
private String groupPath;
private String title;
private String digest;
private String createTime;
private Integer browers;
private Integer comments;
private Map<String,String> author;
private String mark;
private String content;
}
================================================
FILE: src/main/java/com/weapp/interceptor/ApiInterceptor.java
================================================
package com.weapp.interceptor;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.google.common.collect.ImmutableMap;
import com.weapp.entity.auth.AccessLog;
import com.weapp.entity.auth.ApiInfo;
import com.weapp.entity.auth.AppKey;
import com.weapp.service.AccessLogService;
import com.weapp.service.ApiInfoService;
import com.weapp.service.AppKeyService;
/**
* api接口拦截处理
* @author xiaoqiang
*
*/
public class ApiInterceptor implements HandlerInterceptor {
private static ImmutableMap<String,Integer>methodMap = ImmutableMap.of("GET", 1, "POST", 2, "PUT", 4, "DELETE", 8);
@Autowired
private AppKeyService appKeyService;
@Autowired
private ApiInfoService apiInfoService;
@Autowired
private ImmutableMap<String, String> errorCodeMap;
@Autowired
private AccessLogService accessLogService;
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception exp)
throws Exception {
String apiName = request.getParameter("apiName");
if(!StringUtils.isEmpty(apiName)){
AccessLog accessLog = new AccessLog();
accessLog.setAccessDate(new Date());
accessLog.setApiName(apiName);
accessLog.setUri(request.getRequestURI());
if(exp != null){
accessLog.setExp(exp.getMessage());
}
//拼接请求参数,key1=value1&key2=value2的形式
String paramStr = "";
Map<String,String[]> params = request.getParameterMap();
if (params != null && params.size() > 0) {
for(Map.Entry<String, String[]> p : params.entrySet()){
if(p.getValue() == null || p.getValue().length == 0){
continue;
}
paramStr += p.getKey() + "=" + p.getValue()[0] + "&";
}
}
accessLog.setReqParam(paramStr.substring(0, paramStr.length() - 1));
System.out.println(accessLog.getReqParam());
accessLogService.save(accessLog);
}
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
String apiName = request.getParameter("apiName");
if(null == apiName || "".equals(apiName)){
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return false;
}
ApiInfo apiInfo = apiInfoService.getByApiName(apiName);
if(null == apiInfo){
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return false;
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
//判断接口状态;
if(apiInfo.isDisabled()){
//接口已禁用
out = response.getWriter();
out.append(getResStr("40003"));
out.flush();
out.close();
return false;
}
String method = request.getMethod();
if(Integer.compare(methodMap.get(method), apiInfo.getCrud()) != 0){
//http method不匹配 apiInfo.getCrud()
out = response.getWriter();
out.append(getResStr("40005"));
out.flush();
out.close();
return false;
}
String appId = request.getParameter("appId");
if(null == appId || "".equals(appId)){
out = response.getWriter();
out.append(getResStr("40001"));
out.flush();
out.close();
return false;
}
//获取appid,请求是否合法
AppKey appKey = appKeyService.getByAppId(appId);
if(null == appKey){
out = response.getWriter();
out.append(getResStr("40001"));
out.flush();
out.close();
return false;
}
//判断是否有接口调用权限
Map<String,Map<String,Integer>>apiMap = appKey.getApis();
if(null == apiMap || apiMap.size() == 0 || !apiMap.containsKey(apiName)){
//无调用权限
out = response.getWriter();
out.append(getResStr("40006"));
out.flush();
out.close();
return false;
}
//调用次数是否超出上限;
Map<String,Integer>methodInfo = apiMap.get(apiName);
if(methodInfo.get("calltimes") > methodInfo.get("alltimes")){
//超出调用次数
out = response.getWriter();
out.append(getResStr("40007"));
out.flush();
out.close();
return false;
}
//参数校验
//通过,更新调用次数
methodInfo.put("calltimes", methodInfo.get("calltimes") + 1);
apiMap.put(apiName, methodInfo);
appKey.setApis(apiMap);
//记录访问日志
appKeyService.update(appKey);
return true;
}
private String getResStr(String errorCode){
return "{\"errorCode\":" + errorCode + ",\"msg\":\"" + errorCodeMap.get(errorCode) + "\"}";
}
}
================================================
FILE: src/main/java/com/weapp/interceptor/ApiWebConfigure.java
================================================
package com.weapp.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* API接口拦截配置
* @author xiaoqiang
*
*/
@Configuration
public class ApiWebConfigure extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(getApiInterceptor())
.addPathPatterns("/api/**");
}
@Bean
public ApiInterceptor getApiInterceptor(){
return new ApiInterceptor();
}
}
================================================
FILE: src/main/java/com/weapp/listener/ApiServletContextListener.java
================================================
package com.weapp.listener;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.weapp.common.annotation.Api;
import com.weapp.entity.auth.ApiInfo;
import com.weapp.service.ApiInfoService;
import com.weapp.service.WxClubService;
/**
* Get == 1
* POST == 2
* PUT == 4
* DELETE == 8
* @author xiaoqiang
*
*/
@WebListener
@Component
public class ApiServletContextListener implements ServletContextListener {
private static ImmutableMap<String,Integer>methodMap = ImmutableMap.of("GET", 1, "POST", 2, "PUT", 4, "DELETE", 8);
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("destory");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(arg0.getServletContext());
ApiInfoService apiInfoService = wc.getBean(ApiInfoService.class);
WxClubService clubService = wc.getBean(WxClubService.class);
RequestMappingHandlerMapping rmhp = wc.getBean(RequestMappingHandlerMapping.class);
Map<RequestMappingInfo, HandlerMethod> map = rmhp.getHandlerMethods();
List<ApiInfo>apiInfolist = Lists.newArrayList();
ApiInfo apiInfo = null;
Date curDate = new Date();
for(RequestMappingInfo info : map.keySet()){
RequestMethodsRequestCondition requestMethodsRequestCondition = info.getMethodsCondition();
Set<RequestMethod>methods = requestMethodsRequestCondition.getMethods();
if(methods.size() == 0){
continue;
}
HandlerMethod handlerMethod = map.get(info);
if(!handlerMethod.hasMethodAnnotation(Api.class)){
continue;
}
Api api = handlerMethod.getMethodAnnotation(Api.class);
apiInfo = new ApiInfo();
apiInfo.setUri(info.getPatternsCondition().getPatterns().toArray()[0].toString());
apiInfo.setVersion(api.version());
apiInfo.setName(api.name());
apiInfo.setDisabled(api.disabled());
apiInfo.setAlgorithm(api.algorithm());
apiInfo.setAccessLimit(api.accessLimit());
apiInfo.setCrud(methodMap.get(methods.toArray()[0].toString()));
apiInfo.setCreateDate(curDate);
apiInfolist.add(apiInfo);
}
apiInfoService.deleteAll();
apiInfoService.saveList(apiInfolist);
clubService.deleteAll();
try {
clubService.getWxClubColumn();
} catch (IOException e) {
e.printStackTrace();
}
}
}
================================================
FILE: src/main/java/com/weapp/redis/MyRedisCacheConfig.java
================================================
package com.weapp.redis;
import java.lang.reflect.Method;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableCaching
public class MyRedisCacheConfig extends CachingConfigurerSupport {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public RedisTemplate<String, String> redisTemplate(
RedisConnectionFactory factory) {
RedisTemplate<String, String> template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public KeyGenerator wiselyKeyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@Bean
public CacheManager cacheManager(
@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
}
================================================
FILE: src/main/java/com/weapp/redis/RedisUtil.java
================================================
package com.weapp.redis;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
/**
* Jedis增删改查操作
* @author xiaoqiang
*
* @param <T>
*/
@Service
public class RedisUtil {
@Autowired(required=true)
private RedisTemplate<String,String> redisTemplate;
/**
* 添加对象
*/
public boolean add(final String key, final String value) {
redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
connection.set(
redisTemplate.getStringSerializer().serialize(key),
redisTemplate.getStringSerializer().serialize(value));
return true;
}
});
return false;
}
/**
* 添加对象
*/
public boolean add(final String key, final Long expires, final String value) {
redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
connection.setEx(
redisTemplate.getStringSerializer().serialize(key),
expires,
redisTemplate.getStringSerializer().serialize(value)
);
return true;
}
});
return false;
}
/**
* 添加Map
*/
public boolean add(final Map<String,String>map) {
Assert.notEmpty(map);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
public Boolean doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
for (Map.Entry<String, String> entry : map.entrySet()) {
byte[] key = serializer.serialize(entry.getKey());
byte[] name = serializer.serialize(entry.getValue());
connection.setNX(key, name);
}
return true;
}
}, false, true);
return result;
}
/**
* 删除对象 ,依赖key
*/
public void delete(String key) {
redisTemplate.delete(key);
}
/**
* 修改对象
*/
public boolean update(final String key,final String value) {
if (get(key) == null) {
throw new NullPointerException("数据行不存在, key = " + key);
}
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
public Boolean doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
return true;
}
});
return result;
}
/**
* 根据key获取对象
*/
public Object get(final String keyId) {
Object result = redisTemplate.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
byte[] key = serializer.serialize(keyId);
byte[] value = connection.get(key);
if (value == null) {
return null;
}
return serializer.deserialize(value);
}
});
return result;
}
}
================================================
FILE: src/main/java/com/weapp/repository/AccessLogRepository.java
================================================
package com.weapp.repository;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.weapp.entity.auth.AccessLog;
/**
* 访问日志操作
* @author xiaoqiang
*
*/
public interface AccessLogRepository extends MongoRepository<AccessLog, String> {
}
================================================
FILE: src/main/java/com/weapp/repository/ApiInfoRepository.java
================================================
package com.weapp.repository;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.weapp.entity.auth.ApiInfo;
/**
* api管理操作
* @author xiaoqiang
*
*/
public interface ApiInfoRepository extends MongoRepository<ApiInfo, String> {
ApiInfo findByName(String apiName);
}
================================================
FILE: src/main/java/com/weapp/repository/AppKeyRepository.java
================================================
package com.weapp.repository;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.weapp.entity.auth.AppKey;
/**
* appkey管理操作
* @author xiaoqiang
*
*/
public interface AppKeyRepository extends MongoRepository<AppKey, String> {
AppKey findByAppId(String appId);
}
================================================
FILE: src/main/java/com/weapp/repository/WxClubRepository.java
================================================
package com.weapp.repository;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.weapp.common.util.MongoPageable;
import com.weapp.entity.wxclub.Article;
public interface WxClubRepository extends MongoRepository<Article, String> {
List<Article> findByGroupPath(String groupPath);
List<Article> findByTitleLike(String title, MongoPageable page);
}
================================================
FILE: src/main/java/com/weapp/service/AccessLogService.java
================================================
package com.weapp.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.weapp.entity.auth.AccessLog;
import com.weapp.repository.AccessLogRepository;
@Service
@Transactional(readOnly=true)
public class AccessLogService {
@Autowired
private AccessLogRepository accessLogRepository;
@Transactional(readOnly=false)
public void save(AccessLog accessLog) {
accessLogRepository.save(accessLog);
}
}
================================================
FILE: src/main/java/com/weapp/service/ApiInfoService.java
================================================
package com.weapp.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.weapp.entity.auth.ApiInfo;
import com.weapp.repository.ApiInfoRepository;
@Transactional(readOnly=false)
@Service
public class ApiInfoService {
@Autowired
private ApiInfoRepository apiInfoRepository;
public void deleteAll(){
apiInfoRepository.deleteAll();
}
public void saveList(Iterable<ApiInfo>list){
apiInfoRepository.save(list);
}
public ApiInfo getByApiName(String apiName){
return apiInfoRepository.findByName(apiName);
}
}
================================================
FILE: src/main/java/com/weapp/service/AppKeyService.java
================================================
package com.weapp.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Update;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.weapp.entity.auth.AppKey;
import com.weapp.repository.AppKeyRepository;
@Service
@Transactional(readOnly=true)
public class AppKeyService {
@Autowired
AppKeyRepository appKeyRepository;
@Autowired
MongoTemplate mongoTemplate;
public AppKey getByAppId(String appId){
return appKeyRepository.findByAppId(appId);
}
public void update(AppKey appKey){
mongoTemplate.updateFirst(query(where("_id").is(appKey.getId())), Update.update("apis", appKey.getApis()), AppKey.class);
}
}
================================================
FILE: src/main/java/com/weapp/service/WxClubService.java
================================================
package com.weapp.service;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.weapp.common.util.MongoPageable;
import com.weapp.entity.wxclub.Article;
import com.weapp.repository.WxClubRepository;
@Service
public class WxClubService {
@Autowired
private WxClubRepository clubRepository;
private static final String CLUBHOST = "http://www.wxappclub.com";
private static final String WX_CLUB_HOST = "http://www.wxappclub.com";
private static final String[] paths = {"/column/1","/column/2","/column/3","/column/4","/column/5","/column/6","/column/7","/column/8","/column/10"};
//抓取小程序专栏内容
public void getWxClubColumn() throws IOException{
List<Article>list = Lists.newArrayList();
for(String path: paths){
Document document = Jsoup.connect(WX_CLUB_HOST + path).get();
if(document == null){
continue;
}
Elements els = document.select(".topic_list li");
if(els == null || els.size() == 0){
continue;
}
String detailPath = "";
String title = "";
String desc = "";
String content = "";
Map<String,String> authorMap = null;
String createTime = "";
String comment = "0";
String brower = "0";
String remark = "";
for(Element element : els){
Element titleEle = element.select(".topic_title a").first();
detailPath = titleEle.absUrl("href");
title = titleEle.text();
authorMap = Maps.newHashMap();
Document detailDoc = Jsoup.connect(detailPath).get();
if(detailDoc != null){
Element detailEl = detailDoc.select(".topic_content").first();
Elements imgEls = detailEl.select("img[src]");
for (Element el : imgEls) {
String imgUrl = el.attr("src");
imgUrl =CLUBHOST + "/" +imgUrl;
el.attr("src", imgUrl);
}
content = detailEl.html();
String headimg = detailDoc.select(".panel-body p .avatar").first().absUrl("src");
String nickname = detailDoc.select(".panel-body p .username").first().text();
Elements markEls = detailDoc.select(".panel-body .userremark");
if(markEls != null){
remark = markEls.first().text();
}
authorMap.put("headimg", headimg);
authorMap.put("nickname", nickname);
authorMap.put("remark", remark);
}
Elements descEls = element.select(".topic_desc");
if(descEls != null && descEls.size() > 0){
if(descEls.size() == 1){
createTime = descEls.get(0).select(".last_time").first().text();
Elements elss = descEls.get(0).select(".reply_count .count_of_visits");
if(elss != null && elss.size() == 2){
comment = elss.get(0).text().replace("评论", "").replace(" ", "");
brower = elss.get(1).text().replace("浏览", "").replace(" ", "");
}
}else {
desc = descEls.get(0).text();
createTime = descEls.get(1).select(".last_time").first().text();
Elements elss = descEls.get(1).select(".reply_count .count_of_visits");
if(elss != null && elss.size() == 2){
comment = elss.get(0).text().replace("评论", "").replace(" ", "");
brower = elss.get(1).text().replace("浏览", "").replace(" ", "");
}
}
}
Article article = new Article();
article.setAuthor(authorMap);
article.setPath(detailPath);
article.setGroupPath(path);
article.setBrowers(Integer.valueOf(brower));
article.setComments(Integer.valueOf(comment));
article.setContent(content);
article.setCreateTime(createTime);
article.setDigest(desc);
article.setTitle(title);
list.add(article);
detailPath = "";
title = "";
desc = "";
authorMap = null;
createTime = "";
comment = "0";
brower = "0";
content = "";
}
}
clubRepository.save(list);
}
/**
* 清空
*/
public void deleteAll() {
clubRepository.deleteAll();
}
/**
* 根据专栏ID搜索
* @param groupPath
* @return
*/
public List<Article> getByGroupPath(String groupPath) {
return clubRepository.findByGroupPath(groupPath);
}
/**
* 根据文章标题模糊搜索(分页)
* @param title
* @param page
* @return
*/
public List<Article> getByTitle(String title, MongoPageable page) {
return clubRepository.findByTitleLike(title,page);
}
}
================================================
FILE: src/main/java/com/weapp/service/WxService.java
================================================
package com.weapp.service;
import java.util.Map;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.weapp.common.properties.WxAuth;
import com.weapp.common.util.HttpRequest;
import com.weapp.redis.RedisUtil;
@Service
public class WxService {
@Autowired
private WxAuth wxAuth;
@Autowired
private RedisUtil redisUtil;
/**
* 根据小程序登录返回的code获取openid和session_key
* https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html?t=20161107
* @param wxcode
* @return
*/
@SuppressWarnings("unchecked")
public Map<String,Object>getWxSession(String wxCode){
StringBuffer sb = new StringBuffer();
sb.append("appid=").append(wxAuth.getAppId());
sb.append("&secret=").append(wxAuth.getSecret());
sb.append("&js_code=").append(wxCode);
sb.append("&grant_type=").append(wxAuth.getGrantType());
String res = HttpRequest.sendGet(wxAuth.getSessionHost(), sb.toString());
if(res == null || res.equals("")){
return null;
}
return JSON.parseObject(res, Map.class);
}
/**
* 缓存微信openId和session_key
* @param wxOpenId 微信用户唯一标识
* @param wxSessionKey 微信服务器会话密钥
* @param expires 会话有效期, 以秒为单位, 例如2592000代表会话有效期为30天
* @return
*/
public String create3rdSession(String wxOpenId, String wxSessionKey, Long expires){
String thirdSessionKey = RandomStringUtils.randomAlphanumeric(64);
StringBuffer sb = new StringBuffer();
sb.append(wxSessionKey).append("#").append(wxOpenId);
redisUtil.add(thirdSessionKey, expires, sb.toString());
return thirdSessionKey;
}
}
================================================
FILE: src/main/java/com/weapp/webconfig/WebConfigurer.java
================================================
/**
*
* @project xundaowei
* @filename WebConfigurer.java
* @date 2016年12月8日
* @author KeShanqiang
*
*/
package com.weapp.webconfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Component
public class WebConfigurer extends WebMvcConfigurerAdapter {
@Value("${img.local.path}")
private String imgPath;
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String localPath = "file://" + imgPath;
String osName = System.getProperty("os.name");
//判断操作系统类型
if(osName.toLowerCase().contains("win")){
localPath += "/";
}
registry.addResourceHandler("/upload/**").addResourceLocations(localPath);
}
}
================================================
FILE: src/main/java/com/weapp/websocket/ChatWebSocketHandler.java
================================================
package com.weapp.websocket;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* 微信小程序WebSocket
* @author Shanqinag Ke
* @since 2016-10-15
*/
public class ChatWebSocketHandler extends TextWebSocketHandler{
private static final Logger logger = LoggerFactory.getLogger(ChatWebSocketHandler.class);
private final static List<WebSocketSession> sessions = Collections.synchronizedList(new ArrayList<WebSocketSession>());
/**
* 处理接收文本
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String cont = message.getPayload();
if(StringUtils.isEmpty(cont)){
return;
}
//校验JSON格式
if(!cont.startsWith("{") || !cont.endsWith("}")){
return;
}
JSONObject json = JSON.parseObject(cont);
if(!json.containsKey("user") || !json.containsKey("content")){
return;
}
try {
//发送消息
sendChatMessage(json.getString("user"), json.getString("content"));
super.handleTextMessage(session, message);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
logger.debug("connect to the websocket chat success......");
sessions.add(session);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if(session.isOpen()){
session.close();
}
logger.debug("websocket chat connection closed......");
sessions.remove(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.debug("websocket chat connection closed......");
sessions.remove(session);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 判断用户是否在线
* @param userName 登录用户名
* @return
*/
public boolean isUserConnected(String userName){
if(org.springframework.util.StringUtils.isEmpty(userName)){
return false;
}
for (WebSocketSession user : sessions) {
if (user.getAttributes().get("user").equals(userName)) {
return true;
}
}
return false;
}
/**
* 发送消息
* @param userName 昵称
* @param content 发送内容
*/
public static void sendChatMessage(String userName,String content){
if(StringUtils.isEmpty(userName)){
return;
}
if (content == null){
return;
}
for (WebSocketSession session : sessions) {
if (!session.getAttributes().get("user").equals(userName)) {
if(session.isOpen()){
try{
Map<String,Object> retMap = new HashMap<String,Object>();
retMap.put("user",userName);
retMap.put("content",content);
session.sendMessage(new TextMessage(JSON.toJSONString(retMap)));
}catch (IOException ioe){
ioe.printStackTrace();
}
}
break;
}
}
}
}
================================================
FILE: src/main/java/com/weapp/websocket/WebSocketConfig.java
================================================
package com.weapp.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
/**
* 配置websocket
* @author Shanqinag Ke
* @since 2016-10-15
*/
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//注册通道
registry.addHandler(chatWebSocketHandler(),"/websocket").setAllowedOrigins("*").addInterceptors(myInterceptor());
registry.addHandler(chatWebSocketHandler(), "/sockjs/websocket").setAllowedOrigins("*").addInterceptors(myInterceptor()).withSockJS();
}
//消息处理Handler
@Bean
public ChatWebSocketHandler chatWebSocketHandler() {
return new ChatWebSocketHandler();
}
//websocket拦截器
@Bean
public WebSocketHandshakeInterceptor myInterceptor(){
return new WebSocketHandshakeInterceptor();
}
}
================================================
FILE: src/main/java/com/weapp/websocket/WebSocketHandshakeInterceptor.java
================================================
package com.weapp.websocket;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import com.alibaba.fastjson.JSON;
/**
* websocket拦截器
* @author Shanqinag Ke
* @since 2016-10-15
*/
public class WebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor implements HandshakeInterceptor{
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
//解决The extension [x-webkit-deflate-frame] is not supported问题
if(request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
}
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession();
if (session != null) {
//使用user区分WebSocketHandler,以便定向发送消息
HttpServletRequest req = servletRequest.getServletRequest();
String name = req.getParameter("name");
System.out.println(JSON.toJSONString(req.getParameterNames()));
if(null != name && !"".equals(name)){
attributes.put("user", name);
}
}
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
super.afterHandshake(request, response, wsHandler, exception);
}
}
================================================
FILE: src/main/resources/application.properties
================================================
#server
server.context-path=/weappservice
server.display-name=weappservice
server.port=8443
server.ssl.key-store=classpath:https-site.jks
server.ssl.key-store-password=xxx
server.ssl.key-password=xxx
#file
img.host=http://localhost/wximg
img.local.path=/usr/share/nginx/html/wximg
api.v1=/api/v1
#mongodb config
spring.data.mongodb.uri=mongodb://localhost:27017/test
# REDIS (RedisProperties)
spring.redis.database=0
spring.redis.host=xxx.xxx.xxx.xxx
spring.redis.password=xxx
spring.redis.port=6379
spring.redis.pool.max-idle=20
spring.redis.pool.min-idle=5
spring.redis.pool.max-active=100
spring.redis.pool.max-wait=1000
#open aop
spring.aop.auto=true
wxapp.sessionHost=https://api.weixin.qq.com/sns/jscode2session
wxapp.appId=xxx
wxapp.secret=xxx
wxapp.grantType=authorization_code
================================================
FILE: src/main/resources/error_code.properties
================================================
0=
40001=\u4E0D\u5408\u6CD5\u7684appId
40002=\u63A5\u53E3\u4E0D\u5B58\u5728
40003=\u63A5\u53E3\u88AB\u7981\u6B62\u8C03\u7528
40005=Http Method\u4E0D\u5339\u914D
40006=\u63A5\u53E3\u672A\u6388\u6743
40007=\u9891\u7387\u8D85\u9650
40008=\u7528\u6237\u8EAB\u4EFD\u5DF2\u8FC7\u671F
40010=\u8BF7\u9009\u62E9\u4E0A\u4F20\u6587\u4EF6
40011=\u4E0A\u4F20\u5931\u8D25
50010=\u4E0E\u7B2C\u4E09\u65B9\u901A\u8BAF\u5931\u8D25
50020=\u83B7\u53D6\u5FAE\u4FE1session_key\u5931\u8D25
50021=\u7528\u6237\u654F\u611F\u6570\u636E\u89E3\u5BC6\u5931\u8D25
================================================
FILE: src/main/resources/log4j.properties
================================================
log4j.rootCategory=info,stdout,logfile
#stdout configure
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p [%c] - <%m>%n
#logfile configure
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File=../logs/server.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern= %d %p [%c] - %m%n
log4j.logger.java.sql.PreparedStatement=DEBUG
================================================
FILE: src/test/java/com/weapp/ApplicationTest.java
================================================
package com.weapp;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.weapp.controller.AppUserController;
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MockServletContext.class)
@WebAppConfiguration
@TestPropertySource("classpath:application-test.properties")
public class ApplicationTest {
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new AppUserController()).build();
MockitoAnnotations.initMocks(this);
}
//测试获取数据接口
@Test
public void test() throws Exception{
RequestBuilder request = null;
request = MockMvcRequestBuilders.get("/api/v1/user/123123")
.param("appId", "test123").param("apiName", "GET_USER");
mvc.perform(request)
.andExpect(status().isOk())
.andExpect(content().string(equalTo("{\"id\":\"123123\"}")));
}
}
================================================
FILE: src/test/resources/application-test.properties
================================================
server.port=9090
server.context-path=/weappservice
server.display-name=weappservice
imgPath=http://120.26.231.155/wximg/
localPath=/usr/share/nginx/html/wximg/
api.v1=/api/v1
spring.data.mongodb.uri=mongodb://localhost:27017/test
spring.aop.auto=true
gitextract_c7s5u6lo/
├── README.md
├── pom.xml
└── src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── weapp/
│ │ ├── Application.java
│ │ ├── SwaggerConfig.java
│ │ ├── aop/
│ │ │ └── ApiAspect.java
│ │ ├── common/
│ │ │ ├── aes/
│ │ │ │ └── AES.java
│ │ │ ├── annotation/
│ │ │ │ └── Api.java
│ │ │ ├── constant/
│ │ │ │ └── ApiConstant.java
│ │ │ ├── properties/
│ │ │ │ └── WxAuth.java
│ │ │ └── util/
│ │ │ ├── HttpRequest.java
│ │ │ └── MongoPageable.java
│ │ ├── controller/
│ │ │ ├── AppUserController.java
│ │ │ ├── BaseController.java
│ │ │ ├── UploadController.java
│ │ │ ├── WxAuthController.java
│ │ │ └── WxClubController.java
│ │ ├── entity/
│ │ │ ├── app/
│ │ │ │ └── TUser.java
│ │ │ ├── auth/
│ │ │ │ ├── AccessLog.java
│ │ │ │ ├── ApiInfo.java
│ │ │ │ └── AppKey.java
│ │ │ └── wxclub/
│ │ │ └── Article.java
│ │ ├── interceptor/
│ │ │ ├── ApiInterceptor.java
│ │ │ └── ApiWebConfigure.java
│ │ ├── listener/
│ │ │ └── ApiServletContextListener.java
│ │ ├── redis/
│ │ │ ├── MyRedisCacheConfig.java
│ │ │ └── RedisUtil.java
│ │ ├── repository/
│ │ │ ├── AccessLogRepository.java
│ │ │ ├── ApiInfoRepository.java
│ │ │ ├── AppKeyRepository.java
│ │ │ └── WxClubRepository.java
│ │ ├── service/
│ │ │ ├── AccessLogService.java
│ │ │ ├── ApiInfoService.java
│ │ │ ├── AppKeyService.java
│ │ │ ├── WxClubService.java
│ │ │ └── WxService.java
│ │ ├── webconfig/
│ │ │ └── WebConfigurer.java
│ │ └── websocket/
│ │ ├── ChatWebSocketHandler.java
│ │ ├── WebSocketConfig.java
│ │ └── WebSocketHandshakeInterceptor.java
│ └── resources/
│ ├── application.properties
│ ├── error_code.properties
│ └── log4j.properties
└── test/
├── java/
│ └── com/
│ └── weapp/
│ └── ApplicationTest.java
└── resources/
└── application-test.properties
SYMBOL INDEX (125 symbols across 37 files)
FILE: src/main/java/com/weapp/Application.java
class Application (line 36) | @SpringBootApplication
method main (line 54) | public static void main(String[] args) {
method run (line 58) | @Override
method errorCodeMap (line 74) | @Bean
method servletContainer (line 79) | @Bean
method port (line 85) | @Bean
method createStandardConnector (line 89) | private Connector createStandardConnector() {
FILE: src/main/java/com/weapp/SwaggerConfig.java
class SwaggerConfig (line 14) | @Configuration
method createRestApi (line 20) | @Bean
FILE: src/main/java/com/weapp/aop/ApiAspect.java
class ApiAspect (line 10) | @Aspect
method apiAspect (line 14) | @Pointcut(value="@annotation(com.weapp.common.annotation.Api)")
method doAround (line 19) | @Around("apiAspect()")
FILE: src/main/java/com/weapp/common/aes/AES.java
class AES (line 22) | public class AES {
method decrypt (line 32) | public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) t...
method initialize (line 61) | public static void initialize(){
method generateIV (line 67) | public static AlgorithmParameters generateIV(byte[] iv) throws Exception{
FILE: src/main/java/com/weapp/common/constant/ApiConstant.java
class ApiConstant (line 8) | public class ApiConstant {
FILE: src/main/java/com/weapp/common/properties/WxAuth.java
class WxAuth (line 7) | @ConfigurationProperties(prefix = "wxapp")
FILE: src/main/java/com/weapp/common/util/HttpRequest.java
class HttpRequest (line 18) | public class HttpRequest {
method sendGet (line 28) | public static String sendGet(String url, String param) {
method sendPost (line 77) | public static String sendPost(String url, String param) {
FILE: src/main/java/com/weapp/common/util/MongoPageable.java
class MongoPageable (line 8) | public class MongoPageable implements Serializable, Pageable{
method getPageNumber (line 19) | @Override
method getPageSize (line 24) | @Override
method getOffset (line 29) | @Override
method next (line 34) | @Override
method previousOrFirst (line 39) | @Override
method first (line 44) | @Override
method hasPrevious (line 49) | @Override
method getPagenumber (line 54) | public Integer getPagenumber() {
method setPagenumber (line 58) | public void setPagenumber(Integer pagenumber) {
method getPagesize (line 62) | public Integer getPagesize() {
method setPagesize (line 66) | public void setPagesize(Integer pagesize) {
method getSort (line 70) | @Override
FILE: src/main/java/com/weapp/controller/AppUserController.java
class AppUserController (line 14) | @RestController
method get (line 18) | @Api(name=ApiConstant.GET_USER)
method post (line 25) | @Api(name=ApiConstant.POST_USER)
method put (line 32) | @Api(name=ApiConstant.PUT_USER)
method delete (line 39) | @Api(name=ApiConstant.DELETE_USER)
FILE: src/main/java/com/weapp/controller/BaseController.java
class BaseController (line 10) | @Component
method rtnParam (line 21) | protected Map<String,Object> rtnParam(Integer errorCode,Object data) {
FILE: src/main/java/com/weapp/controller/UploadController.java
class UploadController (line 21) | @RestController
method uploadImage (line 35) | @Api(name = ApiConstant.UPLOAD_IMAGE)
FILE: src/main/java/com/weapp/controller/WxAuthController.java
class WxAuthController (line 30) | @RestController
method createSssion (line 42) | @ApiOperation(value = "获取sessionId", notes = "小用户允许登录后,使用code 换取 sessi...
method checkUserInfo (line 71) | @Api(name = ApiConstant.WX_CHECK_USER)
method decodeUserInfo (line 98) | @Api(name = ApiConstant.WX_DECODE_USERINFO)
FILE: src/main/java/com/weapp/controller/WxClubController.java
class WxClubController (line 24) | @RestController
method getArticles (line 35) | @Api(name = ApiConstant.WX_CLUB_ARTICLES)
method getArticles (line 47) | @Api(name = ApiConstant.WX_CLUB_SEARCH)
FILE: src/main/java/com/weapp/entity/app/TUser.java
class TUser (line 14) | @Document(collection="t_users")
FILE: src/main/java/com/weapp/entity/auth/AccessLog.java
class AccessLog (line 16) | @Document(collection="t_access_logs")
method AccessLog (line 36) | public AccessLog(String apiName, String uri, Date accessDate, String r...
FILE: src/main/java/com/weapp/entity/auth/ApiInfo.java
class ApiInfo (line 16) | @Document(collection="t_apis")
method ApiInfo (line 44) | public ApiInfo(String name,String uri, Integer accessLimit, String ver...
FILE: src/main/java/com/weapp/entity/auth/AppKey.java
class AppKey (line 17) | @Document(collection="t_appkeys")
method AppKey (line 39) | public AppKey(String appId, String secretKey, Date createDate, Date va...
FILE: src/main/java/com/weapp/entity/wxclub/Article.java
class Article (line 13) | @Document(collection="t_articles")
FILE: src/main/java/com/weapp/interceptor/ApiInterceptor.java
class ApiInterceptor (line 28) | public class ApiInterceptor implements HandlerInterceptor {
method afterCompletion (line 39) | @Override
method postHandle (line 68) | @Override
method preHandle (line 74) | @Override
method getResStr (line 156) | private String getResStr(String errorCode){
FILE: src/main/java/com/weapp/interceptor/ApiWebConfigure.java
class ApiWebConfigure (line 13) | @Configuration
method addInterceptors (line 15) | @Override
method getApiInterceptor (line 20) | @Bean
FILE: src/main/java/com/weapp/listener/ApiServletContextListener.java
class ApiServletContextListener (line 36) | @WebListener
method contextDestroyed (line 40) | @Override
method contextInitialized (line 45) | @Override
FILE: src/main/java/com/weapp/redis/MyRedisCacheConfig.java
class MyRedisCacheConfig (line 21) | @Configuration
method redisTemplate (line 25) | @SuppressWarnings({ "rawtypes", "unchecked" })
method wiselyKeyGenerator (line 44) | @Bean
method cacheManager (line 60) | @Bean
FILE: src/main/java/com/weapp/redis/RedisUtil.java
class RedisUtil (line 19) | @Service
method add (line 27) | public boolean add(final String key, final String value) {
method add (line 43) | public boolean add(final String key, final Long expires, final String ...
method add (line 61) | public boolean add(final Map<String,String>map) {
method delete (line 81) | public void delete(String key) {
method update (line 88) | public boolean update(final String key,final String value) {
method get (line 107) | public Object get(final String keyId) {
FILE: src/main/java/com/weapp/repository/AccessLogRepository.java
type AccessLogRepository (line 11) | public interface AccessLogRepository extends MongoRepository<AccessLog, ...
FILE: src/main/java/com/weapp/repository/ApiInfoRepository.java
type ApiInfoRepository (line 12) | public interface ApiInfoRepository extends MongoRepository<ApiInfo, Stri...
method findByName (line 14) | ApiInfo findByName(String apiName);
FILE: src/main/java/com/weapp/repository/AppKeyRepository.java
type AppKeyRepository (line 11) | public interface AppKeyRepository extends MongoRepository<AppKey, String> {
method findByAppId (line 13) | AppKey findByAppId(String appId);
FILE: src/main/java/com/weapp/repository/WxClubRepository.java
type WxClubRepository (line 10) | public interface WxClubRepository extends MongoRepository<Article, Strin...
method findByGroupPath (line 12) | List<Article> findByGroupPath(String groupPath);
method findByTitleLike (line 14) | List<Article> findByTitleLike(String title, MongoPageable page);
FILE: src/main/java/com/weapp/service/AccessLogService.java
class AccessLogService (line 10) | @Service
method save (line 17) | @Transactional(readOnly=false)
FILE: src/main/java/com/weapp/service/ApiInfoService.java
class ApiInfoService (line 10) | @Transactional(readOnly=false)
method deleteAll (line 16) | public void deleteAll(){
method saveList (line 20) | public void saveList(Iterable<ApiInfo>list){
method getByApiName (line 24) | public ApiInfo getByApiName(String apiName){
FILE: src/main/java/com/weapp/service/AppKeyService.java
class AppKeyService (line 16) | @Service
method getByAppId (line 24) | public AppKey getByAppId(String appId){
method update (line 28) | public void update(AppKey appKey){
FILE: src/main/java/com/weapp/service/WxClubService.java
class WxClubService (line 20) | @Service
method getWxClubColumn (line 29) | public void getWxClubColumn() throws IOException{
method deleteAll (line 128) | public void deleteAll() {
method getByGroupPath (line 136) | public List<Article> getByGroupPath(String groupPath) {
method getByTitle (line 145) | public List<Article> getByTitle(String title, MongoPageable page) {
FILE: src/main/java/com/weapp/service/WxService.java
class WxService (line 14) | @Service
method getWxSession (line 26) | @SuppressWarnings("unchecked")
method create3rdSession (line 46) | public String create3rdSession(String wxOpenId, String wxSessionKey, L...
FILE: src/main/java/com/weapp/webconfig/WebConfigurer.java
class WebConfigurer (line 17) | @Component
method addResourceHandlers (line 22) | public void addResourceHandlers(ResourceHandlerRegistry registry) {
FILE: src/main/java/com/weapp/websocket/ChatWebSocketHandler.java
class ChatWebSocketHandler (line 27) | public class ChatWebSocketHandler extends TextWebSocketHandler{
method handleTextMessage (line 35) | @Override
method afterConnectionEstablished (line 59) | @Override
method handleTransportError (line 65) | @Override
method afterConnectionClosed (line 74) | @Override
method supportsPartialMessages (line 80) | @Override
method isUserConnected (line 90) | public boolean isUserConnected(String userName){
method sendChatMessage (line 107) | public static void sendChatMessage(String userName,String content){
FILE: src/main/java/com/weapp/websocket/WebSocketConfig.java
class WebSocketConfig (line 16) | @Configuration
method registerWebSocketHandlers (line 21) | @Override
method chatWebSocketHandler (line 28) | @Bean
method myInterceptor (line 34) | @Bean
FILE: src/main/java/com/weapp/websocket/WebSocketHandshakeInterceptor.java
class WebSocketHandshakeInterceptor (line 22) | public class WebSocketHandshakeInterceptor extends HttpSessionHandshakeI...
method beforeHandshake (line 24) | @Override
method afterHandshake (line 48) | @Override
FILE: src/test/java/com/weapp/ApplicationTest.java
class ApplicationTest (line 24) | @ActiveProfiles("test")
method setUp (line 31) | @Before
method test (line 37) | @Test
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (84K chars).
[
{
"path": "README.md",
"chars": 2388,
"preview": "# springboot-weapp-demo\n微信小程序服务端接口,支持普通Http请求、上传文件、长连接,微信登录及敏感数据解密。后台服务使用springboot框架搭建,mongodb做数据库,redis做缓存。\n\n运行环境:JDK8"
},
{
"path": "pom.xml",
"chars": 4108,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
},
{
"path": "src/main/java/com/weapp/Application.java",
"chars": 3211,
"preview": "package com.weapp;\n\nimport java.io.IOException;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\ni"
},
{
"path": "src/main/java/com/weapp/SwaggerConfig.java",
"chars": 1433,
"preview": "package com.weapp;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annota"
},
{
"path": "src/main/java/com/weapp/aop/ApiAspect.java",
"chars": 805,
"preview": "package com.weapp.aop;\n\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport o"
},
{
"path": "src/main/java/com/weapp/common/aes/AES.java",
"chars": 2276,
"preview": "package com.weapp.common.aes;\n\nimport java.io.UnsupportedEncodingException;\nimport java.security.AlgorithmParameters;\nim"
},
{
"path": "src/main/java/com/weapp/common/annotation/Api.java",
"chars": 618,
"preview": "package com.weapp.common.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\ni"
},
{
"path": "src/main/java/com/weapp/common/constant/ApiConstant.java",
"chars": 910,
"preview": "package com.weapp.common.constant;\n\n/**\n * API常量\n * @author xiaoqiang\n *\n */\npublic class ApiConstant {\n\t/*测试*/\t\n\tpublic"
},
{
"path": "src/main/java/com/weapp/common/properties/WxAuth.java",
"chars": 318,
"preview": "package com.weapp.common.properties;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\nimpor"
},
{
"path": "src/main/java/com/weapp/common/util/HttpRequest.java",
"chars": 2956,
"preview": "/**\n *\n * @project ApiService\n * @filename HttpRequest.java\n * @date 2015年8月16日\n * @author KeShanqiang\n *\n */\n\npackage c"
},
{
"path": "src/main/java/com/weapp/common/util/MongoPageable.java",
"chars": 1140,
"preview": "package com.weapp.common.util;\n\nimport java.io.Serializable;\n\nimport org.springframework.data.domain.Pageable;\nimport or"
},
{
"path": "src/main/java/com/weapp/controller/AppUserController.java",
"chars": 1633,
"preview": "package com.weapp.controller;\n\nimport java.util.Map;\n\nimport org.springframework.web.bind.annotation.PathVariable;\nimpor"
},
{
"path": "src/main/java/com/weapp/controller/BaseController.java",
"chars": 723,
"preview": "package com.weapp.controller;\n\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimp"
},
{
"path": "src/main/java/com/weapp/controller/UploadController.java",
"chars": 1724,
"preview": "package com.weapp.controller;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.Map;\n\nimport org.apache"
},
{
"path": "src/main/java/com/weapp/controller/WxAuthController.java",
"chars": 4738,
"preview": "package com.weapp.controller;\n\nimport java.io.UnsupportedEncodingException;\nimport java.security.InvalidAlgorithmParamet"
},
{
"path": "src/main/java/com/weapp/controller/WxClubController.java",
"chars": 1901,
"preview": "package com.weapp.controller;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.an"
},
{
"path": "src/main/java/com/weapp/entity/app/TUser.java",
"chars": 913,
"preview": "package com.weapp.entity.app;\n\nimport org.springframework.data.annotation.Id;\nimport org.springframework.data.mongodb.co"
},
{
"path": "src/main/java/com/weapp/entity/auth/AccessLog.java",
"chars": 921,
"preview": "package com.weapp.entity.auth;\n\nimport java.util.Date;\n\nimport org.springframework.data.annotation.Id;\nimport org.spring"
},
{
"path": "src/main/java/com/weapp/entity/auth/ApiInfo.java",
"chars": 1091,
"preview": "package com.weapp.entity.auth;\n\nimport java.util.Date;\n\nimport org.springframework.data.annotation.Id;\nimport org.spring"
},
{
"path": "src/main/java/com/weapp/entity/auth/AppKey.java",
"chars": 1132,
"preview": "package com.weapp.entity.auth;\n\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.data.annotation"
},
{
"path": "src/main/java/com/weapp/entity/wxclub/Article.java",
"chars": 667,
"preview": "package com.weapp.entity.wxclub;\n\nimport java.util.Map;\n\nimport org.springframework.data.annotation.Id;\nimport org.sprin"
},
{
"path": "src/main/java/com/weapp/interceptor/ApiInterceptor.java",
"chars": 4663,
"preview": "package com.weapp.interceptor;\n\nimport java.io.PrintWriter;\nimport java.util.Date;\nimport java.util.Map;\n\nimport javax.s"
},
{
"path": "src/main/java/com/weapp/interceptor/ApiWebConfigure.java",
"chars": 669,
"preview": "package com.weapp.interceptor;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.a"
},
{
"path": "src/main/java/com/weapp/listener/ApiServletContextListener.java",
"chars": 3175,
"preview": "package com.weapp.listener;\n\nimport java.io.IOException;\nimport java.util.Date;\nimport java.util.List;\nimport java.util."
},
{
"path": "src/main/java/com/weapp/redis/MyRedisCacheConfig.java",
"chars": 2297,
"preview": "package com.weapp.redis;\n\nimport java.lang.reflect.Method;\n\nimport org.springframework.cache.CacheManager;\nimport org.sp"
},
{
"path": "src/main/java/com/weapp/redis/RedisUtil.java",
"chars": 3440,
"preview": "package com.weapp.redis;\n\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport o"
},
{
"path": "src/main/java/com/weapp/repository/AccessLogRepository.java",
"chars": 267,
"preview": "package com.weapp.repository;\n\nimport org.springframework.data.mongodb.repository.MongoRepository;\n\nimport com.weapp.ent"
},
{
"path": "src/main/java/com/weapp/repository/ApiInfoRepository.java",
"chars": 301,
"preview": "package com.weapp.repository;\n\nimport org.springframework.data.mongodb.repository.MongoRepository;\n\nimport com.weapp.ent"
},
{
"path": "src/main/java/com/weapp/repository/AppKeyRepository.java",
"chars": 298,
"preview": "package com.weapp.repository;\n\nimport org.springframework.data.mongodb.repository.MongoRepository;\n\nimport com.weapp.ent"
},
{
"path": "src/main/java/com/weapp/repository/WxClubRepository.java",
"chars": 408,
"preview": "package com.weapp.repository;\n\nimport java.util.List;\n\nimport org.springframework.data.mongodb.repository.MongoRepositor"
},
{
"path": "src/main/java/com/weapp/service/AccessLogService.java",
"chars": 548,
"preview": "package com.weapp.service;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.st"
},
{
"path": "src/main/java/com/weapp/service/ApiInfoService.java",
"chars": 666,
"preview": "package com.weapp.service;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.st"
},
{
"path": "src/main/java/com/weapp/service/AppKeyService.java",
"chars": 971,
"preview": "package com.weapp.service;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.da"
},
{
"path": "src/main/java/com/weapp/service/WxClubService.java",
"chars": 4484,
"preview": "package com.weapp.service;\n\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.jsoup.J"
},
{
"path": "src/main/java/com/weapp/service/WxService.java",
"chars": 1648,
"preview": "package com.weapp.service;\n\nimport java.util.Map;\n\nimport org.apache.commons.lang3.RandomStringUtils;\nimport org.springf"
},
{
"path": "src/main/java/com/weapp/webconfig/WebConfigurer.java",
"chars": 883,
"preview": "/**\n *\n * @project xundaowei\n * @filename WebConfigurer.java\n * @date 2016年12月8日\n * @author KeShanqiang\n *\n */\n\npackage "
},
{
"path": "src/main/java/com/weapp/websocket/ChatWebSocketHandler.java",
"chars": 3305,
"preview": "package com.weapp.websocket;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimpo"
},
{
"path": "src/main/java/com/weapp/websocket/WebSocketConfig.java",
"chars": 1336,
"preview": "package com.weapp.websocket;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.ann"
},
{
"path": "src/main/java/com/weapp/websocket/WebSocketHandshakeInterceptor.java",
"chars": 2195,
"preview": "package com.weapp.websocket;\n\nimport java.util.Map;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet."
},
{
"path": "src/main/resources/application.properties",
"chars": 793,
"preview": "#server\nserver.context-path=/weappservice\nserver.display-name=weappservice\n\nserver.port=8443\nserver.ssl.key-store=classp"
},
{
"path": "src/main/resources/error_code.properties",
"chars": 536,
"preview": "0=\n40001=\\u4E0D\\u5408\\u6CD5\\u7684appId\n40002=\\u63A5\\u53E3\\u4E0D\\u5B58\\u5728\n40003=\\u63A5\\u53E3\\u88AB\\u7981\\u6B62\\u8C03\\u"
},
{
"path": "src/main/resources/log4j.properties",
"chars": 556,
"preview": "log4j.rootCategory=info,stdout,logfile\r\n#stdout configure\r\nlog4j.appender.stdout=org.apache.log4j.ConsoleAppender\r\nlog4j"
},
{
"path": "src/test/java/com/weapp/ApplicationTest.java",
"chars": 1797,
"preview": "package com.weapp;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.resu"
},
{
"path": "src/test/resources/application-test.properties",
"chars": 250,
"preview": "server.port=9090\nserver.context-path=/weappservice\nserver.display-name=weappservice\nimgPath=http://120.26.231.155/wximg/"
}
]
About this extraction
This page contains the full source code of the nosqlcoco/springboot-weapp-demo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (69.4 KB), approximately 19.5k tokens, and a symbol index with 125 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.