搭建springMVC框架-01

我上学那会流行的是struts,但是等我13年毕业工作的时候springMVC开始变得更加流行了,所以我又学了学springMVC,学的不算深入,但是应付开发没问题了。之前搭建的是spring-3.x的,今天下午又搭建了一次spring-4.x,耽误了很久才彻底弄好,这里还是记一下笔记吧,方便我,也方便大家。我这里只是记录搭建的步骤,不是具体的深入讲解springMVC,所以不适合那些刚刚接触springMVC的读者,不过如果只是看搭建的过程的话,完全没问题。

提前说一下,我这里使用的版本是spring-4.1.6.RELEASE版本。

1、建立工程

先建立一个maven工程,在eclipse中(这里我使用的是spring集成的eclipse,spring tool suite,简称sts,在spring的官网spring,io中可以下载到),new maven project ,选择web骨架,然后在pom中添加如下的dependency,

<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.1.6.RELEASE</version>
</dependency>

 2、编辑web.xml

   因为springMVC是一个servlet,所以要在web.xml里面写上springMVC的dispatchServlet,代码如下:

<servlet>
	<servlet-name>springDispatcherServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:mvc.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
	<servlet-name>springDispatcherServlet</servlet-name>
	<url-pattern>*.do</url-pattern>
  </servlet-mapping>

里面参数的意思是

  contextConfigLocation:springMVC的配置文件,这里写的是classpath下的mvc.xml,名字随意,然后把这个文件放在maven项目的resource文件夹下就可以了。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:p="http://www.springframework.org/schema/p"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	 http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-3.0.xsd 
	 http://www.springframework.org/schema/mvc            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">


</beans>

 其中的明明空间先不用管,等到我们使用到特定的标签的时候再加也可以的。

load-on-startup的意思是这个servlet在tomcat启动的时候就创建,而不是等到有访问的时候才会创建,一般的servlet如果不配置load-on-startup则只有在访问的时候才会实例化,而且在整个tomcat的声明周期中只实例化一次。其中参数1表示实例化的先后顺序,越小,越早创建。

然后对应的springMVC的servlet的servlet-mappiing的配置,这里配置的是*.do,表示所有的以.do结尾的请求被这个servet拦截。这里的配置是有讲究的,不要配置为/,这样的话就会覆盖tomcat的默认的servlet,而这个默认的servlet的作用十分强大,我们对js  css 图片  html等静态资源的访问全部依靠这个servet,具体一点的,当访问失败,比如404  500错误时,返回的那个页面,就是依靠的这个缺省的servlet。当然我们可以将springMVC的servlet配置为/,但是这样的话对于静态资源的访问我们必须还要配置别的东西,我印象中里是配置<resouce>什么的,如果你非要配置为/,那么可以去查看<resource>,这里我配置为*.do。

3、测试

现在就可以启动tomcat测试了,这里我们先进入到dispatcherServlet的源码中,在他的构造方法处设置断点,然后debug启动tomcat,如果发现在设置的断点处停下,就说明配置的成功,至少是dispatcherServlet启动了,然后跑完程序后发现tomcat启动没有报错,就可以了写Hello World了。

4、继续配置

   先修改mvc.xml,我依次讲解每个的意思。

<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>

   上面配置的是viewResolver,有很多个viewResolver,因为我们从controller跳出后转向的是jsp,所以使用InternalResourceViewResolver,如果跳出后转向的是velocity,那么就要使用不同的viewResolver,这个等集成velocity的时候再细说。viewResolver的配置

     ·prefix   要跳转的view的位置,也就是在controller中我们返回的ModelAndView或者是String前面补充的前缀,这里/WEB-INF/jsp表示的是WEB-INF下的jsp文件件下。

     ·suffix   要跳转的view的后缀,也就是在controller中我们返回的ModelAndView或者是String前面补充的前缀,这里用的是jsp,如果是velocity,则可以配置为.vm。

    在上面的配置中,如果我在controller中返回的是string   “hello”,且这个controller没有标注@responseBody,那么将跳转到 /WEB-INF/jsp/hello.jsp中。这里的跳转类似于servlet中的forward。

