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+
注意:如果你是本地运行,需要修改为你本地对应的主机和端口。
长连接需使用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){
}
});
```
| 状态码(errcode) |
说明(msg) |
| 0 |
图片路径 |
| 40010 |
请选择上传文件! |
| 40011 |
文件上传失败 |
#### 三、测试小程序websocket相关接口
```javascript
//发起websocket连接
wx.connectSocket({
url: 'ws://localhost:9090/weappservice/websocket?name=xiaoqiang',
//这里写了参数,但是参数没有发送出去,大家可以试试,已经邮件反馈微信团队了,等待回复。所以把参数拼接在url后面。
data: {
'name1': 'xiaoqiang1'
}
}),
//监听打开事件
wx.onSocketOpen(function(res) {
console.log('WebSocket连接已打开!');
}),
//接收消息,接收的消息是json字符串,需要JSON.parse转成JSON对象
wx.onSocketMessage(function(res){
var data = JSON.parse(res.data);
console.log(data);
}),
//发送消息,消息对象属性key(user和content)不能自定义。
wx.sendSocketMessage({
data: JSON.stringify({
user: 'xiaoqaing',
content: 'Hi, My name is xiaoqiang'
}),
success: function(res){
console.log('消息发送成功!')
}
})
```
我的微信小程序DEMO:[weixin_smallexe](https://github.com/cocoli/weixin_smallexe)
PS:我的公众号:

================================================
FILE: pom.xml
================================================
4.0.0
com.wxapp
wxapp
1.0.0
jar
wxchatdemo1.0.0
wechat app API Project
org.springframework.boot
spring-boot-starter-parent
1.4.2.RELEASE
UTF-8
1.8
1.54
2.2.2
1.8.3
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-websocket
org.springframework.boot
spring-boot-starter-data-mongodb
org.springframework.boot
spring-boot-starter-redis
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-starter-web
com.alibaba
fastjson
1.2.31
org.projectlombok
lombok
com.google.guava
guava
19.0
commons-logging
commons-logging
1.2
org.apache.commons
commons-lang3
3.4
org.apache.httpcomponents
httpclient
org.apache.httpcomponents
httpcore
commons-codec
commons-codec
org.bouncycastle
bcprov-jdk15on
${bcprov.version}
io.springfox
springfox-swagger2
${swagger2.version}
io.springfox
springfox-swagger-ui
${swagger2.version}
org.jsoup
jsoup
${jsoup.version}
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-logging
org.springframework.boot
spring-boot-maven-plugin
================================================
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 ImmutableMaperrorCodeMap = 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> apiMap = Maps.newHashMap();
for(String apiName : apiNames){
MaptmpMap = new HashMap();
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 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 get(@PathVariable String id){
ImmutableMap 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 post(@PathVariable String id){
ImmutableMap 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 put(@PathVariable String id){
ImmutableMap 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 delete(@PathVariable String id){
ImmutableMap 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 errorCodeMap;
/**
* 接口数据返回
* @param errorCode
* @param data
* @return
*/
protected Map 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 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 createSssion(@RequestParam(required = true,value = "code")String wxCode){
Map 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 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 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 MapgetArticles(@PathVariable String id,@PathVariable Integer page){
Listlist = 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 MapgetArticles(@PathVariable(value="pageNo",required=false) Integer pageNo,
@RequestParam(required=false,value="text",defaultValue="")String searchText){
MongoPageable page = new MongoPageable();
page.setPagenumber(pageNo);
Listlist = 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> apis;
public AppKey(String appId, String secretKey, Date createDate, Date validDate, String appGrade, Boolean disabled,
Map> 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 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 ImmutableMapmethodMap = ImmutableMap.of("GET", 1, "POST", 2, "PUT", 4, "DELETE", 8);
@Autowired
private AppKeyService appKeyService;
@Autowired
private ApiInfoService apiInfoService;
@Autowired
private ImmutableMap 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 params = request.getParameterMap();
if (params != null && params.size() > 0) {
for(Map.Entry 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>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;
}
//调用次数是否超出上限;
MapmethodInfo = 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 ImmutableMapmethodMap = 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 map = rmhp.getHandlerMethods();
ListapiInfolist = Lists.newArrayList();
ApiInfo apiInfo = null;
Date curDate = new Date();
for(RequestMappingInfo info : map.keySet()){
RequestMethodsRequestCondition requestMethodsRequestCondition = info.getMethodsCondition();
Setmethods = 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 redisTemplate(
RedisConnectionFactory factory) {
RedisTemplate 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
*/
@Service
public class RedisUtil {
@Autowired(required=true)
private RedisTemplate redisTemplate;
/**
* 添加对象
*/
public boolean add(final String key, final String value) {
redisTemplate.execute(new RedisCallback