JavaEE框架---Spring---SpringMVC入门

简介

Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2(一般老项目使用)等。

处理流程

容器

Spring和SpringMVC各有一个容器的,而Spring和SpringMVC整合时需要注意:为了使bean在一个容器需要进行以下配置。

Spring文档中的容器描述


官方文档的配置方式

了解了官方文档的配置方式,接下来开始SpringMVC技术学习

准备jar包

web.xml

配置SpringMVC+Spring只使用一个容器,该容器以Spring作为主导。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1">
	<display-name>spring4.xMVC</display-name>
	
	<filter>
		<!-- 使用Spring自带的字符编码过滤器 -->
		<filter-name>characterFilter</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>
	<filter-mapping>
		<filter-name>characterFilter</filter-name>
		<!-- 只过过滤进入SpringMVC中的请求 -->
		<servlet-name>hncu</servlet-name>	
	</filter-mapping>
	
	<!-- 加载Spring容器需要下面的listener和context-param -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<!-- name是死的 -->
		<param-name>contextConfigLocation</param-name>
		<!-- Spring容器配置文件路径 -->
		<param-value>/WEB-INF/classes/beans.xml</param-value>
	</context-param>
	
	<!-- 下面这个Servlet是进入SpringMVC的入口 -->
	<servlet>
		<servlet-name>hncu</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<!-- 采用值为空的contextConfigLocation即可把'所有bean'放在Spring容器中 -->
			<param-name>contextConfigLocation</param-name>
			<param-value></param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>hncu</servlet-name>
		<url-pattern>/hncu/*</url-pattern>
	</servlet-mapping>


	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

beans.xml

该配置文件是Spring容器的核心,Spring容器初始化时需要读取该文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	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
	" >
	<!-- 
	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
	当访问bean的方式如下时,需要使用上面这个HandlerMapping
	<bean id="/stud/one" class="cn.hncu.controller.HelloController" />
	 -->
	 
	 
	<!-- 下面这个是用来 解析classpath下 视图资源的解析器 -->
	<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
		<!-- 给定一个默认视图类型,其它视图如果给出具体的父类视图,默认继承该视图类型 -->
		<property name="defaultParentView" value="default" />
	</bean>
	
	
	<!-- 使用 @Controller 注解时早期版本采用 bean 的这种方式进行映射,现在已经过时。
		   现在采用下面 标签mvc:annotation-driven这种方式。
	<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
	 -->
	<mvc:annotation-driven />
	
	<!-- 扫描注解并且把符合规则的类在容器中生成相应的bean -->
	<context:component-scan base-package="/cn/hncu" />
	
	
	<!-- 下面两个bean通过name的值 配合 @Resource注解 给Controller的userService注入具体实现类 -->
	<!-- 模拟进行维护,只要换一个class就以换掉具体实现,
		   不用改原来实现类的代码 ,采用注解的话就要移除@Service注解
	<bean name="userService" class="cn.hncu.user.service.UserServiceImpl">
	 -->
	<bean name="userService" class="cn.hncu.user.service.UserServiceImpl2">
		<property name="userDao">
			<bean class="cn.hncu.user.dao.UserDaoImpl" />
		</property>
	</bean>
	
	
	<!-- 使用Apache的文件上传工具时,必须使用下面这个Bean 并且id/name属性必须为 "multipartResolver" -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
	
</beans>

常用配置方式

下面只是部分代码,但是却可以展现出SpringMVC中Controller主要的配置方式。

package cn.hncu.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.util.Streams;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.multipart.MultipartFile;

import cn.hncu.domain.User;

/* 实现ServletContextAware接口就可在 ServletContext初始化
 * 通过监听者模式调用ServletContextAware接口的setServletContext()方法
 * 给 ctx 赋值,这样就可以在POJO中获取到ServletContext容器了。
 */
@Controller
public class DemoController implements ServletContextAware{ 
	private ServletContext ctx; //servletContext容器
	private String basePath; //项目的本地路径
	public ServletContext getCtx() {
		return ctx;
	}
	public void setCtx(ServletContext ctx) {
		this.ctx = ctx;
	}
	public String getBasePath() {
		return basePath;
	}
	public void setBasePath(String basePath) {
		this.basePath = basePath;
	}
	@Override //该方法是ServletContextAware接口的方法!!!
	public void setServletContext(ServletContext servletContext) {
		ctx = servletContext;
		basePath = servletContext.getRealPath("/");
	}
	
	
	// http://127.0.0.1:8080/spring4.xMVC/hncu/demo1?name=张三
	// http://127.0.0.1:8080/spring4.xMVC/hncu/demo1?name=张三&age=22
	@RequestMapping(value="/demo1",method={RequestMethod.GET})
	public String demo1(String name,Integer age) { //使用包装类,否则会出现null异常
		System.out.println("demo1..."+name+","+age);
		return "res";
	}
	