继续配置controller的扫描路径:

<!-- 开启注解 -->
<mvc:annotation-driven />
<!-- 配置扫描路径 -->
	<context:component-scan base-package="com.controller"
		use-default-filters="false">
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Controller" />
	</context:component-scan>

这个配置很重要,在spring的配置文件中,我们可以定义很多的bean,其中就包括我们自己定义的bean,比如service dao  controller,但是spring给我们提供了扫描的机制,也就是不用自己在配置文件中写上bean了,而是提供一个机制让spring去自动得将我们需要的bean放入spring的容器中,spring的解决办法是提供一个路径,然后spring会在这个路径中搜索所有的类,如果满足一定的条件就会实例化这个类,然后放入spring的容器中,这里的条件就是用的注解,即如果这个类上有@controller  @service   @dao   @conmponent之一的话就会实例化放入ioc容器。springMVC这里的配置也是一样的。

<mvc:annotation-driven/>   这个的意思是开启注解的功能,

<context:component-scan ...../>这个的作用是配置扫描的路径,use-default-filters  这个的配置很有来头,默认的配置是true,表示只要这个类上面有@controller  @service  @dao  @component这四个的一个,就会放入springmvc的容器,我们这里配置了false,表示禁用这个默认的值,而是指定扫描的注解为@controller,也可以使用排除  即<context:exlude-filter..../>,但是具体的exclude和include怎么配合使用我没有研究,这里只使用<include >的话,的确是不会扫描@service @dao  @component的。我已经做过实验。

  完成这个配置,可以做个hello world的测试了,我的测试代码如下:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Test1 {
	@RequestMapping("/hello.do")
	public String hello(){
		return "hello";		
	}	
}

 在 WEB-INF/jsp文件夹下创建 hello.jsp,然后访问 localhost:8080/app/hello.do    其中app表示你的web应用的contextPath,如果出现正常的页面,则表示配置成功。

5、不跳转到页面的配置

    有时候,我们在前段html可能仅仅是请求一个true false,或者是一个对象的json字符串,这个时候就不需要再跳转到view了,这里需要在controller中配置@responseBody,表示执行完这个方法后不再跳转到view了。关于这个方法的返回值有很多讲究,比如返回的是个string,或者是返回的是个list又或者是map,或者是个bean,还要涉及到编码格式,返回的http响应头等。

这个就要涉及到MessageConvertor了,我们继续在xml中配置如下:

<bean
		class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="messageConverters">
			<list>
				<bean class="org.springframework.http.converter.StringHttpMessageConverter">
					<property name="supportedMediaTypes">
						<list>
							<value>text/plain;charset=UTF-8</value>
						</list>
					</property>
				</bean> 
				 
				<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
					<property name="supportedMediaTypes">
						<list>
							<value>applicaton/json;charset=UTF-8</value>
						</list>
					</property>
				</bean> 
			</list>
		</property>
	</bean>

 先注意:一定要把这个配置放在<mvc:annotation-driven/>前面,否则这个配置不起作用。在配置spring的xml时我总结的经验就是一定要将<bean/>的配置放在其他的配置的前面,因为其他的配置会使用到bean的配置。

这个bean   RequestMappingHandlerAdaptor里面有个叫做messageConverters的list的属性,表示配置的消息转换器,springMVC自动的就会带有很多个消息转换器,比如这里配置的String的转换器  StringHttpMessageConverter,但是我们做实验的时候发现她对中文的支持不了,中文的全部是乱码,我做的实验室这样的:先注释掉上面配置的<bean  RequestMappingHandlerAdaptor/>  然后访问如下的代码

@Controller
@RequestMapping("/hello")
public class HelloWorldController {
 
	@RequestMapping("/world.do")
	@ResponseBody
	public String hello(){
		System.out.println("fsafas");
		return "hello    你好";
	}
}

 请一定要将刚刚配置的bean注释掉,然后访问 这个路径,发现返回的是 hello   ??,中文的乱码了,说明他的默认的编码字符集不支持中文,我们到StringHttpMessageConverter的源码中一看,他有个属性:DEFAULT_CHARSET 是 ISO-8859-1的,不用多想,一定时没有指定编码他才是用了这个不支持中文的字符集。再打开我们配置的bean,返现就可以返回正常的中文了。

