Spring+Struts项目里配置Servlet详细过程及问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/superit401/article/details/83151191

1.现象:

通过浏览器地址栏访问http://localhost:8080/app/weixin/WeixinServlet?id=wed29051000027&signature=dq3uyrn83qfhwi&timestamp=1539850532&nonce=263014780&echostr=xxxx

报错:

There is no Action mapped for namespace [/weixin] and action name [WeixinServlet] associated with context path [/app]

2.报错时代码:

WeixinServlet

/**
 * 核心请求处理类
 * 
 */
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也做相应的改变:

http://localhost:8080/app/weixin/WeixinServlet.servlet?id=wed29051000027&signature=dq3uyrn83qfhwi&timestamp=1539850532&nonce=263014780&echostr=xxxx

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。

参考:

https://blog.csdn.net/shimiso/article/details/6045157

猜你喜欢

转载自blog.csdn.net/superit401/article/details/83151191
今日推荐