在简单的Spring 4 REST服务上获得404

时间:2014-01-15 02:52:45

标签: spring rest

我正在尝试访问我编写的RESTful Web服务:

http://localhost:8080/dukegen/ws/family/1

但是使用浏览器中的地址栏获取404并且不知道原因。我想恢复JSON。我把Jackson 2放在了我的课堂上:

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

这是服务器输出:

Jan 14, 2014 8:29:55 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/ws/family/{familyId}] onto handler 'familyResource'
Jan 14, 2014 8:29:55 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/ws/family/{familyId}.*] onto handler 'familyResource'
Jan 14, 2014 8:29:55 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/ws/family/{familyId}/] onto handler 'familyResource'
Jan 14, 2014 8:29:55 PM org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'dispatcher': initialization completed in 360 ms
Jan 14, 2014 8:29:55 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/dukegen/ws/family/1] in DispatcherServlet with name 'dispatcher'

这是我的控制器:

@Controller
@RequestMapping("ws")
public class FamilyResource {

    @RequestMapping(value="family/{familyId}", method = RequestMethod.GET, produces="application/json")
    public @ResponseBody Family getFamily(@PathVariable long familyId) {
            .... builds Family object ....
             return family;
         }

}

这是我在web.xml中设置的调度程序:

 <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/mvcContext.xml</param-value>
        </init-param>
  </servlet>

  <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>

我的mvcContext.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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="ws.hamacher.dukegen.resource"/>

</beans>

任何帮助都会受到赞赏。

2 个答案:

答案 0 :(得分:17)

这里的一些事情都不正确。

首先,在您的请求映射中,映射应该是一致的。 您的类应映射到"/ws",产生结果的方法应为"/family/{familyId}"

在您的web.xml中,您已配置servlet以响应/ws/*,并且您的控制器再次请求映射到ws。这不起作用。

servlet拦截"/ws/*"后,不应在请求映射中重复它。 Controller仅响应其上下文中的URL模式。在您的URL中"/ws"之后的任何内容仅在控制器的上下文中。

我通常更喜欢将servlet映射到"/"以及在控制器内编码的所有其他分辨率。不过只是我的偏好。

所以正确的配置是

web.xml

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/mvcContext.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

和控制器

   @Controller
   @RequestMapping("/ws")
   public class FamilyResource {
       @RequestMapping(value="/family/{familyId}", method = RequestMethod.GET, produces="application/json")
       public @ResponseBody Family getFamily(@PathVariable long familyId) {
          .... builds Family object ....
          return family;
       }
   }

答案 1 :(得分:0)

在stackoverflow中搜索了几篇文章之后,没有找到决定性的答案,下面就是我验证的内容:

1)如果您通过以下方式在请求映射中进行设置:“ / rest / *”,web.xml或“ AbstractAnnotationConfigDispatcherServletInitializer”类的“ getServletMappings”方法中,请不要在RestController的RequestMapping。

MySpringMvcDispatcherServletInitializer.java

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { DemoAppConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/rest/*" };
    }
}   

DemoRestController.java

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value="/rest")
public class DemoRestController {

    // add code for the "/hello" endpoint

    @GetMapping(value="/hello")
    public String sayHello() {
        return "Hello World!";
    }   
}

如果您在RestController类的RequestMapping中重复“ / rest”,它将不起作用。尝试访问以下网址时,您会收到404错误:http://localhost:9091/your-context-app/rest/hello

2)当我们在请求映射中定义“ / rest / *”时,我们正在向Servlet Dispatcher指示从该上下文“ / rest”将处理所有内容。因此,通过删除“ / rest”来更改RestController的映射。输入另一个映射,例如“ / test”:

DemoRestController.java

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value="/test")
public class DemoRestController {

    // add code for the "/hello" endpoint

    @GetMapping(value="/hello")
    public String sayHello() {
        return "Hello World!";
    }   
}

3)现在,使用URL http://localhost:9091/your-context-app/rest/test/hello

访问rest服务。

这应该很好!

希望这会有所帮助。