我有一个带有REST端点的Spring 4后端可以从我的AngularJS前端命中。问题是每当我从前端点击这些端点时,请求返回404。
当我启动Tomcat时,我查看了应用程序的日志文件,REST的url映射正由Spring正确映射到处理程序。这是显示我试图点击的网址的确切线。
2015-11-27 09:16:50,885 RMI TCP Connection(4)-127.0.0.1 INFO annotation.RequestMappingHandlerMapping Mapped
"{[/rest/userAccount/createAccount],methods=[POST]}" onto public
我尝试使用REST测试应用程序点击端点并返回相同的内容。所以我的Angular前端并没有出错。作为参考,我试图击中的确切终点是
/gravytrack/rest/userAccount/createAccount
。
这是我的Spring配置文件:
的web.xml
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- Log4j configuration loading -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.xml</param-value>
</context-param>
<!-- Bootstrapping context loading -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/gravytrack-servlet.xml
/WEB-INF/gravytrack-services.xml
<!--/WEB-INF/gravytrack-security.xml-->
</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>gravytrack.root</param-value>
</context-param>
<!-- session management listener -->
<!--<listener>-->
<!--<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>-->
<!--</listener>-->
<session-config>
<!-- session times out if no activities for 30 minutes -->
<session-timeout>30</session-timeout>
</session-config>
<!-- defining the DispatcherServlet -->
<servlet>
<servlet-name>gravytrack</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>gravytrack</servlet-name>
<url-pattern>/rest/**</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<welcome-file-list>
<welcome-file>
/index.html
</welcome-file>
</welcome-file-list>
</web-app>
gravytrack-servlet.xml中
<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:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- the application context definition for the GravyTrack DispatcherServlet -->
<context:component-scan base-package="com.gbsolutions.gravytrack.web" />
<context:component-scan base-package="com.gbsolutions.gravytrack.service" />
<context:component-scan base-package="com.gbsolutions.gravytrack.model" />
<!--<context:component-scan base-package="com.gbsolutions.gravytrack.security" />-->
<context:annotation-config />
<mvc:annotation-driven />
<!--<mvc:view-controller path="/dashboard" view-name="dashboard"/>-->
<!--<mvc:view-controller path="/login" view-name="login"/>-->
<mvc:resources mapping="/webjars/**" location="classpath:/webjars/"/>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:/messages/messages</value>
<value>classpath:/messages/errors</value>
<value>classpath:/jdbc.properties</value>
<value>classpath:/gravytrack.properties</value>
</list>
</property>
<property name="cacheSeconds" value="1"/>
</bean>
<!--<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">-->
<!--<property name="order" value="0" />-->
<!--<property name="viewClass"-->
<!--value="org.springframework.web.servlet.view.JstlView" />-->
<!--<property name="prefix" value="/WEB-INF/jsp/" />-->
<!--<property name="suffix" value=".jsp" />-->
<!--</bean>-->
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<list>
<bean
class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="html" value="text/html" />
</map>
</constructor-arg>
</bean>
<bean
class="org.springframework.web.accept.HeaderContentNegotiationStrategy" />
</list>
</constructor-arg>
</bean>
</property>
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
<!-- XML View -->
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="packagesToScan">
<list>
<value>com.gbsolutions.gravytrack.model.domain</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
</list>
</property>
</bean>
</beans>
UserAccountController
package com.gbsolutions.gravytrack.web;
import com.gbsolutions.gravytrack.model.domain.UserAccount;
import com.gbsolutions.gravytrack.service.manager.UserAccountManager;
import com.gbsolutions.gravytrack.service.validator.CreateUserAccountValidator;
import com.gbsolutions.gravytrack.web.dto.GenericJsonDTO;
import com.gbsolutions.gravytrack.web.dto.JsonFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
@Controller
@RequestMapping("/rest/userAccount")
@SessionAttributes("userAccount")
public class UserAccountController {
@RequestMapping(value="/createAccount", method = RequestMethod.POST)//, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public GenericJsonDTO createAccount(@RequestBody UserAccount userAccount, BindingResult result, SessionStatus status){
JsonFactory jsonFactory = new JsonFactory(result, "/gravytrack/dashboard");
validator.validate(userAccount, result);
if(!result.hasErrors()) {
userAccountManager.createUserAccount(userAccount);
status.setComplete();
}
return jsonFactory.getDto();
}
@RequestMapping(value="/signIn", method = RequestMethod.POST)//, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public GenericJsonDTO signIn(@RequestBody UserAccount userAccount, BindingResult result, SessionStatus status){
System.out.println("signIn entered!");
JsonFactory jsonFactory = new JsonFactory(result, "/gravytrack/dashboard");
validator.validate(userAccount, result);
if(!result.hasErrors()) {
userAccountManager.createUserAccount(userAccount);
status.setComplete();
}
return jsonFactory.getDto();
}
}
这是我使用JSP转换为Angular的应用程序。所以我不得不修改配置文件,因为它不再需要很多配置了。
正如您在 web.xml 和 gravytrack-servlet.xml 中所看到的,我已经注释掉了一些我认为不再需要的行。我完全注释掉了对Spring Security的任何引用,因为一旦我开始工作,我就必须设置它。
我尝试过很多不同的方式来改变我的配置,但似乎没有任何工作。什么可能导致这里的问题?
答案 0 :(得分:1)
<servlet-mapping>
<servlet-name>gravytrack</servlet-name>
<url-pattern>/rest/**</url-pattern>
</servlet-mapping>
servlet映射错误,应该是/ rest / *而不是两个星号。 (我想/ gravytrack是应用程序的上下文路径)
另一件事是重复的rest
网址前缀 - DispatcherServlet
已映射到/rest
,这是弹簧容器的根网址。控制器是一个子资源,并再次映射到/rest/..
- 因此生成的网址为/rest/rest/...
。
所以你需要从REST服务的RequestMapping中删除/rest
前缀 - 这里是UserAccountController上的类级别注释,它必须看起来像@RequestMapping("/userAccount")