Spring3.0 MVC的初次尝试

 

Spring的mvc在2.5的时候尝试过一次,感觉配置繁琐,比struts2还难用

但看了3.0后,感觉新的基于注解的mvc变得简单易用,而且强大。。。。

 

附上Spring mvc的简易入门教程,我使用的是注解

 

首先下载需要的jar文件,我用到的有

 

aopalliance-1.0.jar

c3p0-0.9.1.jar 

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

commons-fileupload-1.2.1.jar,commons-io-1.3.2.jar

commons-lang-2.3.jar

commons-logging-1.1.1.jar 

jackson-all-1.7.3.jar

jstl.jar

log4j-1.2.16.jar

mysql-connector-java-5.1.10-bin.jar

org.springframework.aop-3.0.4.RELEASE.jar

org.springframework.asm-3.0.4.RELEASE.jar

org.springframework.beans-3.0.4.RELEASE.jar

org.springframework.context-3.0.4.RELEASE.jar

org.springframework.core-3.0.4.RELEASE.jar

org.springframework.expression-3.0.4.RELEASE.jar

org.springframework.jdbc-3.0.4.RELEASE.jar

org.springframework.transaction-3.0.4.RELEASE.jar

org.springframework.web-3.0.4.RELEASE.jar

org.springframework.web.servlet-3.0.4.RELEASE.jar

standard.jar

commons-codec-1.4.jar 

 

其中标注为红色的包,为非必须的,可以根据情况自由选择

 

下面配置 web.xml文件

添加如下内容

 
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
 

指定spring mvc配置文件的位置

 

