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

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