使用HOT部署的Spring/REST应用程序:Groovy脚本不会在运行时在tomcat启动时从applicationContext.xml动态加载

use*_*874 6 rest groovy spring-mvc tomcat6 spring-annotations

我正在使用Spring MVC和Groovy将已经存在的Java Web应用程序转换为RESTful Web应用程序.我想要实现的主要功能之一是HOT DEPLOYMENT.我之所以选择groovy是因为我不想对已经实现的业务逻辑(处理程序)进行更改,而且如果我必须在部署后对groovy代码进行更改,我可以轻松地在不重新启动服务器的情况下执行此操作(即在运行时).这可以做到,因为Spring支持动态重新加载groovy脚本(bean).如果它们被更改,它会重新加载动态语言类.

我使用Spring注释将请求URL映射到控制器方法,应用程序部署在tomcat 6.0.35中.

这是web.xml文件

//web.xml

        <?xml version = "1.0" encoding = "UTF-8"?>
        <web-app xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

         <!-- Spring Dispatcher -->
         <servlet>
              <servlet-name>rest</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
         </servlet>
         <servlet-mapping>
              <servlet-name>rest</servlet-name>
              <url-pattern>/service/*</url-pattern>
         </servlet-mapping>
        <!-- Loads application context files in addition to  ${contextConfigLocation} -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>    

            <!-- Set session timeout to 30 minutes -->
        <session-config>
            <session-timeout>30</session-timeout>
        </session-config>
    </web-app>
Run Code Online (Sandbox Code Playgroud)

这个groovy文件是DispatcherServlet将请求映射到的控制器.

// UserController.groovy

@Controller
class UserController 
 {
    // This is the method to which the HTTP request is submitted to based on the mapping of the 
    // action field of the form ie. /service/user/login/auth.json
    @RequestMapping(value="/user/login/auth.{extension:[a-zA-Z]+}", method=RequestMethod.POST)
    @ResponseBody
    public String authenticate(
    @PathVariable String extension,
    @RequestParam(value="username", required=true) String username,
    @RequestParam(value="password", required=true) String password) 
    {
        // UserResource makes the backend calls, authenticates a user and returns the result.
        def user = new UserResource()
        def result = user.login(name:username, userPassword:password)

        // Output the result of the query. Method makeView makes a JSON response of the result
        // and sends to the client(browser) 
        def builder = makeView(extension) 
        {
            it.login(action:result.action, message:result.message)
        }
    }
  }
Run Code Online (Sandbox Code Playgroud)

Spring配置文件如下所示,我使用了支持动态语言的"lang:groovy"标签.我还提到刷新时间为5秒,因此可以每1秒钟看到在运行时对那些groovy文件所做的任何更改,并重新加载类.

//applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:c="http://www.springframework.org/schema/c" 
    xmlns:util="http://www.springframework.org/schema/util" 
    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 
        http://www.springframework.org/schema/util  
        http://www.springframework.org/schema/util/spring-util-3.1.xsd
        http://www.springframework.org/schema/lang
        http://www.springframework.org/schema/lang/spring-lang-3.1.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="app.controller,app.resource" />

     <lang:groovy id="user" script-source="classpath:controller/UserController.groovy" refresh-check-delay="1000"></lang:groovy>

    <!-- To enable @RequestMapping process on type level and method level -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

    <!-- Resolves view names to template resources within the directory -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".html"/>
    </bean>

</beans>
Run Code Online (Sandbox Code Playgroud)

我已相应地配置了我的Buildpath和groovy编译器,以便所有groovy脚本直接复制到目标文件夹,而不是编译到类文件.

主要问题
当我在tomcat服务器中部署这个项目时,它会加载所需的所有Spring bean,包括ScriptProcessor.现在,当我进入浏览器,加载表单,并尝试提交身份验证表单时,我在Tomcat日志中收到以下错误:

15:20:09 WARN - No mapping found for HTTP request with URI [/service/user/login/auth.json] in DispatcherServlet with name 'rest'
Run Code Online (Sandbox Code Playgroud)

我还在$ TOMCAT_DIR/conf/context.xml中对防火墙资源和JARS进行了更改

<Context antiResourceLocking="true" antiJARLocking="true" reloadable="true" privileged="true">
.
.
.</Context>
Run Code Online (Sandbox Code Playgroud)

但是,如果我将项目配置为将这些groovy脚本编译为字节码类,请注释applicationContext.xml中的"lang:groovy"标记,然后重新启动服务器,groovy脚本将编译为类文件,并且请求将完美地提供服务.身份验证发生.

此外,如果我使用以下两行而不是标记在applicationContet.xml中配置动态bean,我的bean将在运行时动态创建,并且由于注释,URL会映射到相应的控制器方法.

<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor" />

<bean id ="User" class="org.springframework.scripting.groovy.GroovyScriptFactory">
   <constructor-arg value="classpath:controller/UserController.groovy" />
</bean>
Run Code Online (Sandbox Code Playgroud)

但我不知道如何使用这种风格创建bean刷新功能.所以我猜标签处理groovy脚本的方式存在问题.

我真的很感激一些帮助.我在互联网上搜索并阅读了无数的教程,并按照那里提到的确切程序.但我不知道什么是错的.

请帮我解决这个问题.

谢谢.

Tod*_*one 0

尝试使用已编译的 Java/Groovy 创建控制器,并让它注入 Groovy“脚本”作为依赖项来完成实际工作。我似乎记得以前这样做过,可能是注释或 Spring 加载控制器的方式使“脚本”无法正常工作。