springmvc简单入门

来源:互联网 发布:js c标签的if else 编辑:程序博客网 时间:2024/05/29 08:19

作为当前最火的mvc框架,优点:性能快,开发简单,能很方便的支持restfull风格,可以直接返回json和xml格式。

一:简单入门

先建一个maven工程spring_mvc
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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.julyday</groupId><artifactId>spring_mvc</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>spring_mvc Maven Webapp</name><url>http://maven.apache.org</url><properties><commons-lang.version>2.6</commons-lang.version><slf4j.version>1.7.6</slf4j.version><spring.version>4.1.3.RELEASE</spring.version><jackson.version>2.5.4</jackson.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-framework-bom</artifactId><version>${spring.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-oxm</artifactId></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>${commons-lang.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version><exclusions><exclusion><artifactId>slf4j-api</artifactId><groupId>org.slf4j</groupId></exclusion></exclusions></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.3</version></dependency><!-- xml格式输出 --><dependency>    <groupId>com.thoughtworks.xstream</groupId>    <artifactId>xstream</artifactId>    <version>1.4.7</version></dependency></dependencies></project>


<?xml version="1.0" encoding="utf-8"?><web-app xmlns="http://java.sun.com/xml/ns/javaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  version="3.0"  metadata-complete="true">  <display-name>spring_mvc</display-name>    <!-- spring上下文 -->  <context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 编码utf-8 --><filter><filter-name>encodingFilter</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><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- Spring MVC的核心  DispatcherServlet-->  <servlet>  <servlet-name>mvc-dispatcher</servlet-name>  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  <init-param>        <param-name>contextConfigLocation</param-name>        <param-value>classpath:spring-mvc.xml</param-value>  </init-param>  <load-on-startup>1</load-on-startup>  </servlet>  <servlet-mapping>  <servlet-name>mvc-dispatcher</servlet-name>  <url-pattern>/</url-pattern>  </servlet-mapping></web-app>
这里我们还是用到了spring,虽然我们这个项目可以不整合spring,但是在实际的开发中不运用spring几乎是不可能的。这里我们把controller层交给springmvc处理,service层交给spring来处理,我们接下来的service层也是模拟出来的,不是真正的经过数据库的
spring配置文件:applicationContext.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: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"><!-- 使用@ Resource 、@ PostConstruct、@ PreDestroy --><!-- context:component-scan 会一并扫描,如果注解在base-package下使用可以去掉该注解 --><context:annotation-config /><!-- 自动扫描 -->  <context:component-scan base-package="com.julyday"><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller" /></context:component-scan> <!--<context:component-scan base-package="com.julyday.service.impl"/>--></beans>
这里我们只模拟了service层,所有注释的自动扫描也是可以的,但是最后还是用没注释的,以后我们如果是和数据库相连的话是不会错的。
springmvc配置文件:spring-mvc.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: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"><!-- 启用Spring基于annotation的DI, 使用户可以在Spring MVC中使用Spring的强大功能。 激活 @Required @Autowired,JSR 250's @PostConstruct, @PreDestroy and @Resource 等标注 --><context:annotation-config /><!-- DispatcherServlet上下文, 只管理@Controller类型的bean, 忽略其他型的bean, 如@Service --><context:component-scan base-package="com.julyday"><context:include-filter type="annotation"expression="org.springframework.stereotype.Controller" /></context:component-scan><!-- <context:component-scan base-package="com.julyday.controller"/> --><!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 --><mvc:annotation-driven /><!-- 静态资源处理,resources, css, js, imgs --><!--<mvc:resources mapping="/resources/**" location="/resources/" /><mvc:resources mapping="/js/**" location="/js/" />    <mvc:resources mapping="/images/**" location="/images/" />    <mvc:resources mapping="/css/**" location="/css/" />-->        <!-- 容器默认的DefaultServletHandler处理 所有静态内容与无RequestMapping处理的URL -->  <mvc:default-servlet-handler/>      <!-- 配置ViewResolver。 可以用多个ViewResolver。 使用order属性排序。 InternalResourceViewResolver放在最后。 --><beanclass="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"><property name="order" value="1"/><!-- 在没有扩展名时即: "/user/1" 时的默认展现形式 --><!-- 以json作为默认返回,方便调用,省去后缀.json --><!--  <property name="defaultContentType" value="application/json"></property>--><!-- 扩展名至mimeType的映射,即 /user.json => application/json --><property name="mediaTypes"><map><!-- 告诉视图解析器,返回的类型 /user/123.xml 将返回xml格式数据 /user/123.json 将返回json格式数据 /user/123.html 将返回html格式数据 favorParameter = false /user/123?format=xml //将返回xml数据 /user/123?format=json //将返回json数据 --><entry key="json" value="application/json" /><entry key="html" value="text/html" /><entry key="xml" value="application/xml" /></map></property><!-- 用于开启 /userinfo/123?format=json 的支持 --><property name="favorParameter" value="true" /><property name="defaultViews"><list><!-- for application/json --><beanclass="org.springframework.web.servlet.view.json.MappingJackson2JsonView"></bean><!-- for application/xml --><bean class="org.springframework.web.servlet.view.xml.MarshallingView"><property name="marshaller"><bean class="org.springframework.oxm.xstream.XStreamMarshaller" /></property></bean></list></property><property name="ignoreAcceptHeader" value="true" /></bean><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="viewClass"value="org.springframework.web.servlet.view.JstlView" /><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" /></bean><!--200*1024*1024即200M resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="maxUploadSize" value="209715200" /><property name="defaultEncoding" value="UTF-8" /><property name="resolveLazily" value="true" /></bean></beans>
在看springmvc配置之前,大家可以参考springmvc流程这篇文章,文章很详细的讲解了springmvc的流程,大家会知道HandlerMapping,HandlerAdapter,Controller,ViewResolver,View。HandlerMapping,HandlerAdapter 这个springmvc有默认的,我们不需要配置,Controller我们自己写的逻辑,交给springmvc管理,ViewResolver这个就是需要我们配置的,在上文中,View视图我们自己写的,最后只要在controller里面告诉springmvc,我们返回哪个视图即可。
package com.julyday.entity;public class User {private int id;private String name;private int age;//getter setter}

</pre><pre name="code" class="java">@Service("userService")public class UserServiceImpl implements UserService{@Overridepublic User findByid(Integer id) {System.out.println("UserServiceImpl findByid"+id);User u = new User("julyday",18);u.setId(1);return u;}@Overridepublic List<User> findAll() {User u1 = new User("julyday",18);u1.setId(1);User u2 = new User("zhangsan",28);u2.setId(2);List<User> list = new ArrayList<User>();list.add(u1);list.add(u2);return list;}}
@Controller@RequestMapping("/user")public class UserController {private static Logger log = LoggerFactory.getLogger(UserController.class);@Autowiredprivate UserService userService;// 本方法将处理/user/hello@RequestMapping(value = "hello")public String hello() {return "hello";}}
@Controller:告诉springmvc,管理这个controller。
@Autowired:注入service。
@RequestMapping:这个可以在类和方法上,访问的时候是类上值+方法上值,他还可以拦截指定的请求方式,请求参数等。
hello.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>hello.jsp</title></head><body>this is julyday hello.jsp</body></html>
return "hello";springmvc会更具我们的配置信息InternalResourceViewResolver,返回我们需要的实体hello.jsp。

二:restfull风格的支持

@RequestMapping("/restful/{userId}")public String restful(@PathVariable("userId") Integer id,Map<String, Object> model) {log.debug("UserController restful {}", id);User user = userService.findByid(id);model.put("user", user);return "user/view";}
<%@ page language="java" contentType="text/html; charset=utf-8"    pageEncoding="utf-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>view.jsp</title></head><body>欢迎您:${user.name}</body></html>
@PathVariable:获取url请求上的动态参数,这个让springmvc很简单就支持restfull风格,注解的value必须要在@RequestMapping中用{}表示出来,并且名称一致。
当然我们还可以这样:
@RequestMapping("/restful2/{userId:[0-9]+}/{param}")public String restful2(@PathVariable("userId") Integer id,@PathVariable("param")String param,Map<String, Object> model){log.debug("UserController restful id: {} and param: {}",id,param);User user = userService.findByid(id);model.put("user", user);return "user/view";}
userId我们用了正则的方式,我们还可以是多个参数的restfull。

三:返回格式及文件下载

@RequestMapping("request")public String request(HttpServletRequest request){Integer id = Integer.valueOf(request.getParameter("userId"));log.debug("UserController request {}",id);User user = userService.findByid(id);request.setAttribute("user", user);return "user/view";}
我们可以在参数中加入HttpServletRequest这样,直接访问request,response,session等servlet参数。
@RequestMapping("all")public @ResponseBody String findAll(){List<User> list = userService.findAll();return JSON.toJSONString(list);}@RequestMapping("all2")public ResponseEntity<List<User>> findAll2(){List<User> list = userService.findAll();return new ResponseEntity<List<User>>(list, HttpStatus.OK);}
@ResponseBody:通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
这里@ResponseBody和ResponseEntity效果都是一样的。
细心发朋友发现我们参数用过Model和Map来存放参数,除了这两种之外还有ModelAndView,他们最后都会被springmvc封装成ModelAndView。

@RequestMapping(value="/upload", method=RequestMethod.GET)public ModelAndView showUploadPage(ModelAndView model){model.setViewName("upload");return model;}@RequestMapping(value="/doUpload", method=RequestMethod.POST)public String doUploadFile(@RequestParam("file") MultipartFile file) throws IOException{if(!file.isEmpty()){log.debug("doUpload file: {}", file.getOriginalFilename());FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\\temp\\", System.currentTimeMillis()+ file.getOriginalFilename()));}return "success";}

@RequestParam:请求参数,默认是必须要的,可以修改required=false,来设置非必输,需要注意的是,如果是false,基本类型的话,如果没有传值,会有异常出现,所有最好用包装类来接收参数。

四:过滤器

springmvc过滤器可以有两种接口去实现:HandlerInterceptor,WebRequestInterceptor,两种方式差不多
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {System.out.println("MyInterceptor preHandle...");return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {if("/spring_mvc/user/upload/".equals(request.getRequestURI())){modelAndView.setViewName("user/add");}System.out.println("MyInterceptor postHandle..."+handler.toString());}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("MyInterceptor afterCompletion...");}}

public class WebInterceptor implements WebRequestInterceptor {@Overridepublic void preHandle(WebRequest request) throws Exception {System.out.println("WebInterceptor preHandle ...");}@Overridepublic void postHandle(WebRequest request, ModelMap model) throws Exception {System.out.println("WebInterceptor postHandle ...");}@Overridepublic void afterCompletion(WebRequest request, Exception ex)throws Exception {System.out.println("WebInterceptor afterCompletion ...");}}

HandlerInterceptor中preHandle方法:返回false后面就不再执行,包括controller。
而WebRequestInterceptor的preHandle是没有返回值的。当然不是我们写了一个类springmvc就知道要走这个过滤器。
<mvc:interceptors>    <bean class="com.julyday.interceptor.MyInterceptor"></bean>    <mvc:interceptor>    <mvc:mapping path="/user/upload2"/>    <bean class="com.julyday.interceptor.WebInterceptor"></bean>    </mvc:interceptor>    </mvc:interceptors>
springmvc配置文件加上如上信息。
MyInterceptor我们没有配置mapping,他是过滤所有的controller的,而WebInterceptor我们是配置了mapping的,他是过滤指定url的。
这里说明下,我们的MyInterceptor过滤/spring_mvc/user/upload/时会指定到另一个视图,其中最后的“/”也是必须的。
upload2通过控制台我们可以看到MyInterceptor的preHandle方法先执行,WebInterceptorpreHandle后执行,后面依次是controller,WebInterceptor postHandle ,MyInterceptor postHandle,WebInterceptor afterCompletion ,MyInterceptor afterCompletion,这个是怎么理解的呢。
我们用过年开车回家的例子来说明:比如上海到安徽,经过江苏高速MyInterceptor,安徽高速WebInterceptor,然后到家controller,回来我们先是安徽高速,再是江苏高速,回去上班由于我们生产上出现问题,一路超速行驶,然后收到了安徽高速的罚单,后面又收到了江苏高速的罚单。

最后放上全部的代码:代码下载




0 0
原创粉丝点击