使用外观模式(Facade)调用微信企业号API
2015-11-30 15:24
711 查看
在开发微信企业号时免不了调用大量的 API, 那么外观模式或许是个不错的选择。
WxApiFacade
可以看到以上的每一个方法背后就是一个微信企业号api的调用, 现在以调用第三方授权获得永久授权码为例,讲解代码。
RequestPermanentAuthCodeAPI
我们看到在构造函数里面初始化了所需要的数据,在getPostBody中初始化了所需要post的数据。
使用fluent发送http请求。
WxApiFacade
package com.augmentum.wechatee.framework.wxapi; import java.io.File; import java.sql.Timestamp; import java.util.Date; import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.augmentum.wechatee.framework.data.base.WxDepartmentListJson; import com.augmentum.wechatee.framework.data.base.WxDepartmentUserListJson; import com.augmentum.wechatee.framework.data.base.WxTagListJson; import com.augmentum.wechatee.framework.data.base.WxTagUserListJson; import com.augmentum.wechatee.framework.data.models.Log; import com.augmentum.wechatee.framework.data.repositories.LogRepository; import com.augmentum.wechatee.framework.data.to.AuthCorpAgentInfoTO; import com.augmentum.wechatee.framework.data.to.CorporationAccessTokenTO; import com.augmentum.wechatee.framework.data.to.MaterialTO; import com.augmentum.wechatee.framework.data.to.OAuthTo; import com.augmentum.wechatee.framework.data.to.PermanentAuthCodeTO; import com.augmentum.wechatee.framework.data.to.PreAuthCodeRecordTO; import com.augmentum.wechatee.framework.data.to.SuiteAccessTokenTO; import com.augmentum.wechatee.framework.data.to.WxCallbackReponseTO; import com.augmentum.wechatee.framework.data.to.WxDepartmentListTO; import com.augmentum.wechatee.framework.data.to.WxDepartmentUserListTO; import com.augmentum.wechatee.framework.data.to.WxMaterialListTO; import com.augmentum.wechatee.framework.data.to.WxMenuContentTo; import com.augmentum.wechatee.framework.data.to.WxMessageTO; import com.augmentum.wechatee.framework.data.to.WxPermanentMaterialTO; import com.augmentum.wechatee.framework.data.to.WxRequestMaterialCountTO; import com.augmentum.wechatee.framework.data.to.WxTagListTO; import com.augmentum.wechatee.framework.data.to.WxTagUserListTO; import com.augmentum.wechatee.framework.data.vo.WxDeletePermanentResponseVO; import com.augmentum.wechatee.framework.data.vo.WxUploadPermanentMaterialResponseJsonVO; import com.augmentum.wechatee.framework.wxapi.exceptions.WxApiException; @Component public class WxApiFacade implements LogObserverInterface{ //terry add @Autowired private LogRepository logRepository; // //////////////////////////////////////////////////////////////////////// // // Suite Access Token // // //////////////////////////////////////////////////////////////////////// public SuiteAccessTokenTO requestSuiteAccessToken(String suiteId, String suiteSecret, String suiteTicket) throws WxApiException { RequestSuiteAccessTokenAPI api = new RequestSuiteAccessTokenAPI(suiteId, suiteSecret, suiteTicket); api.addObserver(this); WxSuiteAccessTokenResponse response = RequestSuiteAccessTokenAPI.request(api, WxSuiteAccessTokenResponse.class); if (response == null) { throw new WxApiException(api); } return transferObjectFromWxResponse(response, suiteId); } private SuiteAccessTokenTO transferObjectFromWxResponse(WxSuiteAccessTokenResponse response, String suiteId) { SuiteAccessTokenTO to = new SuiteAccessTokenTO(); to.setAccessToken(response.getSuiteAccessToken()); to.setExpiresIn(response.getExpiresIn()); to.setSuiteId(suiteId); to.setCreatedDate(new Date()); to.setLastModifiedDate(new Date()); return to; } // //////////////////////////////////////////////////////////////////////// // // Suite Access Token // // //////////////////////////////////////////////////////////////////////// public PreAuthCodeRecordTO requestPreAuthCode(String suiteId, String suiteAccessToken, int[] appIds) throws WxApiException { RequestGetPreAuthCodeAPI api = new RequestGetPreAuthCodeAPI(suiteId, suiteAccessToken, appIds); api.addObserver(this); WxPreAuthCodeResponse response = RequestGetPreAuthCodeAPI.request(api, WxPreAuthCodeResponse.class); return transferObjectFromWxResponse(response, suiteId); } private PreAuthCodeRecordTO transferObjectFromWxResponse(WxPreAuthCodeResponse response, String suiteId) { PreAuthCodeRecordTO to = new PreAuthCodeRecordTO(); to.setId(0); to.setCreatedDate(new Date()); to.setLastModifiedDate(new Date()); to.setNotes(""); to.setPreAuthCode(response.getPreAuthCode()); to.setSuiteId(suiteId); to.setExpiresIn(response.getExpiresIn()); return to; } // //////////////////////////////////////////////////////////////////////// // // Permanent authentication code // // //////////////////////////////////////////////////////////////////////// public PermanentAuthCodeTO requestPermanentAuthCode(String suiteId, String preAuthCode, String suiteAccessToken) throws WxApiException { RequestPermanentAuthCodeAPI api = new RequestPermanentAuthCodeAPI(suiteId, preAuthCode, suiteAccessToken); api.addObserver(this); PermanentAuthCodeTO response = RequestPermanentAuthCodeAPI.request(api, PermanentAuthCodeTO.class); return response; } // //////////////////////////////////////////////////////////////////////// // // Corporation Access Token // // //////////////////////////////////////////////////////////////////////// public CorporationAccessTokenTO requestCorporationAccessToken(String suiteId, String authCorpId, String permanentCode, String suiteAccessToken) throws WxApiException { RequestCorporationAccessTokenAPI api = new RequestCorporationAccessTokenAPI(suiteId, authCorpId, permanentCode, suiteAccessToken); api.addObserver(this); WxCorporationAccessTokenJson response = RequestCorporationAccessTokenAPI.request(api, WxCorporationAccessTokenJson.class); return transferObjectFromWxResponse(response, authCorpId); } private CorporationAccessTokenTO transferObjectFromWxResponse(WxCorporationAccessTokenJson response, String corporationId) { CorporationAccessTokenTO to = new CorporationAccessTokenTO(); to.setAccessToken(response.getAccessToken()); to.setCorporationId(corporationId); to.setCreatedDate(response.getCreatedDate()); to.setExpiresIn(response.getExpiresIn()); to.setLastModifiedDate(new Date()); return to; } // //////////////////////////////////////////////////////////////////////// // // Request enterprise Wechat department list // // //////////////////////////////////////////////////////////////////////// public WxDepartmentListTO requestCorporationDepartmentList(String corporationAccessToken) throws WxApiException { RequestDepartmentListAPI api = new RequestDepartmentListAPI(corporationAccessToken, 1); api.addObserver(this); WxDepartmentListJson response = RequestDepartmentListAPI.request(api, WxDepartmentListJson.class); return transferObjectFromWxResponse(response); } private WxDepartmentListTO transferObjectFromWxResponse(WxDepartmentListJson response) { WxDepartmentListTO to = new WxDepartmentListTO(); to.setErrMsg(response.getErrMsg()); to.setErrorCode(response.getErrorCode()); to.setDepartments(response.getDepartments()); return to; } // //////////////////////////////////////////////////////////////////////// // // Request enterprise Wechat tag list // // //////////////////////////////////////////////////////////////////////// public WxTagListTO requestCorporationTagList(String corporationAccessToken) throws WxApiException { RequestTagListAPI api = new RequestTagListAPI(corporationAccessToken); api.addObserver(this); WxTagListJson response = RequestTagListAPI.request(api, WxTagListJson.class); return transferObjectFromWxResponse(response); } private WxTagListTO transferObjectFromWxResponse(WxTagListJson response) { WxTagListTO to = new WxTagListTO(); if(response != null){ to.setErrMsg(response.getErrMsg()); to.setErrorCode(response.getErrorCode()); if(response.getTags() != null){ to.setTags(response.getTags()); } } return to; } // //////////////////////////////////////////////////////////////////////// // // Request enterprise Wechat tag user list // // //////////////////////////////////////////////////////////////////////// public WxTagUserListTO requestCorporationTagUserList(String corporationAccessToken, String tagid) throws WxApiException { RequestTagUserListAPI api = new RequestTagUserListAPI(corporationAccessToken, tagid); api.addObserver(this); WxTagUserListJson response = RequestTagUserListAPI.request(api, WxTagUserListJson.class, 1000, RequestTagUserListAPI.METHOD_GET, 5); return transferObjectFromWxResponse(response); } private WxTagUserListTO transferObjectFromWxResponse(WxTagUserListJson response) { WxTagUserListTO to = new WxTagUserListTO(); if(response != null){ to.setErrMsg(response.getErrMsg()); to.setErrorCode(response.getErrorCode()); if(response.getTagUserList() != null){ to.setTagUserList(response.getTagUserList()); } } return to; } // //////////////////////////////////////////////////////////////////////// // // Request enterprise Wechat department user list // // //////////////////////////////////////////////////////////////////////// public WxDepartmentUserListTO requestCorporationDepartmentUserList(String corporationAccessToken) throws WxApiException { RequestDepartmentUserListAPI api = new RequestDepartmentUserListAPI(corporationAccessToken); api.addObserver(this); WxDepartmentUserListJson response = RequestDepartmentUserListAPI.request(api, WxDepartmentUserListJson.clas eea7 s); return transferObjectFromWxResponse(response); } public WxDepartmentUserListTO requestCorporationDepartmentUserList(String corporationAccessToken, int departmentId) throws WxApiException { RequestDepartmentUserListAPI api = new RequestDepartmentUserListAPI(corporationAccessToken, departmentId); api.addObserver(this); WxDepartmentUserListJson response = RequestDepartmentUserListAPI.request(api, WxDepartmentUserListJson.class); return transferObjectFromWxResponse(response); } private WxDepartmentUserListTO transferObjectFromWxResponse(WxDepartmentUserListJson response) { WxDepartmentUserListTO to = new WxDepartmentUserListTO(); to.setErrMsg(response.getErrMsg()); to.setErrorCode(response.getErrorCode()); to.setUserList(response.getUserList()); return to; } // //////////////////////////////////////////////////////////////////////// // // Upload temp material and permanent material // // //////////////////////////////////////////////////////////////////////// public MaterialTO uploadTempMaterial(String corpAccessToken, String type, File file) throws WxApiException { UploadTempMaterialAPI api = new UploadTempMaterialAPI(corpAccessToken, type, file); api.addObserver(this); WxUploadTempMaterialResponse response = UploadTempMaterialAPI.request(api, WxUploadTempMaterialResponse.class, 1000, UploadTempMaterialAPI.METHOD_POST, 5); return transferObjectFromWxResponse(response); } private MaterialTO transferObjectFromWxResponse(WxUploadTempMaterialResponse response) { MaterialTO to = new MaterialTO(); to.setCreatedAt(response.getCreatedAt()); to.setMediaId(response.getMedieId()); to.setType(response.getType()); return to; } public WxUploadPermanentMaterialResponseJsonVO uploadPermanentMaterial(int appId, String corpAccessToken, String type, File file) throws WxApiException { UploadPermanentMaterialAPI api = new UploadPermanentMaterialAPI(appId, corpAccessToken, type, file); api.addObserver(this); WxUploadPermanentMaterialResponse response = UploadPermanentMaterialAPI.request(api, WxUploadPermanentMaterialResponse.class); return transferObjectFromWxUploadPermanentMaterialResponse(response); } private WxUploadPermanentMaterialResponseJsonVO transferObjectFromWxUploadPermanentMaterialResponse(WxUploadPermanentMaterialResponse response) { WxUploadPermanentMaterialResponseJsonVO vo = new WxUploadPermanentMaterialResponseJsonVO(); vo.setErrcode(response.getErrcode()); vo.setErrmsg(response.getErrmsg()); vo.setMedieId(response.getMedieId()); return vo; } public WxUploadPermanentMaterialResponseJsonVO uploadPermanentMpNews(String accessToken, String body) throws WxApiException { UploadPermanentMpNewsAPI api = new UploadPermanentMpNewsAPI(accessToken, body); api.addObserver(this); return UploadPermanentMpNewsAPI.request(api, WxUploadPermanentMaterialResponseJsonVO.class); } public WxDeletePermanentResponseVO deletePermanentMaterial(String accessToken, int agentId, String mediaId) throws WxApiException { DeletePermanentMaterialAPI api = new DeletePermanentMaterialAPI(accessToken, agentId, mediaId); api.addObserver(this); return DeletePermanentMaterialAPI.request(api, WxDeletePermanentResponseVO.class, 1000, DeletePermanentMaterialAPI.METHOD_GET, 5); } public WxUploadPermanentMaterialResponseJsonVO updatePermanentMaterial(String accessToken, String body) throws WxApiException { UpdatePermanentMaterialAPI api = new UpdatePermanentMaterialAPI(accessToken, body); api.addObserver(this); return UpdatePermanentMaterialAPI.request(api, WxUploadPermanentMaterialResponseJsonVO.class); } public WxPermanentMaterialTO requestPermanentMaterial(String accessToken, String mediaId, String agentId) throws WxApiException { RequestPermanentMaterialAPI api = new RequestPermanentMaterialAPI(accessToken, mediaId, agentId); api.addObserver(this); WxPermanentMaterialTO response = RequestPermanentMaterialAPI.request(api, WxPermanentMaterialTO.class, 1000, RequestPermanentMaterialAPI.METHOD_POST, 5); return response; } public WxRequestMaterialCountTO requestMaterialCount(String accessToken, String agentId) throws WxApiException { RequestMaterialCountAPI api = new RequestMaterialCountAPI(accessToken, agentId); api.addObserver(this); WxRequestMaterialCountTO to = RequestMaterialCountAPI.request(api, WxRequestMaterialCountTO.class, 1000, RequestMaterialCountAPI.METHOD_POST, 5); return to; } public WxMaterialListTO requestMaterialList(String accessToken, String body) throws WxApiException { RequestMaterialListAPI api = new RequestMaterialListAPI(accessToken, body); api.addObserver(this); WxMaterialListTO to = RequestMaterialListAPI.request(api, WxMaterialListTO.class, 1000, RequestMaterialListAPI.METHOD_POST, 5); return to; } // //////////////////////////////////////////////////////////////////////// // // Batch add contact // // //////////////////////////////////////////////////////////////////////// public String batchAddContact(String corpAccessToken, String token, String key, String corpId, String mediaId) throws WxApiException { BatchAddContactAPI api = new BatchAddContactAPI(corpAccessToken, token, key, corpId, mediaId); api.addObserver(this); api.setTimeout(120000); WxAsynRespnose response = BatchAddContactAPI.request(api, WxAsynRespnose.class); return response.getJobId(); } // //////////////////////////////////////////////////////////////////////// // // Batch update contact // // //////////////////////////////////////////////////////////////////////// public String batchUpdateContact(String corpAccessToken, String token, String key, String corpId, String mediaId) throws WxApiException { BatchUpdateContactAPI api = new BatchUpdateContactAPI(corpAccessToken, token, key, corpId, mediaId); api.addObserver(this); api.setTimeout(120000); WxAsynRespnose response = BatchUpdateContactAPI.request(api, WxAsynRespnose.class); return response.getJobId(); } // //////////////////////////////////////////////////////////////////////// // // Batch update department // // //////////////////////////////////////////////////////////////////////// public String batchUpdateDepartment(String corpAccessToken, String token, String key, String corpId, String mediaId) throws WxApiException { BatchUpdateDepartmentAPI api = new BatchUpdateDepartmentAPI(corpAccessToken, token, key, corpId, mediaId); api.addObserver(this); api.setTimeout(120000); WxAsynRespnose response = BatchUpdateDepartmentAPI.request(api, WxAsynRespnose.class); return response.getJobId(); } // //////////////////////////////////////////////////////////////////////// // // Batch delete department // // //////////////////////////////////////////////////////////////////////// public boolean batchDeleteContacts(String corpAccessToken, String[] userIds) throws WxApiException { BatchDeleteContactAPI api = new BatchDeleteContactAPI(corpAccessToken, userIds); api.addObserver(this); api.setTimeout(120000); WxResponse response = BatchDeleteContactAPI.request(api, WxResponse.class); return response.getErrcode() == 0; } // //////////////////////////////////////////////////////////////////////// // // Update menu, Request menu // // //////////////////////////////////////////////////////////////////////// public boolean updateMenu(String corpAccessToken, int appId, String server, String corpId, String suiteId) throws WxApiException { UpdateMenuAPI api = new UpdateMenuAPI(corpAccessToken, appId, server, corpId, suiteId); api.addObserver(this); WxResponse response = UpdateMenuAPI.request(api, WxResponse.class); return response.getErrcode() == 0; } public String update1Menu(String corpAccessToken, int agentId, String body) throws WxApiException { UpdateMenu1API api = new UpdateMenu1API(corpAccessToken, agentId, body); api.addObserver(this); WxResponse response = UpdateMenu1API.request(api, WxResponse.class, 1000, UpdateMenu1API.METHOD_POST, 5); return response.getErrmsg(); } public WxMenuContentTo requestMenu(String accessToken, int agentId) throws WxApiException { RequestWxMenuAPI api = new RequestWxMenuAPI(accessToken, agentId); api.addObserver(this); return RequestWxMenuAPI.request(api, WxMenuContentTo.class, 1000, RequestWxMenuAPI.METHOD_GET, 5); } // //////////////////////////////////////////////////////////////////////// // // Send Message // // //////////////////////////////////////////////////////////////////////// public WxMessageTO sendMessage(String toUser, String agentId, String message, String accessToken) throws WxApiException{ RequestSendMessageAPI api = new RequestSendMessageAPI(toUser, agentId, message, accessToken); api.addObserver(this); WxMessageTO response = RequestSendMessageAPI.requestReturnErroCode(api, WxMessageTO.class); return response; } // //////////////////////////////////////////////////////////////////////// // // Get userId by OAuth // // //////////////////////////////////////////////////////////////////////// public OAuthTo requestOAuth(String accessToken, String code, String agentId) throws WxApiException{ RequestOAuthAPI api = new RequestOAuthAPI(accessToken, code, agentId); api.addObserver(this); OAuthTo response = RequestOAuthAPI.requestHandle(api, OAuthTo.class, 1000, 1, 5); return response; } // //////////////////////////////////////////////////////////////////////// // // post request Callback // // //////////////////////////////////////////////////////////////////////// public WxCallbackReponseTO requestCallback(String callback, String body) throws WxApiException{ RequestCallbackAPI api = new RequestCallbackAPI(callback, body); api.addObserver(this); return RequestCallbackAPI.request(api, WxCallbackReponseTO.class); } // //////////////////////////////////////////////////////////////////////// // // post request Callback // // //////////////////////////////////////////////////////////////////////// public String requestAppCallback(String callback, String body) throws WxApiException{ RequestCallbackAPI api = new RequestCallbackAPI(callback, body); api.addObserver(this); return RequestCallbackAPI.request(api); } // //////////////////////////////////////////////////////////////////////// // // Get Auto Info // // //////////////////////////////////////////////////////////////////////// public AuthCorpAgentInfoTO requestAuthIfo(String suiteId, String authCorpId, String permanentCode, String suiteAccessToken) throws WxApiException{ RequestAuthInfoAPI api = new RequestAuthInfoAPI(suiteId, authCorpId, permanentCode, suiteAccessToken); api.addObserver(this); AuthCorpAgentInfoTO response = RequestAuthInfoAPI.request(api, AuthCorpAgentInfoTO.class); return response; } // //////////////////////////////////////////////////////////////////////// // //set agent Info // // //////////////////////////////////////////////////////////////////////// public boolean requestAgentInfo(String suiteId, String authCorpId, String permanentCode, String suiteAccessToken, int agentId) throws WxApiException{ RequestSetAgentAPI api = new RequestSetAgentAPI(suiteId, authCorpId, permanentCode, suiteAccessToken, agentId); api.addObserver(this); WxResponse response = RequestSetAgentAPI.request(api, WxResponse.class); return response.getErrcode() == 0; } @Override public void after(Timestamp startDate, long duration, String errorMessage, String url, String body) { Log log = prepareLogData(startDate, duration, errorMessage, url, body); persistLog(log); } //terry add private Log prepareLogData(Timestamp startDate, long duration, String errorMessage, String url, String body){ Log log = new Log(); log.setStartDate(startDate); log.setDuration(duration); log.setMessage(errorMessage); log.setUrl(url); log.setBodyData(body); log.setType("wxOut"); log.setType("out"); return log; } //terry add @Transactional private void persistLog(Log log){ logRepository.save(log); } }
可以看到以上的每一个方法背后就是一个微信企业号api的调用, 现在以调用第三方授权获得永久授权码为例,讲解代码。
RequestPermanentAuthCodeAPI
package com.augmentum.wechatee.framework.wxapi; import com.augmentum.wechatee.framework.utils.JsonUtils; import com.fasterxml.jackson.annotation.JsonProperty; public class RequestPermanentAuthCodeAPI extends AbstractWxAPI { private static final String API_URL = "https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token={0}"; private String suiteId; private String preAuthCode; public RequestPermanentAuthCodeAPI(String suiteId, String preAuthCode, String suiteAccessToken) { super(API_URL); this.suiteId = suiteId; this.preAuthCode = preAuthCode; setRequestParameters(suiteAccessToken); } @Override public String getPostBody() { WxPermanentAuthCodeBody body = new WxPermanentAuthCodeBody(); body.setSuiteId(suiteId); body.setAuthCode(preAuthCode); return JsonUtils.object2JsonStr(body); } class WxPermanentAuthCodeBody { @JsonProperty("suite_id") private String suiteId; @JsonProperty("auth_code") private String authCode; public WxPermanentAuthCodeBody() { } public String getSuiteId() { return suiteId; } public void setSuiteId(String suiteId) { this.suiteId = suiteId; } public String getAuthCode() { return authCode; } public void setAuthCode(String authCode) { this.authCode = authCode; } } }
我们看到在构造函数里面初始化了所需要的数据,在getPostBody中初始化了所需要post的数据。
public static <T> T request(WxAPI api, Class<T> clazz) throws WxApiException { api.buildRequest(); T response = JsonUtils.jsonStr2Model(api.sendRequest(), clazz); return response; }
@Override public void buildRequest() { parameterCount = StringUtils.countOccurrencesOf(baseUrl, "{"); url = MessageFormat.format(baseUrl, paramValues); body = getPostBody(); }
private String sendRequest(int timeout, int method) throws ClientProtocolException, IOException, WxWrongParameterNumberException { if (setParameterCount != parameterCount) { logger.info(" - *API* require {} parameters, set {} parameter(s)", parameterCount, setParameterCount); throw new WxWrongParameterNumberException(this, parameterCount, setParameterCount); } String response = null; long start = System.currentTimeMillis(); startDate = new Timestamp(start); try{ switch (method) { case METHOD_GET: Request reqGet = Request.Get(url).connectTimeout(timeout); if (body != null && !body.isEmpty()) { logger.info(" - *API* sending Body[{}]", url, body); reqGet.bodyString(body, ContentType.APPLICATION_JSON); } response = reqGet.execute().returnContent().asString(); break; default: Request reqPost = Request.Post(url).connectTimeout(timeout); if (body != null && !body.isEmpty()) { logger.info(" - *API* sending Body[{}]", url, body); reqPost.bodyString(body, ContentType.APPLICATION_JSON); } if (this.fileToUpload != null) { FileBody fileBody = new FileBody(fileToUpload, ContentType.APPLICATION_OCTET_STREAM); HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("media", fileBody).build(); reqPost.body(reqEntity); } response = reqPost.execute().returnContent().asString(); break; } }catch(ClientProtocolException e){ errorMessage = e.getMessage(); throw new ClientProtocolException(e.getMessage()); }catch(IOException e){ errorMessage = e.getMessage(); throw new IOException(e.getMessage()); }finally{ long end = System.currentTimeMillis(); duration = end - start; WxResponse err = JsonUtils.jsonStr2Model(response, WxResponse.class); if (err != null && err.getErrcode() != 0) { errorMessage = "{ wxErrorResponse:" + JsonUtils.object2JsonStr(err) + " }"; } //lambda observers.forEach(observer -> observer.after(startDate, duration, errorMessage, url, body)); } return response; }
使用fluent发送http请求。
相关文章推荐
- 六、设计模式——外观模式
- C#中实现Fluent Interface的三种方法
- C#中设计、使用Fluent API
- JavaScript设计模式之外观模式实例
- JavaScript设计模式之外观模式介绍
- 深入理解JavaScript系列(30):设计模式之外观模式详解
- Java设计模式之外观模式(Facade模式)介绍
- Spring整合Dwr,Cannot locate BeanDefinitionParser for element [annotation-scan]
- spring3 MVC手工搭建Spring3项目demo
- 大话设计模式 - 外观(Facade)模式
- spring mvc 开发需要的jar包的用途详解
- 解读最具O2O属性—哈根达斯微信企业号的成功之道
- 基于注解的 Spring MVC 简单入门-网摘
- [MVC] 深入浅出Spring MVC
- Java设计模式 结构模式-外观模式(Facade)
- Spring MVC 为例,从前台—>后台—>前台的编解码过程及出现乱码的案例
- Session_Facade(外观模式)
- (struts2) spring mvc + mybatis + maven整合
- FLUENT运行出错