Spring Mvc的春季风云

时间:2018-07-02 15:09:55

标签: spring model-view-controller spring-hateoas

我正在尝试通过Spring MVC学习Spring hateoas,但无法使其正常工作。我在Google上搜索了很多,但是我在Spring Boot中发现了所有的仇恨 我有一个非常简单的Spring MVC项目。我的pom是

View

要使用hateaos,我要添加其依赖项

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.SpringMvcWeb</groupId>
<artifactId>SpringMvcWebXml</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
    </plugins>
</build>

但是缺少常见日志记录的给出错误,因此我添加了

    <dependency>
        <groupId>org.springframework.hateoas</groupId>
        <artifactId>spring-hateoas</artifactId>
        <version>0.24.0.RELEASE</version>
    </dependency>

现在说的是NoSuchMethodError:org.springframework.web.servlet.handler.AbstractHandlerMapping.obtainApplicationContext()

我想念什么? 如果有人可以指导我使用Spring MVC和hateoas代码,那将真的很有帮助。

1 个答案:

答案 0 :(得分:0)

我试图重现您的用例。在pom.xml上应如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.SpringMvcWeb</groupId>
    <artifactId>SpringMvcWebXml</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <javax-jaxb.version>2.3.0</javax-jaxb.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.hateoas</groupId>
            <artifactId>spring-hateoas</artifactId>
            <version>0.24.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>


        <dependency>
            <groupId>org.springframework.plugin</groupId>
            <artifactId>spring-plugin-core</artifactId>
            <version>1.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.6</version>
        </dependency>


    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

关键部分是spring-plugin-core和com.fasterxml.jackson.core,我在示例中使用json。我需要spring-plugin-core,因为tomcat错过了这个bean PluginRegistryFactoryBean。

我非常简单的restfull服务如下:

@RestController
public class EndPointSample {

    private final MessageLinkFactory messageLinkFactory;

    public EndPointSample(MessageLinkFactory messageLinkFactory) {
        this.messageLinkFactory = messageLinkFactory;
    }

    @GetMapping("/test")
    public ResponseEntity test(){
        return ResponseEntity.ok(messageLinkFactory.getRes(new Message("hello")));
    }
}

public class MessageLinkFactory {

    public Resource getRes(Message message){
        Link link = linkTo(methodOn(EndPointSample.class).test()).withSelfRel();

        Resource<Message> hello = new Resource<>(message);
        hello.add(link);

        return hello;
    }
}

public class Message {

    private String message;

    public Message() { }

    public Message(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

结果是一个类似json的

{ message: "hello", _links: {self: { href: "http://localhost:8080/test" } } }

但是,仅当您使用accetp标头application / hal + json发送请求时,此方法才有效。如果您希望它与像spring boot这样的application / json一起使用,则可以为此添加一个消息转换器。我把Spring Boot所采用的代码放进去了。

@Component
class HalMessageConverterSupportedMediaTypesCustomizer
        implements BeanFactoryAware {

    private volatile BeanFactory beanFactory;

    @PostConstruct
    public void configureHttpMessageConverters() {
        if (this.beanFactory instanceof ListableBeanFactory) {
            configureHttpMessageConverters(((ListableBeanFactory) this.beanFactory)
                    .getBeansOfType(RequestMappingHandlerAdapter.class).values());
        }
    }

    private void configureHttpMessageConverters(
            Collection<RequestMappingHandlerAdapter> handlerAdapters) {
        for (RequestMappingHandlerAdapter handlerAdapter : handlerAdapters) {
            for (HttpMessageConverter<?> messageConverter : handlerAdapter
                    .getMessageConverters()) {
                configureHttpMessageConverter(messageConverter);
            }
        }
    }

    private void configureHttpMessageConverter(HttpMessageConverter<?> converter) {
        if (converter instanceof TypeConstrainedMappingJackson2HttpMessageConverter) {
            List<MediaType> supportedMediaTypes = new ArrayList<>(
                    converter.getSupportedMediaTypes());
            if (!supportedMediaTypes.contains(MediaType.APPLICATION_JSON)) {
                supportedMediaTypes.add(MediaType.APPLICATION_JSON);
            }
            ((AbstractHttpMessageConverter<?>) converter)
                    .setSupportedMediaTypes(supportedMediaTypes);
        }
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

}

所有这些小步骤应该足以解决我所做的所有问题,并且在我的小型POC中它可以在tomcat 9.0.x上运行。希望对您有帮助