6

いくつかのチュートリアルと多数の StackOverflow エントリを使用して、Java を使用して RESTful サービスを作成しようとしています。残念ながら、コードを機能させることができないようです。エンドポイントにアクセスしようとすると、永続的に Http 406 が発生します。どんな助けでも大歓迎です。

GreetingController.java:

import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/greeting")
public class GreetingController {

    protected final Logger log = LoggerFactory.getLogger(GreetingController.class);

    private static final String template = "Hello, %s!";
    private static Random rand = new Random();

    @RequestMapping(method = RequestMethod.GET, headers="Accept=*/*")//, value="/{name}")
    @ResponseBody
    public Greeting greeting() {
        log.debug("Entered greeting()");
        return new Greeting(rand.nextInt(99999999),
                            String.format(template, "Stephen"));
    }

    @RequestMapping(method = RequestMethod.GET, value="/{name}")
    @ResponseBody
    public Greeting greetingName(@PathVariable String name) {
        log.debug("Entered greetingName()");
        return new Greeting(rand.nextInt(99999999),
                            String.format(template, name));
    }
}

Greeting.java:

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="greeting")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class Greeting {

    private Integer id;
    private String content;

    public Greeting() {

    }

    public Greeting(Integer id, String content) {
        this.id = id;
        this.content = content;
    }

    @XmlElement
    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    @XmlElement
    public void setContent(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

x-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:oxm="http://www.springframework.org/schema/oxm"
    xmlns:mvc="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

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

    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix">
            <value>/WEB-INF/pages/</value>
      </property>
      <property name="suffix">
            <value>.jsp</value>
      </property>
    </bean>

</beans>

HTTP ヘッダー (firebug 経由):

Response Headers
Content-Language    en
Content-Length  1067
Content-Type    text/html;charset=utf-8
Date    Tue, 18 Feb 2014 20:24:13 GMT
Server  Apache-Coyote/1.1

Request Headers
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Connection  keep-alive
Cookie  JSESSIONID=9064B3E9F1C3259B73C65B022C8BDC75
Host    localhost:8080
User-Agent  Mozilla/5.0 (Windows NT 6.0; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0

tomcat を起動し、上記のサーバーのさまざまなページにアクセスしたときのログ:

DEBUG o.s.security.web.FilterChainProxy - Converted URL to lowercase, from: '/greeting'; to: '/greeting'
DEBUG o.s.security.web.FilterChainProxy - Candidate is: '/greeting'; pattern is /**; matched=true
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 1 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.channel.ChannelProcessingFilter@9a6bbb'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Converted URL to lowercase, from: '/greeting'; to: '/greeting'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Candidate is: '/greeting'; pattern is /**; matched=true
DEBUG o.s.s.w.a.c.ChannelProcessingFilter - Request: FilterInvocation: URL: /greeting; ConfigAttributes: [ANY_CHANNEL]
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 2 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@16fcc4'
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 3 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@1db52c8'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 4 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@17d6c1'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 5 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@1144823'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 6 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.www.BasicAuthenticationFilter@8c02cc'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 7 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.savedrequest.RequestCacheAwareFilter@bbd1b'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 8 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@ac576f'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 9 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.AnonymousAuthenticationFilter@15daa9e'
DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 10 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.session.SessionManagementFilter@6c9f0f'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 11 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.ExceptionTranslationFilter@13ec758'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 12 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.intercept.FilterSecurityInterceptor@917cb0'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Converted URL to lowercase, from: '/greeting'; to: '/greeting'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Candidate is: '/greeting'; pattern is /welcome*; matched=false
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Candidate is: '/greeting'; pattern is /**; matched=true
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /greeting; Attributes: [IS_AUTHENTICATED_ANONYMOUSLY]
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@1913751, returned: 0
DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@c6b80e, returned: 1
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
DEBUG o.s.security.web.FilterChainProxy - /greeting reached end of additional filter chain; proceeding with original chain
DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'spring-tutorial' determining Last-Modified value for [/SpringMVC/greeting]
DEBUG o.s.w.s.m.a.DefaultAnnotationHandlerMapping - Mapping [/greeting] to handler 'com.example.controller.GreetingController@1eb1db2'
DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/SpringMVC/greeting] is: -1
DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'spring-tutorial' processing GET request for [/SpringMVC/greeting]
DEBUG o.s.w.b.a.s.HandlerMethodInvoker - Invoking request handler method: public com.example.form.Greeting com.example.controller.GreetingController.greeting()
INFO  c.s.controller.GreetingController - Entered greeting()
DEBUG o.s.w.s.m.a.AnnotationMethodHandlerExceptionResolver - Resolving exception from handler [com.example.controller.GreetingController@1eb1db2]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [com.example.controller.GreetingController@1eb1db2]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [com.example.controller.GreetingController@1eb1db2]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext contents are anonymous - context will not be stored in HttpSession. 
DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'spring-tutorial': assuming HandlerAdapter completed request handling
DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
4

4 に答える 4

3

これを追跡するのに数時間費やしたので、私にとってうまくいったもの(私はSpring 4.0.6を使用しています)とあなたにとってうまくいくと私が信じているもの(Spring 3.0.x)をここに残します。

春 4.0.x

MappingJackson2HttpMessageConverterは Jackson データ バインディング ライブラリを自動的に取得し、 で注釈が付けられたコントローラー メソッドが JSON を自動的に返すことを可能にするため@ResponseBody、通常、そのようなツールは XML にも存在すると想定されますが、そうではありません。

XML を有効にするためにRequestMappingHandlerAdapter、2 つのメッセージ コンバーター ( のMarshallingHttpMessageConverter後にMappingJackson2HttpMessageConverter.

これにより、Spring が提供する任意のマーシャラーを のプロパティとして設定するだけで使用することもできますMarshallingHttpMessageConverter

結果spring-servlet.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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- ... -->

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                    <property name="marshaller">
                        <bean class="org.springframework.oxm.xstream.XStreamMarshaller"></bean>
                    </property>
                </bean>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
            </list>
        </property>
    </bean>

    <!-- ... -->

</beans>

春 3.0.x

注: のスキーマの場所からこのバージョンを想定していますx-servlet.xml

http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvcおよびhttp://spring.io/blog/2013/06/03/content-negotiation-using-によるとviews/の場合、Spring 3 で目的を達成する方法は 2 つあります。最初の方法はContentNegotiationManager、バージョン 3.2.x 以降でのみ使用できる を使用するため、お使いのバージョンでは使用できません。2 つ目はContentNegotiatingViewResolver、要求されたコンテンツ タイプに基づいて、ビューの解決を他のリゾルバーに委任する を使用しています (これがAcceptヘッダーによって定義されているか、拡張機能によって定義されているか、または既定で構成可能であるか)。

ContentNegotiatingViewResolver基本的に、XML 用と JSP ビュー用の 2 つのリゾルバーを構成する必要があります。

spring-servlet.xml:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.XmlViewResolver">
                <property name="location" value="spreadsheet-views.xml"/>
            </bean>

            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="WEB-INF/views"/>
                <property name="suffix" value=".jsp"/>
            </bean>
        </list>
    </property>
</bean>

たとえば、JSON のビュー リゾルバーを追加できますが、Spring ではビュー リゾルバーが提供されないため、実装する必要があります。2 番目のブログ投稿では、単純なものを実装する方法を示します。

于 2014-08-19T16:26:41.710 に答える
1

406 は、リクエストのコンテンツがサーバーによって受け入れられないと見なされることを意味します。ヘッダーを削除するか、注釈にAccept追加してみてください。headers="Accept=*/*"@RequestMapping

于 2014-02-18T21:07:06.873 に答える