至于下面的MappingJackson2HttpMessageConverter,这个是处理bean的,像我们定义的person类,ArrayList啊,HashMap啊,这个转化器是转化为json字符串返回给浏览器,我们到这个类的源码中看一下他的javadoc

 Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter} that  can read and write JSON using <a href="http://jackson.codehaus.org/">Jackson 2.x's</a> {@link ObjectMapper}.   <p>This converter can be used to bind to typed beans, or untyped {@link java.util.HashMap HashMap} instances.  <p>By default, this converter supports {@code application/json} and {@code application/*+json}.  This can be overridden by setting the {@link #setSupportedMediaTypes supportedMediaTypes} property. <p>The default constructor uses the default configuration provided by {@link Jackson2ObjectMapperBuilder}.  <p>Compatible with Jackson 2.1 and higher.

大致的翻译是能够转化bean和hashamap,将其转化为json,能够通过覆写supportedMediaTypes属性来改变转化的格式。也就是说我们在配置中写的<property name="supportedMediaTypes".../>默认就是application/json类型的,然后我们再看看他的编码是什么,我们到他的父类中AbstractJackson2HttpMessageConverter,发现有个属性DEFAULT_CHARSET  就是UTF-8的,所以貌似我们这里的配置只要写上<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter实验的java代码如下:

//我们新建立一个person类
public class Person {
	public Person(){}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}
//controller如下  我们是通过ajax的方式访问的world2.do

@Controller
@RequestMapping("/hello")
public class HelloWorldController { 
	@RequestMapping("world2.do")
	@ResponseBody
	public Person person(){
		return new Person("张三", 20);		
	}
	
	@RequestMapping("/world.do")
	@ResponseBody
	public String hello(){
		System.out.println("fsafas");
		return "hello    你好";
	}
}

访问的ajax代码如下,我们使用的是jquey访问的请一定要加入jquey的js
<script type="text/javascript" src="jquery-1.11.3.js"></script>
<script type="text/javascript">
  $(function(){
	  $.ajax({
		  
		  url:"/yourApp/hello/world2.do",
		  success:function(data){
			  if(data){
				  alert(data.name);
			  }else{
				  alert("失败");  
			  }  
		  }		  
	  });
  });
</script>

 我们访问这个jsp,然后就会alert出   ”张三“。

然后我们把配置的  <property name="supportedMediaTypes">  注释掉,发现,结果一样,证明了我们的猜想。。

我们在测试一个map的,修改之前的HelloWorldController ,添加如下的模块

@RequestMapping("map.do")
	@ResponseBody
	public Map<String,String> map(){
		Map<String,String> m = new HashMap<String, String>();
		m.put("name", "李四");
		m.put("age", "22");
		return m;		
	}

 然后仍然使用ajax访问,我的ajax的代码如下:

<script type="text/javascript" src="jquery-1.11.3.js"></script>
<script type="text/javascript">
  $(function(){
	  $.ajax({
		  
		  url:"/yourApp/hello/map.do",
		  success:function(data){
			  if(data){
				  alert(data.name);
			  }else{
				  alert("失败");  
			  }  
		  }		  
	  });
  });

</script>

 我的实验是可以的。

我记得之前的springMVC3中是可以序列化list的,再次做个实验:继续在上面的HelloWorldController中加入如下代码:

@RequestMapping("list.do")
@ResponseBody
public List<String> list(){
	List<String> l = new ArrayList<String>();
	l.add("中国");
	l.add("捷克");
	l.add("日本");
	return l;
}

 然后修改之前的jsp,如下

<script type="text/javascript" src="jquery-1.11.3.js"></script>
<script type="text/javascript">
	$(function() {
		$.ajax({

			url : "/velocity/hello/list.do",
			success : function(data) {
				if (data) {
					for(var i=0;i<data.length;i++){
						alert(data[i]);
					}
				} else {
					alert("失败");
				}
			}
		});
	
	});
</script>

 运行后访问,可以发现,正常,说明是可以序列化list的。

   

   

  

相关推荐