1.现象:
报错:
There is no Action mapped for namespace [/weixin] and action name [WeixinServlet] associated with context path [/app]
2.报错时代码:
/**
* 核心请求处理类
*
*/
public class WeixinServlet extends HttpServlet {
private Logger log = LoggerFactory.getLogger(WeixinServlet.class);
/**
* 确认请求来自微信服务器
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
//公众帐号ID
String waccountId = request.getParameter("id");
PrintWriter out = response.getWriter();
out.print(echostr);
out.close();
out = null;
}
/**
* 处理微信服务器发来的消息
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
web.xml
<!-- struts配置 begin -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>com.util.ExtendStrutsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>WeixinServlet</servlet-name>
<servlet-class>com.weixin.action.WeixinServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WeixinServlet</servlet-name>
<url-pattern>/weixin/WeixinCoreServlet</url-pattern>
</servlet-mapping>
这是最原始、最原生的Servlet定义方法,但是在有Struts过滤器的时候就不管用了,要稍作修改
3.解决方案
方案一、servlet的配置中的<url-pattern>中路径后追加.servlet ,struts2的filter中<url-pattern>不变
方案二、struts2的filter中<url-pattern>中路径改为*.action,servlet中的<url-pattern>不变
出于最小影响原则,选择方案一,使新加的servlet只影响局部不影响全局。
修改后的web.xml
<!-- struts配置 begin -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>com.util.ExtendStrutsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>WeixinServlet</servlet-name>
<servlet-class>com.weixin.action.WeixinServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WeixinServlet</servlet-name>
<url-pattern>/weixin/WeixinCoreServlet.servlet</url-pattern>
</servlet-mapping>
即:
在servlet-mapping标签中的url-pattern中的路径后面追加.servlet,使之能准确定位到Servlet类
然后浏览器访问url也做相应的改变:
4.遇到问题
(1)在WeixinServlet中无法通过对weixinService设置set、get方法 或者 通过在applicationContext_xxx.xml里如下配置使用weixinService,
<bean id="weixinServlet" class="com.weixin.action.WeixinServlet" scope="prototype">
<property name="weixinService" ref="weixinService"></property>
</bean>
<bean id="weixinService" class="com.weixin.service.WeixinService">
<property name="weixinMapper" ref="weixinMapper"></property>
<property name="cacheManager" ref="cacheManager"></property>
</bean>
此时weixinService都为null,无法引用,需要通过new WeixinService()的方式引用。
(2)也不能如上xml配置使weixinService去调用weixinMapper和cacheManager,此时weixinService中的weixinMapper和cacheManager都为null
解决方法:
需要通过如下方式如引用:
ApplicationContext ac = ContextLoaderListener.getCurrentWebApplicationContext();
CacheManager cacheManager = (CacheManager)ac.getBean("cacheManager");
ApplicationContext ac = ContextLoaderListener.getCurrentWebApplicationContext();
WaccountMapper waccountMapper = (WaccountMapper)ac.getBean("waccountMapper");
原因:
Servlet是独立于任何框架的容器,原生的java就可以使用Servlet,不需要Spring、Struts2等框架支持框架,是独立容器,走独立逻辑。在Spring框架下,项目启动时通过解析applicationContext_xxx.xml定义的bean,独立的Servlet不走这套流程,读取不到解析出来的bean,需要使用原始的bean加载器ContextLoaderListener去获取上下文ApplicationContext来获取bean。
参考: