今天来尝试一下搭建基于SpringMVC的RESTful标准的后端服务。
首先,什么是MVC?M-model,模型,指业务数据层,具体一点就是业务逻辑与数据库的交互;V-view,视图,用来展示数据,传统SpringMVC中控制器有返回类型ModelAndView,即返回含有数据模型与页面视图的jsp文件;C-controller,控制器,通常负责处理与用户间的交互,控制从数据库取数与返回结果到用户等。
那么,什么是REST风格的服务呢?REST(Representational State Transfer),中文可以叫表述性状态转移,有以下几个特点
简单来说,传统的MVC框架,后端和前端是部署在一起的,服务器接受请求,去数据库(缓存实质也是非关系型的键值对数据库)查询然后计算,然后和jsp进行组装渲染,直接返回一个完整的html给浏览器。而RESTful的结构下,前端和后端是可以分离部署的,浏览器访问一个页面,前端根据需要向后端发送HTTP请求,后端接收请求然后同样查询数据库再计算,把结果封装为JSON报文后返回给前端,前端把数据组装到静态页面中,生成最终展示给用户的页面。
从个人在开发中的理解,RESTful相比之下有以下几个优点:
下面正式开始环境的搭建,因为主要是讲环境搭建,一下配置内容分析先不写了,留到深入研究spring之后
首先编辑pom.xml,把需要的jar包先弄进来,如果没有自动下载的话,手动在工程项目上右键maven->update project,注意要把forcre那行勾上。
列表可以参考下面这个,这里建议spring这样一个系列的包的版本号统一在最上方以参数写入,便于集体版本替换,这点在企业开发中也是非常常用的。
<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.0modelVersion> <groupId>com.graywindgroupId> <artifactId>webdemoartifactId> <version>0.0.1-SNAPSHOTversion> <packaging>warpackaging> <properties> <spring.version>4.1.6.RELEASEspring.version> properties> <dependencies> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-coreartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-oxmartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-txartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-jdbcartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webmvcartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-aopartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-context-supportartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-testartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>log4jgroupId> <artifactId>log4jartifactId> <version>1.2.17version> dependency> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.10version> dependency> <dependency> <groupId>org.aspectjgroupId> <artifactId>aspectjweaverartifactId> <version>1.8.9version> dependency> <dependency> <groupId>javax.servletgroupId> <artifactId>jstlartifactId> <version>1.2version> dependency> <dependency> <groupId>com.fasterxml.jackson.coregroupId> <artifactId>jackson-annotationsartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.fasterxml.jackson.coregroupId> <artifactId>jackson-coreartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.fasterxml.jackson.coregroupId> <artifactId>jackson-databindartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.fasterxml.jackson.jrgroupId> <artifactId>jackson-jr-allartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>fastjsonartifactId> <version>1.2.46version> dependency> dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.pluginsgroupId> <artifactId>maven-compiler-pluginartifactId> <version>2.3.2version> <configuration> <source>1.8source> <target>1.8target> configuration> plugin> plugins> build> project>
然后修改些项目属性,右键项目properties->prject facts确定设置如下。若web module不是3.0可把勾去掉,应用后再修改到3.0.
然后到deployment assembly,设置如下
修改web.xml如下,这里有两个配置文件的路径是以classpath开头,根据上方的设置classpath会从WEB-INF/classes开始寻找,而src/main/java和src/main/resources下的内容会被装配至该路径下。
xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>mybatisdisplay-name> <welcome-file-list> <welcome-file>index.jspwelcome-file> welcome-file-list> <context-param> <param-name>contextConfigLocationparam-name> <param-value>classpath:applicationContext.xmlparam-value> context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class> listener> <servlet> <servlet-name>springmvcservlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class> <init-param> <description>spring mvc 配置文件description> <param-name>contextConfigLocationparam-name> <param-value>classpath:springmvc.xmlparam-value> init-param> <load-on-startup>1load-on-startup> servlet> <servlet-mapping> <servlet-name>springmvcservlet-name> <url-pattern>/url-pattern> servlet-mapping> <filter> <description>字符集过滤器description> <filter-name>encodingFilterfilter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class> <init-param> <description>字符集编码description> <param-name>encodingparam-name> <param-value>UTF-8param-value> init-param> filter> <filter-mapping> <filter-name>encodingFilterfilter-name> <url-pattern>/*url-pattern> filter-mapping> <context-param> <param-name>log4jConfigLocationparam-name> <param-value>classpath:log4j.propertiesparam-value> context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListenerlistener-class> listener> web-app>
现在添加application.xml和springmvc.xml以及log4j.properties至resources目录下
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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <context:component-scan base-package="webdemo.*"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> context:component-scan> beans>
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: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-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <context:component-scan base-package="webdemo.*" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> context:component-scan> <mvc:annotation-driven /> <mvc:default-servlet-handler /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/pages/value> property> <property name="suffix"> <value>.jspvalue> property> bean> <bean id="stringConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/plain;charset=UTF-8value> list> property> bean> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8value> <value>text/plain;charset=UTF-8value> <value>application/json;charset=UTF-8value> list> property> bean> list> property> bean> beans>
### set log levels ###
log4j.rootLogger = debug,stdout,D,E
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ${catalina.home}/logs/webdemo-info.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = INFO
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =${catalina.home}/logs/webdemo-error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
${catalina.home}表示日志文件会产生到tomcat的文件目录下
然后添加controller与bean
package webdemo.hello; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; 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.RestController; @RestController @RequestMapping("/") public class UserController { private static final Logger log = Logger.getLogger(UserController.class); @RequestMapping("/hello") public String hello(){ return "hello"; } @RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = "application/json") public User getUser(@PathVariable("id") int id){ log.info("get user " + id); User user = new User(); user.setId(id); user.setName("Hello"); return user; } @RequestMapping(value = "/userlist", method = RequestMethod.GET, produces = "application/json") public ListgetUserlist(){ System.out.println("get userlist"); List list = new ArrayList (); for(int i=1;i<10;i++){ User user = new User(); user.setId(i); user.setName("Hello"); list.add(user); } return list; } }
package webdemo.hello; public class User { private String name; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } }
现在启动服务器,测试下接口,因为我把server设置那里的path去掉了,所以直接输入IP与端口
现在网页上显示的就是json报文了,基本的环境也就搭建完成了。但是以网站开发角度来说,后续还有很多需要扩展的地方,比如权限控制过滤器,ajax报文的组装,错误控制,日志切面等等,后续会进一步在这个基础上扩展。
个人GitHub地址: https://github.com/GrayWind33