最近在搞抄袭,抄哪家就不说了,反正人家开源了源码,然后就涉及到了JavaEE的开发。想起了读研的时候开发的教学管理系统,那会还是用的框架还是SSH,然后第一份工作中也涉及了部分云端开发,用的框架是SSM,没想到干了一年又需要整这个,看来搞Android没前途呀,哈哈哈哈,扯远了~
先说遇到的问题:在Servlet里使用了自动注入失败,报空指针异常。这个问题其实拆分下来是两个问题,问题一:Servlet如何使用Spring的自动注入;问题二:static关键字修饰的自动注入对象失败。
先说问题一:网上百度搜了一下,基本上解释都是千篇一律,说是注解@ComponentScan所注解的Application没有在根目录,导致搜不到对应的类,这个吧是导致注入失败的原因之一,但是不是我遇到的问题,只能说是我这个搜的问题没有描述清楚。我遇到的问题的根本是Servlet使用了@Autowired失败,网上大神的说法是,Servlet和Spring不是统一由Spring管理的,所以在Servlet里不能直接使用Spring的注解,解决办法如下:
@WebServlet("/sevlet/test")
public class TestServlet extends HttpServlet {
@Override
public void init() throws ServletException {
WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()).getAutowireCapableBeanFactory().autowireBean(this);
super.init();
ServletContext application = this.getServletContext();
// 解决servlet用@Autowired自动注入service失败的问题
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, application);
if (testController == null) {
System.out.println("========== 注入失败 ==========");
} else {
System.out.println("========== 注入成功 ==========");
TestControllerUtil controllerUtil = new TestControllerUtil();
controllerUtil.setTestController(testController);
}
}
@Autowired
private TestController testController;
public TestServlet() {
super(getSkill());
}
private static Skill getSkill() {
Skill skill = Skills.custom()
.addRequestHandlers(new PhoneCallHandler())
.withSkillId("adbcdefg")
.build();
return skill;
}
}
其实就是在init()的时候加入了一句话就可以在servlet里使用自动注入了。第一个问题就算是解决了。
接下来是第二个问题:static关键字修饰的自动注入对象失败。从上面的代码里可以看到,我在注入成功了之后还调用了一个Util然后把testController通过set方法传进去。其实最开始的时候是这样写的:
@Autowired
private static PhoneController phoneController;
然后就注入失败,报空指针了。这个时候就不得不找原因了:原因是自动注入实际上是由Spring自动new了一个对象,而static修饰的对象是在程序一开始的时候就初始化了,也就是static的初始化比较早,这个解决方法就是自己写一个工具类,然后通过set方法把自动注入的对象传进去,代码如下:
public class TestControllerUtil {
private static TestController testController;
public TestController getContactController() {
return testController;
}
public void setTestController(TestController testController) {
TestControllerUtil.testController = testController;
}
public static ContactEntity searchContact(String phoneNumber, String name) {
ContactEntity contactEntity = testController.searchContact(phoneNumber, name);
return contactEntity;
}
public static String searchPhoneNumberByUserId(String userId) {
String phoneNumber = testController.getUserPhoneNumber(userId);
return phoneNumber;
}
}
注意set方法不是static的。至此,解决了这两个问题。
最后不得不说,Spring还是强大啊,IOC和AOP,不过我太久没碰了,早就忘光了,哎,我还是太菜。