2012-08-08 10 views
5

私はSpringで非常に基本的なmvcアプリケーションを構築しています。リクエスト本体で検証を呼び出すコントローラが1つあります。問題は、web.xmlでマッピングを定義すると正しいコントローラを見つけられなくなりますが、サーブレットアプリケーションのコンテキストを変更すると、新しいバインディングが作成されますが、今回はアノテーションベースの検証は無視されます。注釈ベースの検証を引き続き呼び出すと同時に、web.xml内のマッピングを制御するにはどうすればよいですか?ここSpringが間違ったコントローラマッピングを呼び出す

詳細は、次のとおり

コントローラ:

@Controller 
@RequestMapping("/api") 
public class UserActionsController { 

    @RequestMapping(value="/choice", method = RequestMethod.POST) 
    public @ResponseBody NameValue addUserChoice(@Valid @RequestBody NameValue action) 
    {  
     return action; 
    } 
} 

これは、サーブレット・アプリケーション・コンテキストである:

<mvc:annotation-driven/> 

<context:component-scan base-package="com.my.package" /> 

<bean 
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
    <property name="mediaTypes"> 
     <map> 
      <entry key="json" value="application/json" /> 
     </map> 
    </property> 
    <property name="defaultContentType" value="application/json" /> 
    <property name="defaultViews"> 
     <list> 
      <bean 
       class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> 
     </list> 
    </property> 
</bean> 

ウェブXML:

<servlet> 
    <servlet-name>action-api</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>action-api</servlet-name> 
    <url-pattern>/*</url-pattern> 
</servlet-mapping> 

上記の設定が有効です。コントローラーが "/ api/*"のみを担当するように、web.xmlを変更しようとすると問題が発生します。私はそれを<url-pattern>/api/*</url-pattern>に変更します。その場合、Springは正しいコントローラを見つけることができません。

(DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice] 
(RequestMappingHandlerMapping:209) - Looking up handler method for path /choice 
(RequestMappingHandlerMapping:219) - Did not find handler method for [/choice] 
(PageNotFound:1080) - No mapping found for HTTP request with URI [/api/choice] in DispatcherServlet with name 'action-api' 
(DispatcherServlet:913) - Successfully completed request 

サーブレットアプリケーションのコンテキストを変更すると、Springはコントローラを検出できますが、検証はもう呼び出されません。ここで

<bean 
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="alwaysUseFullPath" value="true" /> 
    <property name="messageConverters"> 
     <util:list id="beanList"> 
      <bean class="org.springframework.http.converter.StringHttpMessageConverter"/> 
      <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> 
     </util:list> 
    </property> 
</bean> 

<bean 
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> 
    <property name="alwaysUseFullPath" value="true" /> 
</bean> 

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
    <property name="alwaysUseFullPath" value="true" /> 
</bean> 

はログです:

(DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice] 
(RequestMappingHandlerMapping:209) - Looking up handler method for path /choice 
(RequestMappingHandlerMapping:219) - Did not find handler method for [/choice] 
(DefaultAnnotationHandlerMapping:124) - Mapping [/api/choice] to HandlerExecutionChain with handler [[email protected]] and 1 interceptor 
(HandlerMethodInvoker:638) - Reading [com.my.package.model.NameValue] as "application/json" using [org.springf[email protected]2059ef] 
(HandlerMethodInvoker:173) - Invoking request handler method: public com.my.package.model.NameValue com.citypath.dima.controller.UserActionsController.addUserChoice(com.my.package.model.NameValue) 
(AnnotationMethodHandlerAdapter:1037) - Written [[email protected]] as "application/json;charset=UTF-8" using [org.springf[email protected]2059ef] 
(DispatcherServlet:957) - Null ModelAndView returned to DispatcherServlet with name 'action-api': assuming HandlerAdapter completed request handling 
(DispatcherServlet:913) - Successfully completed request 

は、春には、いくつかのその場で結合することのように見えますが、今回のバリデータは無視されます。 私は '/ api'と '/ something'のように2つのコントローラーが必要です。 web.xmlでどのように定義すればよいでしょうか?そうすれば、Springはそれらを見つけて検証を呼び出すことができます。

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

答えて

7

Spring @Controllers URLは、常にそれらを処理するSpring Dispatcherサーブレットに関連して解釈されます。したがって、ディスパッチャサーブレットをweb.xmlの/ api/*にマップすると、上記のコントローラへのURLは/ api/api/choiceになります。

したがって、web.xmlに2つのスプリングディスパッチャーserveltsを/ apiとweb.xmlの/ somethingelseにマッピングされている場合、@RequestMappingsから/ apiを削除することができます

私のアプリでは、APIとUI用にDispatcherサーブレットを1つ使用しています。 APIによって公開されているさまざまなリソースへのパスを構築するために、さまざまなAPIコントローラのURLと呼ばれるfinal String。以下は私のAPIの例です。

@Controller 
@RequestMapping(CompanyPermissionsResourceController.PATH) 
public class CompanyPermissionsResourceController extends BaseApiController 
{ 
    public static final String PATH = CompanyResourceController.PATH + "/permissions"; 
+0

ありがとうございます。 '/ api/api/choice'は実際にSpringがコントローラを見つけられなかった理由を理解するのに役立ちました。コントローラーで 'api'部分を定義しないと、web.xmlだけですごくうまくいきます。コントローラとメソッドレベルでのマッピングちょうどそれが働くと思われるように。 – Dima

+0

この回答は私の問題の根本的な原因を見つけるのを助けました。私の@ComponentScanには私のコントローラのパッケージは含まれていませんでした – McLovin

1

postリクエストを/api/choiceにしてもよろしいですか?

@RequestMapping(value="/choice", method = RequestMethod.POST) 

私はそれがこのように動作しますとは思わない

@RequestMapping(value="/choice", method = RequestMethod.GET) 
public @ResponseBody NameValue addUserChoice(@Valid @RequestBody NameValue action) 
{  
    return action; 
} 
+0

前述したように、最初の設定が機能します。したがって、クライアント側には問題はありません。 (私は全く問題ないFiddlerを使用しています) – Dima

-1

に変更してみてください。すべてのパス/api/choiceをメソッドレベルにします。

+0

なぜそれは動作するはずではないのか説明できますか?コントローラレベルの@RequestMappingがサポートされています。 web.xmlで/ * – Dima

+0

以外のパスが指定されていない場合は正常に動作しています。SpringはメソッドレベルのRequestMappingからRequestMappingまでのパスをクラスレベルで追加しないと思います。もちろん、私は間違っているかもしれません。私はこのアプローチを試みたことはありません。 RequestMappingをメソッドレベルで定義して、それを機能させる必要があります。それは確かです。 RequestMappingがクラスレベルのパスでパラメータ化されている場合、pathでパラメータ化する必要はありません。問題は、あなたが何かのためにこのアプローチが必要なのか? –

+0

そして今私は間違っていたことを知っています。 :) –

関連する問題