注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
String value() default "";
}
@Target:用于描述注解的使用范围(注解可以用在什么地方)
ElementType.TYPE:类、接口(包括注解类型) 或enum声明。
@Retention:注解的生命周期,用于表示该注解会在什么时期保留。
RetentionPolicy.RUNTIME:运行时保留,这样就可以通过反射获得了。
@Documented:表示该注解会被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。
前提需求:在公众号中上传图片时,图片上传到微信的服务器中,并且会返回mediaId。这时我们拿到mediaid到微信服务器中将图片下载并上传到自己的服务器中。例如:当前端同学传给后端用户头像时候,我们希望进入controller时候,这些流程全部已经实现。在业务层只是单纯的执行所需要的业务逻辑。
实现内容:前端 cheadimg=mediaid【微信给的图片id】–> 进入controller时,cheadimg=http://zhang.com/001.jpg【自己服务器中的图片地址】
废话不多说了,直接贴上相关代码:
a:自定义一个注解
/**
* 设置微信图片注解
* Retention:保留至运行时,通过反射去获取注解信息。
* Target:方法级别的
* Created by zhang on 2018/5/10.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface SetWeChatImg {
String value() default "";
}
b:添加拦截器,拦截每个方法、类中是否添加注解@SetWeChatImg
/**
* 在WebMvcConfigurerAdapter里添加拦截器
* Created by zhang on 2018/5/10.
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
/**
* 在Spring添加拦截器之前先自己创建一下这个WeChatImgInterceptor
*/
@Bean
public WeChatImgInterceptor weChatImgInterceptor() {
return new WeChatImgInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则
registry.addInterceptor(weChatImgInterceptor()).addPathPatterns("/control/loan/wechatimg/*");
super.addInterceptors(registry);
}
}
/**
* Created by zhang on 2018/5/10.
*/
@Component
public class WeChatImgInterceptor extends HandlerInterceptorAdapter {
@Autowired
WeChatImgUtil util;
/**
* 微信图片
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
SetWeChatImg setWeChatImg = method.getAnnotation(SetWeChatImg.class);
if (setWeChatImg != null) {
ParameterRequestWrapper requestWrapper = (ParameterRequestWrapper) request;
util.wehatImg(requestWrapper);
}
return true;
}
}
c:实现功能的一个util类
/**
* 微信图片从服务器上获取并下载到自己服务器
* Created by zhang on 2018/5/8.
*/
@Component
public class WeChatImgUtil {
private static Logger logger = LoggerFactory.getLogger(WeChatImgUtil.class);
public static final String APPNAME = "zhang";
@Autowired
Environment evn;
@Autowired
MemCachedClient memCachedClient;
@Autowired
RedisTemplate redisTemplate;
public void wehatImg(ParameterRequestWrapper requestWrapper) throws Exception {
logger.info("wehatImg:上传微信图片开始---------");
LocalDate today = LocalDate.now();
int year = today.getYear();
int month = today.getMonthValue();
int date = today.getDayOfMonth();
//dir =2018/5/8/
String dir = new StringBuilder().append(year).append(File.separator).append(month).append(File.separator).append(date).append("/").toString();
logger.info("dir={}", dir);
Map map = new HashMap<>();
map.put("cheadimg", requestWrapper.getParameter("cheadimg"));
map.put("cidcardface", requestWrapper.getParameter("cidcardface"));
map.put("cidcardback", requestWrapper.getParameter("cidcardback"));
Set> entries = map.entrySet();
Iterator> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
if (entry.getValue() != null) {
String mediaId = entry.getValue().trim();
if (mediaId.indexOf("http:") < 0) {
//下载图片都用loan的appId
String imgName = downloadImg(mediaId, dir, entry.getKey());
if (imgName != null) {
requestWrapper.setParameter(entry.getKey(), imgName);
} else {
requestWrapper.setParameter("errcode", "-1");
requestWrapper.setParameter("errdesc","图片上传失败");
}
logger.info("imgName---------" + imgName);
}
}
}
}
/**
* 根据mediaId下载图片,并返回图片名称
*
* @param mediaId
* @param dirStr
* @throws IOException
*/
public String downloadImg(String mediaId, String dirStr, String fileType) throws IOException {
String uploadPath = "/Users/zhang/export/img/";
String downLoadPath = "/Users/zhang/export/img/";
logger.info("uploadPath = {}, downLoadPath = {}", uploadPath, downLoadPath);
File dir = new File(uploadPath, dirStr);
if (!dir.exists()) {
dir.mkdirs();
}
String imageName = UUID.randomUUID().toString() + ".jpg";
String url = new StringBuilder("http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=")
.append(getAccess_token())
.append("&media_id=")
.append(mediaId)
.toString();
System.out.println("图片下载地址:" + url);
DataInputStream dataInputStream = new DataInputStream(new URL(url).openStream());
FileOutputStream fileOutputStream = new FileOutputStream(new File(dir, imageName));
byte[] buffer = new byte[1024];
int length;
int i = 0;
while ((length = dataInputStream.read(buffer)) > 0) {
i++;
//先读取,判断大小,是否超过1k,小于1k为json错误
if (i == 1 && length < buffer.length) {
String respStr = new String(buffer, Charset.forName("UTF-8"));
logger.error("从微信端下载图片失败:" + respStr);
return null;
}
fileOutputStream.write(buffer, 0, length);
}
dataInputStream.close();
fileOutputStream.close();
return downLoadPath + dirStr + imageName;
}
/**
* 获取微信token【先从memcached中获取,如果为null,redis中获取】
*
* @return
*/
public String getAccess_token() {
String key = APPNAME + "_access_token";
String access_token = (String) memCachedClient.get(key);
if (null == access_token) {
access_token = redisTemplate.opsForValue().get(key);
if (null == access_token) {
logger.error("error报警:memcached和redis中均没有获取到微信token");
}
}
return access_token;
}
}
d:模拟测试
@RequestMapping("/control/loan/wechatimg/test")
@SetWeChatImg
public JSONObject annotationTest(LendUserBean bean) {
System.out.println("我是注解测试~~~~~");
return null;
}