master c843e2b69204 cached
44 files
69.4 KB
19.5k tokens
125 symbols
1 requests
Download .txt
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:我的公众号:

![](https://github.com/cocoli/weixin_smallexe/blob/master/screenshot/dingyuhao.JPG?raw=true)


================================================
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
Download .txt
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
Download .txt
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.

Copied to clipboard!