• Spring Mobile 与struts整合


    I'm experimenting with Spring Mobile but I can't seem to get the basic example working. I have a feeling I'm missing something stupidly simple but I can't figure out what it is. Here is what I have in place...

    In 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>

    In 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>

    In my Java class:

    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

    Why is the device not set and resulting as null?

    EDIT: Log files seem to indicate a problem with setting the interceptor but I'm still not sure where I went wrong.

    2012-05-29 09:36:36,696 DEBUG [ConstructorResolver.java:201] : Ignoring constructor [public org.springframework.web.servlet.handler.MappedInterceptor(java.lang.String[],org.springframework.web.context.request.WebRequestInterceptor)] of bean 'org.springframework.web.servlet.handler.MappedInterceptor#0': org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.web.servlet.handler.MappedInterceptor#0': Unsatisfied dependency expressed through constructor argument with index 1 of type [org.springframework.web.context.request.WebRequestInterceptor]: Could not convert constructor argument value of type [org.springframework.mobile.device.DeviceResolverHandlerInterceptor] to required type [org.springframework.web.context.request.WebRequestInterceptor]: Failed to convert value of type 'org.springframework.mobile.device.DeviceResolverHandlerInterceptor' to required type 'org.springframework.web.context.request.WebRequestInterceptor'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.mobile.device.DeviceResolverHandlerInterceptor] to required type [org.springframework.web.context.request.WebRequestInterceptor]: no matching editors or conversion strategy found



    up vote3down voteaccepted
    +50

    I've had a look at this and managed to get it to work myself. So I have a few comments.

    1a) I don't think both the Filter and the Interceptor are required. I've just used the Filter and that was enough.

    1b) The Interceptor (if used) should be configured in a DispatcherServlet xml config file. You look like you are using Struts from the use of ActionSupport, is this correct? If so, you (probably) won't have aDispatcherServlet and therefore I don't think this config will work as expected. I think that's why you're getting the stack trace.

    2) I would add a breakpoint to org.springframework.mobile.device.DeviceResolverRequestFilter.doFilterInternal to make sure it's being executed.

    3) I would check that Struts isn't doing something 'funny' with the ServletRequest, and hiding the"currentDevice" request attribute from you somehow. In fact, I would port your code to vanilla Spring if possible.

    4) Maybe you could use ServletActionContext.getRequest in your execute method and see if that works, and/or compare the returned request to that set in setServletRequest.


    Using Spring MVC, this is what works for me. My project is called spring-mobile-test, and "spring-mobile-test" is its context root:

    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 is empty.

    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;
        }
    }

    The browser shows the following text when I browse to the URL http://localhost/spring-mobile-test/mvc/:

    Hello desktop user!


     
     
    As I thought... it was a really stupid mistake that no one would have been able to determine here because I didn't post the entire web.xml contents. I had my filters setup backwards! Your suggestion #2 helped me set the breakpoint in the right place to realize my error. And I believe I needed both the filter and the interceptor in order to get my application to work... at least in my case. –  nmc Jun 13 '12 at 19:28
  • 相关阅读:
    php7与其他版本共存
    centos源码安装mysql5.7
    禁用composer update命令
    lumen怎么得到当前Uri的控制器、Action、路由规则
    配置lumen的log为daily模式
    laravel如何打印orm封装的sql语句
    nginx 重写URL尾部斜杠
    Laravel的Nginx重写规则--让路由支持末尾加斜线
    laravel redis存数组并设置过期时间
    openresty
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318034.html
Copyright © 2020-2023  润新知