6

Spring MVC と Groovy を使用して、既存の Java Web アプリケーションを RESTful Web アプリケーションに変換しようとしています。私が達成したかった主な機能の 1 つは、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>

この 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)
        }
    }
  }

Spring 構成ファイルは次のとおりです。ここでは、動的言語をサポートする「lang:groovy」タグを使用しています。また、リフレッシュ時間は 5 秒であると述べました。これにより、実行時にこれらの groovy ファイルに加えられた変更が 1 秒ごとに表示され、クラスがリロードされます。

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

それに応じて Buildpath と groovy コンパイラを構成し、すべての groovy スクリプトがクラス ファイルにコンパイルされるのではなく、ターゲット フォルダーに直接コピーされるようにしました。

主な問題
このプロジェクトを Tomcat サーバーにデプロイすると、ScriptProcessor を含む必要なすべての Spring Bean がロードされます。ここで、ブラウザにアクセスしてフォームをロードし、認証フォームを送信しようとすると、Tomcat ログに次のエラーが表示されます。

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

$TOMCAT_DIR/conf/context.xml にも変更を加えて、アンチロック リソースと JARS を作成しました。

<Context antiResourceLocking="true" antiJARLocking="true" reloadable="true" privileged="true">
.
.
.</Context>

ただし、これらの Groovy スクリプトをバイトコード クラスにコンパイルするようにプロジェクトを構成し、applicationContext.xml の「lang:groovy」タグをコメント アウトしてからサーバーを再起動すると、Groovy スクリプトがクラス ファイルにコンパイルされ、要求が完全に処理されます。 . 認証が行われます。

また、タグの代わりに次の 2 行を使用して 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>

しかし、このスタイルで Bean のさわやかな機能を作成する方法がわかりません。したがって、タグが groovy スクリプトを処理する方法に問題があると思います。

これについて何か助けていただければ幸いです。私はインターネット全体を検索し、無数のチュートリアルを読み、そこに記載されている正確な手順に従いました. しかし、何が問題なのかわかりません。

この問題を解決するのを手伝ってください。

ありがとうございました。

4

1 に答える 1