	/* 使用@RequestParam注解被注解的参数默认是必填的
	 *     http://127.0.0.1:8080/spring4.xMVC/hncu/demo2    错误代码400
	 * 可以设置required为false
	 * 还可以设置前端的name为'nm'才封装给被注解的参数
	 *     http://127.0.0.1:8080/spring4.xMVC/hncu/demo2?nm=张三
	 * 
	 */
	@RequestMapping(value="/demo2")
	public String demo2(@RequestParam(required=false,name="nm") String name,Integer age) { //使用包装类,否则会出现null异常
		System.out.println("demo2..."+name+","+age);
		return "res";
	}
	
	/* 使用@PathVariable注解可以解析url路径
	 *     http://127.0.0.1:8080/spring4.xMVC/hncu/demo3/123/abc/stud
	 *     ---> path=123,path2=stud
	 */
	@RequestMapping(value="/demo3/{p}/abc/{pp}")
	public String demo3(@PathVariable(value="p") String path,@PathVariable(value="pp") String path2) { //使用包装类,否则会出现null异常
		System.out.println("demo3..."+path +","+path2);
		return "res";
	}
	
	/* http://127.0.0.1:8080/spring4.xMVC/hncu/demo4?name=张三&age=22
	 * 使用Model对象调用addAttribute()相当于 request.setAttribute()
	 * 还可在方法参数给的 req、session、resp、out 等
	 * 注意  OutputStream 和  Model 不能共存
	 */
	@RequestMapping(value="/demo4")
	public String demo4(User user, Model model,
			HttpServletRequest req,
			HttpSession session,
			HttpServletResponse resp) { //resp的输出流
		System.out.println("demo4...");
		model.addAttribute("user", user);
		return "res";
	}
	
	/* 使用@RequestHeader注解可以获得请求头信息
	 * 使用@CookieValue注解可以获得cookie的信息
	 */
	@RequestMapping(value="/demo5")
	public String demo5(@RequestHeader(name="accept")String accept,
			@CookieValue(name="JSESSIONID")String sessionid
			){
		System.out.println(accept);
		System.out.println(sessionid);
		return "res";
	}
	/* http://127.0.0.1:8080/spring4.xMVC/hncu/demo6?name=张三&age=22&addr.id=a001&addr.name=hncu
	 * 通过使用 addr.id=a001&addr.name=hncu 可以级联到User中的 Addr属性
	 */
	@RequestMapping(value="/demo6")
	public String demo6(User user,Model model){
		System.out.println(user);
		model.addAttribute("user",user);
		return "res";
	}
	
	////////////文件下载//////////////
	@RequestMapping(value="/demo7")
	public void demo7( OutputStream out, HttpServletResponse resp ) {
		
		//设置文件下载响应头
		resp.setHeader("Content-Disposition", "attachment;filename=a.txt");
		resp.setContentType("application/force-download;charact=utf-8");
		
		File file = new File(basePath+"/file/a.txt");
		if( file != null && file.isFile()) {
			try {
				InputStream in = new FileInputStream(file);
				//使用appache的工具包commons-io进行流拷贝
				Streams.copy(in, out, true);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	////////文件上传//////
	/* 需要 apache的 commons-fileupload-X.X.X.jar和commons-io-X.X.jar
	 * 同时需要 beans.xml中配置 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
	 */
	//上传单个文件
	@RequestMapping(value="/demo8")
	public String demo8(@RequestParam(name="file") MultipartFile file ) { //必须使用MultipartFile接口进行获取上传的文件
		try {
			InputStream in = file.getInputStream();
			//获取上传文件的文件名   解决中文乱码
			String fileName = new String(file.getOriginalFilename().getBytes("iso8859-1"),"utf-8");
			System.out.println( fileName );
			OutputStream out = new FileOutputStream(basePath+"/file/"+fileName);
			Streams.copy(in, out, true);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "res";
	}
	
	//上传多个文件,使用list再封装一层
	@RequestMapping(value="/demo9")
	public String demo9(@RequestParam(name="files") ArrayList<MultipartFile> files ) {
		if( files != null ) {
			for (MultipartFile file : files) {
				//当文件不存在时跳过,预防空指针
				if( file == null || file.isEmpty() ) {
					continue;
				}
				try {
					InputStream in = file.getInputStream();
					//获取上传文件的文件名   解决中文乱码
					String fileName = new String(file.getOriginalFilename().getBytes("iso8859-1"),"utf-8");
					System.out.println( fileName );
					OutputStream out = new FileOutputStream(basePath+"/file/"+fileName);
					Streams.copy(in, out, true);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		return "res";
	}
	
}

完整代码链接

完整代码链接中有一个user模块如何从Controller ===> Service ===> DAO

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章