在Spring管理的web项目里,配置好之后,就可以直接通过@Autowire自动注入获得service;
但是在普通Java类中使用service或者dao就会报空指针异常,因为这个普通类不在Spring的管理下,所以不能使用Spring来注入。
下面讲一下一个普通的Java类如何使用service
先定义SpringContextHolder
package com.fan.framework.context; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; /** * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext.*/ @Service @Lazy(false) public class SpringContextHolder implements ApplicationContextAware, DisposableBean { private static ApplicationContext applicationContext = null; private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class); /** * 取得存储在静态变量中的ApplicationContext. */ public static ApplicationContext getApplicationContext() { assertContextInjected(); return applicationContext; } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(Class<T> requiredType) { assertContextInjected(); return applicationContext.getBean(requiredType); } /** * 清除SpringContextHolder中的ApplicationContext为Null. */ public static void clearHolder() { if (logger.isDebugEnabled()){ logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); } applicationContext = null; } /** * 实现ApplicationContextAware接口, 注入Context到静态变量中. */ @Override public void setApplicationContext(ApplicationContext applicationContext) { // logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext); // if (SpringContextHolder.applicationContext != null) { // logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); // } SpringContextHolder.applicationContext = applicationContext; } /** * 实现DisposableBean接口, 在Context关闭时清理静态变量. */ @Override public void destroy() throws Exception { SpringContextHolder.clearHolder(); } /** * 检查ApplicationContext不为空. */ private static void assertContextInjected() { Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder."); } }
然后再使用SpringContextHolder获取指定的service
package com.thinkgem.jeesite.modules.sys.utils; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.cp.api.WxCpConfigStorage; import me.chanjar.weixin.cp.api.WxCpService; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.lang3.StringUtils; import com.fan.framework.context.SpringContextHolder; import com.fan.modules.sys.entity.User; import com.fan.modules.sys.entity.WechatLog; import com.fan.modules.sys.service.WechatLogService; import com.thinkgem.jeesite.common.utils.Exceptions; /** * 微信日志*/ public class WechatLogUtils { private static WechatLogService wechatLogService = SpringContextHolder.getBean(WechatLogService.class); /** * 保存日志 * @param request * @param wxCpService * @param wxCpConfigStorage * @param qyWechat 微信号名称 * @param title 操作菜单名称 * @param user 用户,可为空 * @param handler * @param e 异常信息 */ public static void saveWeChatLog(HttpServletRequest request, WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage, String qyWechat, String application, String title, String message, User user, Object handler, Exception e) { WechatLog weChatLog = new WechatLog(); if(StringUtils.isNotBlank(qyWechat)){ // 企业微信 weChatLog.setQyWechat(qyWechat); } if(StringUtils.isNotBlank(application)){ // 应用 weChatLog.setApplication(application); } if(null != request && null != wxCpService && null != wxCpConfigStorage){ weChatLog.setApplication(getAgentName(wxCpService, wxCpConfigStorage)); // 应用 Map<String, String> map = getMatchedMenu(request, wxCpService, wxCpConfigStorage); weChatLog.setFirstLevelMenu(map.get("first_level_menu")); // 一级菜单 weChatLog.setSecondLevelMenu(map.get("second_level_menu")); // 二级菜单 } if(null != user){ weChatLog.setEmployeeNo(user.getLoginName()); // 工号 weChatLog.setEmployeeName(user.getName()); // 姓名 } if(StringUtils.isNotBlank(title)){ // 标题 weChatLog.setTitle(title); }else{ if(StringUtils.isNotBlank(weChatLog.getApplication())){ title = weChatLog.getApplication(); if(StringUtils.isNotBlank(weChatLog.getFirstLevelMenu())){ title += ("-"+weChatLog.getFirstLevelMenu()); } if(StringUtils.isNotBlank(weChatLog.getSecondLevelMenu())){ title += ("-"+weChatLog.getSecondLevelMenu()); } weChatLog.setTitle(title); } } Calendar calendar= Calendar.getInstance(); weChatLog.setCreateDate(calendar.getTime()); // 创建时间 weChatLog.setException(Exceptions.getStackTraceAsString(e)); // 异常消息 if(StringUtils.isNotBlank(message)){ weChatLog.setMessage(message); } weChatLog.setType(e == null ? WechatLog.TYPE_ACCESS : WechatLog.TYPE_EXCEPTION); // 日志接入类型(1:接入日志;2:错误日志) if(null != request){ weChatLog.setParams(request.getParameterMap()); // 操作提交的数据 weChatLog.setMethod(request.getMethod()); // 提交方式 weChatLog.setUserAgent(""); // 操作用户代理信息 weChatLog.setIp(getRemoteAddr(request)); // ip weChatLog.setUri(request.getRequestURI()); // uri } // 如果无标题并无异常日志,则不保存信息 if (StringUtils.isNotBlank(weChatLog.getTitle()) || StringUtils.isNotBlank(weChatLog.getException())){ // 保存日志信息 wechatLogService.insert(weChatLog); } } /** * 获得用户远程地址 */ public static String getRemoteAddr(HttpServletRequest request){ String remoteAddr = request.getHeader("X-Real-IP"); if (StringUtils.isNotBlank(remoteAddr)) { remoteAddr = request.getHeader("X-Forwarded-For"); }else if (StringUtils.isNotBlank(remoteAddr)) { remoteAddr = request.getHeader("Proxy-Client-IP"); }else if (StringUtils.isNotBlank(remoteAddr)) { remoteAddr = request.getHeader("WL-Proxy-Client-IP"); } return remoteAddr != null ? remoteAddr : request.getRemoteAddr(); } /** * 获取应用 * https://qyapi.weixin.qq.com/cgi-bin/agent/get?access_token=ACCESS_TOKEN&agentid=AGENTID * 返回的是json字符串 */ public static String getAgent(WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) { String accessToken = wxCpConfigStorage.getAccessToken(); Integer agentId = wxCpConfigStorage.getAgentId(); String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/get?"; String info = null; try { info = wxCpService.get(url, "access_token="+accessToken + "&agentid=" + agentId); } catch (WxErrorException e) { e.printStackTrace(); } return info; } /** * 获取菜单 * https://qyapi.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN&agentid=AGENTID * 返回的是json字符串 */ public static String getMenu(WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) { String accessToken = wxCpConfigStorage.getAccessToken(); Integer agentId = wxCpConfigStorage.getAgentId(); String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?"; String menu = null; try { menu = wxCpService.get(url, "access_token="+accessToken + "&agentid=" + agentId); } catch (WxErrorException e) { e.printStackTrace(); } return menu; } /** * 获取应用中的name * @throws WxErrorException */ public static String getAgentName(WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) { String json = getAgent(wxCpService, wxCpConfigStorage); // 响应结果 JSONObject jsonObject = JSONObject.fromObject(json); // name String name = (String) jsonObject.get("name"); return name; } /** * 根据uri与获取的菜单相匹配,返回一级菜单和二级菜单 */ public static Map<String, String> getMatchedMenu(HttpServletRequest request, WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) { Map<String, String> matchedMenu = new HashMap<String, String>(); matchedMenu.put("first_level_menu", ""); matchedMenu.put("second_level_menu", ""); String uri = request.getRequestURI(); if(uri.startsWith("/")){ uri = uri.replaceFirst("/", ""); } String json = getMenu(wxCpService, wxCpConfigStorage); // 响应结果 JSONObject jsonObject = JSONObject.fromObject(json); JSONArray button = jsonObject.getJSONArray("button"); if(button.size() > 0){ boolean isBreak = false; for (int i = 0; i < button.size(); i++) { JSONObject firstObject = JSONObject.fromObject(button.get(i)); JSONArray subButton = firstObject.getJSONArray("sub_button"); if(subButton.size() > 0){ for(int j = 0 ; j < subButton.size() ; j++){ JSONObject secondObject = JSONObject.fromObject(subButton.get(j)); String url = (String) secondObject.get("url"); if(StringUtils.isNotBlank(url) && url.endsWith(uri)){ // 二级菜单的名称 String name2 = (String) secondObject.get("name"); matchedMenu.put("second_level_menu", name2); // 一级菜单的名称 String name1 = (String) firstObject.get("name"); matchedMenu.put("first_level_menu", name1); isBreak = true; break; } } if(isBreak){ break; } } } } return matchedMenu; } }
另外一种方法是
先编写一个类来实现ApplicationContextAware
/** * 通过该类即可在普通工具类里获取spring管理的bean */ public final class SpringTool implements ApplicationContextAware { private static ApplicationContext applicationContext = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringTool.applicationContext == null) { SpringTool.applicationContext = applicationContext; System.out.println( "========ApplicationContext配置成功,在普通类可以通过调用ToolSpring.getAppContext()获取applicationContext对象,applicationContext=" + applicationContext + "========"); } } public static ApplicationContext getApplicationContext() { return applicationContext; } public static Object getBean(String name) { return getApplicationContext().getBean(name); } }
然后把这个类加到spring的配置文件中去
<bean class="com.xsl.spring.SpringTool"/>
这样就可以在任何一个普通的工具类里,根据spring里配置好的bean的id,得到这个注入好的对象了
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath*:spring/spring-context.xml") public class JmFposStoreSalesTest { @Test public void test() { WechatLogService wechatLogService = (WechatLogService) SpringTool.getBean("articleService"); // 再进行其它操作 } }