Spring Mobile - 拦截器未应用?设备为空。

3

我正在尝试使用Spring Mobile,但我似乎无法使基本示例正常工作。 我有一种感觉,我错过了某些愚蠢简单的东西,但我无法弄清楚它是什么。 这是我的现有内容...

在web.xml中

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/applicationContext.xml
    </param-value>
</context-param> 
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
    <filter-name>deviceResolverRequestFilter</filter-name>
    <filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>deviceResolverRequestFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

在applicationContext.xml文件中

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:device="http://www.springframework.org/schema/mobile/device"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://www.springframework.org/schema/mvc 
                http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/mobile/device 
                http://www.springframework.org/schema/mobile/device/spring-mobile-device-1.0.xsd">

    <!-- Interceptors that execute common control logic across multiple requests -->
    <interceptors>
        <!-- Detects the client's Device -->
        <beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" />
    </interceptors>

</beans:beans>

在我的Java课程中:

public class TestAction extends ActionSupport implements ServletRequestAware {

    // So that we can lookup the current Device 
    private HttpServletRequest request;

    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }

    @Override
    public String execute() {
        Device currentDevice = DeviceUtils.getCurrentDevice(request);
        if (currentDevice.isMobile()) // <-- fails here with NPE

为什么设备未设置并导致为空?

编辑: 日志文件似乎表明设置拦截器存在问题,但我仍然不确定哪里出错了。

2012-05-29 09:36:36,696 DEBUG [ConstructorResolver.java:201] : 忽略构造函数[public org.springframework.web.servlet.handler.MappedInterceptor(java.lang.String[],org.springframework.web.context.request.WebRequestInterceptor)] 的bean 'org.springframework.web.servlet.handler.MappedInterceptor#0': org.springframework.beans.factory.UnsatisfiedDependencyException: 创建bean时发生错误 'org.springframework.web.servlet.handler.MappedInterceptor#0': 通过构造函数参数表达的不满足的依赖项 索引1的类型为 [org.springframework.web.context.request.WebRequestInterceptor]: 无法将类型为 [org.springframework.mobile.device.DeviceResolverHandlerInterceptor] 的构造函数参数值转换为所需类型 [org.springframework.web.context.request.WebRequestInterceptor]: 无法将类型为 'org.springframework.mobile.device.DeviceResolverHandlerInterceptor' 的值转换为所需类型 'org.springframework.web.context.request.WebRequestInterceptor'; 嵌套异常是java.lang.IllegalStateException:无法转换 类型为[org.springframework.mobile.device.DeviceResolverHandlerInterceptor] 到所需类型 [org.springframework.web.context.request.WebRequestInterceptor]: 找不到匹配的编辑器或转换策略。

2个回答

4
我已经查看了这个问题并成功解决了。以下是我的一些评论。
1a) 我认为不需要同时使用过滤器和拦截器。我只使用了过滤器就足够了
1b) 如果使用拦截器,应该在DispatcherServlet的xml配置文件中进行配置。从使用ActionSupport的情况来看,您似乎正在使用Struts,这是正确的吗?如果是这样,您(可能)没有DispatcherServlet,因此我认为此配置将无法按预期工作。我认为这就是您收到堆栈跟踪的原因。
2) 我会在org.springframework.mobile.device.DeviceResolverRequestFilter.doFilterInternal中添加断点,以确保它被执行。
3) 我会检查Struts是否对ServletRequest做了一些“奇怪”的事情,并且以某种方式隐藏了“currentDevice”请求属性。实际上,如果可能的话,我会将您的代码移植到vanilla Spring。
4) 也许您可以在execute方法中使用ServletActionContext.getRequest,然后查看它是否有效,并将返回的请求与setServletRequest中设置的请求进行比较。
使用Spring MVC,以下是对我有效的内容。我的项目名为spring-mobile-test,“spring-mobile-test”是它的上下文根:
web.xml:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>deviceResolverRequestFilter</filter-name>
        <filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>deviceResolverRequestFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>/mvc/*</url-pattern>
    </servlet-mapping>
</web-app>

applicationContext.xml是空的。

mvc-servlet.xml:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:component-scan base-package="temp" />

</beans>

temp.TestController:

package temp;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestController {
    private static final Logger logger = Logger.getLogger(TestController.class);

    @RequestMapping("/")
    public @ResponseBody
    String home(HttpServletRequest req) {
        Device device = DeviceUtils.getCurrentDevice(req);
        String msg = "";
        if (device.isMobile()) {
            msg = "Hello mobile user!";
        } else {
            msg = "Hello desktop user!";
        }
        logger.info(msg);
        return msg;
    }
}

当我浏览到URL http://localhost/spring-mobile-test/mvc/ 时,浏览器会显示以下文本:

您好,桌面用户!


正如我所想...这是一个非常愚蠢的错误,没有人能够在这里确定,因为我没有发布整个web.xml内容。我的过滤器设置反了!你的建议#2帮助我在正确的位置设置断点,以认识到我的错误。而且我相信我需要过滤器和拦截器才能让我的应用程序工作...至少在我的情况下是这样。 - nmc

0

在web.xml中添加过滤器就足以处理移动设备检测。

1- 在web.xml文件中使用以下配置。

<!--Device Resolver filter start here  -->
<filter>
       <filter-name>deviceResolverRequestFilter</filter-name>
       <filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter     </filter-class>
</filter>
 <filter-mapping>
    <filter-name>deviceResolverRequestFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>  

2- 添加以下jar文件

        spring-mobile-device-1.x.x.RELEASE.jar

3- 检查设备的代码

        Device device=DeviceUtils.getCurrentDevice(request);
        boolean isMobile = device.isMobile();
        boolean isTablet=device.isTablet();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接