然后在 WEB-INF目录下建立servlet-context.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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<!-- @Controller, @Service, @Configuration, etc. -->
	<context:component-scan base-package="com.web" />

	<!-- Enables the Spring MVC @Controller programming model -->
	<mvc:annotation-driven />

	<!-- Enable placeholderConfig -->
    <bean id="placeholderConfig"  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>classpath:database.properties</value>
        </property>
    </bean>

	<!-- Configuration dataSource -->
	 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
	 	<property name="driverClass" value="${driverClass}" />
	     <property name="jdbcUrl" value="${url}"/>
	     <property name="user" value="${username}"/>
	     <property name="password" value="${password}"/>
	     <property name="acquireIncrement" value="1"/>
	     <property name="minPoolSize" value="5"/>
	     <property name="maxPoolSize" value="50"/>
	     <property name="maxIdleTime" value="1800"/>
	     <property name="maxStatements" value="0"/>
	     <property name="idleConnectionTestPeriod" value="1800"/>
	 </bean>

	<!-- Enable transactionManager -->
	<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<!-- Configuration Transaction -->
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.web.service.*.*(..))" />
	</aop:config>

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

	<!-- FileUpload Support -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

	<!-- Support static resource 
	<mvc:resources mapping="/js/**" location="/js/" />
	<mvc:resources mapping="/css/**" location="/css/" />
	<mvc:resources mapping="/images/**" location="/images/" />
	-->
	<mvc:default-servlet-handler/>

	<!-- Spring Interceptors -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/admin/*"/>
			<bean class="com.web.interceptor.MyInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>
	
	<!-- Support json ResponseBody -->
	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="messageConverters">
			<list>
				<ref bean="mappingJacksonHttpMessageConverter" />
			</list>
		</property>
	</bean>
	<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</beans>
   

配置文件方面,spring的常见配置就不在累述

其中org.springframework.web.servlet.view.InternalResourceViewResolver  这里配置视图文件位置, 我配置的是/WEB-INF/views 目录下后缀为jsp的文件

 

下面这个配置是,开启sring的文件上传功能

	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

 

这些则是配置静态资源的路径,比如js,和图片,这样就不用被spring mvc进行解析处理

    <!-- Support static resource -->
    <mvc:resources mapping="/js/**" location="/js/" />

 

 

最下面的注释为<!-- Support json ResponseBody -->的配置是,是配置spring的返回json功能

 

OK,下面开始写demo代码

 

控制器的代码如下

package com.web.controller;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.web.service.HelloWorldService;

@Controller
public class HelloWorld {

	private HelloWorldService helloWorldService;
	
	@Resource(name="helloWorldService")
	public void setHelloWorldService(HelloWorldService helloWorldService) {
		this.helloWorldService = helloWorldService;
	}

	@RequestMapping(value="/helloworld")
	@ResponseBody 
	public Map<String,Object> renderJson(@RequestParam(value="id",required=false) Integer id,HttpServletRequest req){
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("say", helloWorldService.sayHello());
		map.put("test", "value");
		return map;
	}
	
	@RequestMapping(value="/test")
	public ModelAndView renderView(){
		ModelAndView mv = new ModelAndView();
		mv.setViewName("test");
		mv.addObject("key", "value");
		return mv;
	}
	
	@RequestMapping(value="/upload")
	public ModelAndView uploadFile(@RequestParam("file") MultipartFile file){
		System.out.println(file.getContentType());
		System.out.println(file.getOriginalFilename());
		System.out.println(file.getSize());
		ModelAndView mv = new ModelAndView();
		mv.setViewName("view");
		mv.addObject("result", "success");
		return mv;
	}
}
 

 

上面三个方法分别定义了三个url路径,为/helloworld,/test,/upload

其中/helloworld 返回的是一个Map对象,这个map对象在返回给客户端的时候会自动转化为json字符串

/test 返回一个 ModelAndView 对象,这个对象里面包含了要返回的视图名称和一些展示数据,在视图页面可以使用el 和jstl进行取值展示,类似于servlet的forward

/upload 上传文件的处理路径,上传的文件会被spring自动封装为一个MultipartFile对象,可以对此对象进行相关操作。

 

spring 会自动把传递的参数注入到方法的参数中,这里有个问题,比如public Map<String,Object> renderJson(@RequestParam("name") String name) 这个方法需要一个参数名为name的参数,如果在浏览器访问这个路径的时候没有带上这个name参数,则会获得400的错误。解决办法是使用public Map<String,Object> renderJson(HttpServletRequest req) 这个方法代替,自己从req中取得参数。

 

好了,控制器的代码完成了。

下面完善service代码

 

service类为

package com.web.service;

public interface HelloWorldService {

	public String sayHello();
}
package com.web.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.web.dao.HelloWorldDao;
import com.web.service.HelloWorldService;

@Service("helloWorldService")
public class HelloWorldServiceImp implements HelloWorldService {

	private HelloWorldDao helloWorldDao;
	
	@Resource(name="helloWorldDao")
	public void setHelloWorldDao(HelloWorldDao helloWorldDao) {
		this.helloWorldDao = helloWorldDao;
	}

	@Override
	public String sayHello() {
		return helloWorldDao.sayHello();
	}

}
 

 

通过 @Service("helloWorldService") 这个注解注册名称为helloWorldService的HelloWorldServiceImp类到spring容器中

 

@Resource(name="helloWorldDao") 这个注解表示 给这个类中注入 HelloWorldDao的实现类

 

最后是Dao层的代码

package com.web.dao;

public interface HelloWorldDao {

	public String sayHello();
}
package com.web.dao.impl;

import org.springframework.stereotype.Repository;

import com.util.LogUtil;
import com.web.dao.HelloWorldDao;

@Repository("helloWorldDao")
public class HelloWorldDaoImp extends BaseDaoImp implements HelloWorldDao {

	@Override
	public String sayHello() {
		String testSql = "set names utf8";
		String insert = "insert user(name) values(?)";
		this.getJdbcTemplate().execute(testSql);
		this.getSimpleJdbcTemplate().update(insert, "test");
		//int i = 1/0;  test rollback
		LogUtil.info(testSql);
		return "hello";
	}
}
 

 

 

 

BaseDaoImp这个类作为所有Dao的基础类,提供操作JdbcTemplate和SimpleJdbcTemplate的访问接口,其中的

package com.web.dao.impl;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

public class BaseDaoImp{

	private DataSource dataSource;
	private JdbcTemplate jdbcTemplate;
	private SimpleJdbcTemplate simpleJdbcTemplate;
	
	public DataSource getDataSource() {
		return dataSource;
	}
	
	@Autowired
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
		this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
		this.dataSource = dataSource;
	}
	
	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}
	
	public SimpleJdbcTemplate getSimpleJdbcTemplate() {
		return simpleJdbcTemplate;
	}
}
   

这段代码为自动注入DataSource

 

其中//int i = 1/0;  test rollback 这行代码为测试时候,事物在出现异常后会自动回滚

 

 

至此基本告一段落。

可以看到以前的一些大段的配置,已经变为了代码里的注解,这样确实可以快速开发。 但缺点是没有使用xml配置明了。。。

还有一个不知道算不算问题,这样利用注解配置,每个controller里面有可能包含还多url路径方法,以前的action泛滥有可能变成一个类包含太多的逻辑而变的异常庞大

 

最后还发现一个问题,就是下面这段代码

    <mvc:resources mapping="/js/**" location="/js/" />
    <mvc:resources mapping="/css/**" location="/css/" />
    <mvc:resources mapping="/images/**" location="/images/" />

如果在上面的目录中含有后缀为rar的文件,则访问此文件会出现404的错误,具体原因不知。。。

用<mvc:default-servlet-handler/> 替代上面的静态资源映射,问题解决。

 

注意:这个一个bug为后来发现,所以附件的项目工程中servlet-context.xml并未更正,请自己更正。

 

最后附上项目源码,为eclipse3.5jee的web项目

你可能感兴趣的:(spring,AOP,mvc,Web,bean)