最近负责的项目需要前后端分离,该项目使用的是struts框架,准备在该项目上先同时使用SpringMVC+Struts,然后再拆掉Struts。
整合SpringMVC步骤
首先在项目的web.xml
上添加DispatcherServlet以及Servlet映射路径关系。通过DispatcherServlet,提供了SpringMVC集中访问点。
<!-- 拦截匹配的请求 -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/dispatcher-servlet.xml</param-value>
</init-param>
<!-- 是否在启动时加载这个Servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!-- 拦截匹配规则,拦截/,例如:/user/add-->
<!-- SpringMVC的请求都改为以mvc结尾-->
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
dispathcer-servlet.xml
用于定义视图文件位置、定义全局变量、定义拦截器、开启注解扫描等。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
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"
default-autowire="byName">
<!-- 视图解析器 -->
<!-- 定义支持注解的HanlderMapping,用于分发请求 -->
<mvc:annotation-driven/>
<!-- 设置使用注解的类所在的jar包 -->
<context:component-scan base-package="com.xx.xxxx.web.controller"/>
</beans>
下面是web.xml
几乎完整的配置
<?xml version="1.0" encoding="utf-8"?>
<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">
<display-name>xxxxxx</display-name>
<context-param>
<param-name>logPath</param-name>
<param-value>/export/home/tomcat/logs/xxxx.xx.com</param-value>
</context-param>
<!-- spring listener,自动装配ApplicationContext的配置信息 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring config 部署spring-config.xml -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config.xml</param-value>
</context-param>
<!-- spring character encoding,解决页面传过来的编码问题 -->
<filter>
<filter-name>Character Encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<!-- 拦截匹配的请求 -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/dispatcher-servlet.xml</param-value>
</init-param>
<!-- 是否在启动时加载这个Servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!-- 拦截匹配规则,拦截/,例如:/user/add-->
<!-- SpringMVC的请求都改为以mvc结尾-->
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<!-- 指定欢迎页 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter-mapping>
<filter-name>Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- struts配置 -->
<!-- struts2 filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.html</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
</web-app>
接下来在POM文件中引入SpringMVC依赖的jar包。
<!-- 添加springmvc依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
就这样,导致了依赖冲突,报错如下:
java.lang.NoSuchMethodError: org.springframework.core.GenericTypeResolver.resolveTypeArguments
可以查看到GenericTypeResolver这个类在我项目中有2个!一个2.7.6版本,一个是3.1.1版本。发现是用于spring这个包冲突的,那么解决依赖冲突吧。
通过MAVEN的Show Dependencies(Ctrl+Alt+Shift+U),对这个Spring包Exclude吧。这个有时候鼠标排除有bug,那么只能手动在POM文件里添加。
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
推荐IDEA插件MAVEN Helper插件,听说很好用,然而不会,待学习,有会的小伙伴教教我=.=。
项目跑起来后又抱错,错误如下:
[org.springframework.web.servlet.DispatcherServlet] - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.validation.beanvalidation.LocalValidatorFactoryBean#0': Invocation of init method failed; nested exception is javax.validation.ValidationException: Unable to create a Configuration, because no Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:636)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:934)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:602)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:521)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:462)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
需要给项目中添加jsr303-validation包。MAVEN添加依赖
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-jsr303</artifactId>
<version>0.5</version>
</dependency>
一切正常,当我想通过@ResponseBody
将对象自动转换为JSON返回时,报错了。
@Controller
@RequestMapping("/home")
public class HomeController {
@RequestMapping("/category")
@ResponseBody
public Category category() {
return new Category(1, "默认分类");
}
/**
* 为了方便先这么写这个类~
**/
public static class Category{
public int getCateId() {
return cateId;
}
public void setCateId(int cateId) {
this.cateId = cateId;
}
public String getCateName() {
return cateName;
}
public void setCateName(String cateName) {
this.cateName = cateName;
}
public int cateId;
public String cateName;
public Category(int cateId, String cateName) {
this.cateId = cateId;
this.cateName = cateName;
}
}
}
报错描述是,页面状态码为406 Not Accepatable。
The resource identified by this request is only capable of generating responses with characteristics
not acceptable according to the request "accept" headers ().
406解析:HTTP 协议中的 406 Not Acceptable 状态码表示客户端错误,指代服务器端无法提供与 Accept-Charset 以及 Accept-Language 消息头指定的值相匹配的响应。
发现HTTP Response的content-type是text/xml
。而不是application/json
。
解决方法,需要我们添加POM依赖:
<!-- 解决注解返回JSON,抛出406错误 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.9.1</version>
</dependency>
到此第一步工作完成。
参考链接:
Validation错误
Web项目同时使用Struts2和SpringMVC
Spring MVC的web.xml配置详解
@ResponseBody返回json 报406 not acceptable