練習項目:test
SpringMVC 實例 --非注解,只用于學習理解。到了spring?3.0以后或許部分東西已經過時了,在實際工作中并不一定好用。
但對于理解SpringMVC的實現方式很有幫助,在以后使用注解時,會明白是怎么個來龍去脈!
?
web.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"?
?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_2_5.xsd">
? <welcome-file-list>
??? <welcome-file>index.jsp</welcome-file>
? </welcome-file-list>
? <servlet>
? ?<!-- 框架總的控制中心, -->
? ?<!-- 當瀏覽器發送一個請求時,DispatcherServlet會對以下配置
? ??<servlet-mapping>
??? ?<servlet-name>test</servlet-name>
??? ?<url-pattern>/*.do</url-pattern>
??? </servlet-mapping>
????
? ?的url /*.do類型的請求攔截。然后初始化DispatcherServlet的一個實例(servlet的上下文,單利模式),同時讀取配置文件(xml類型)初始化里面的bean。
? ?【如何沒有指定文件的目錄和名稱時,默認會到/WEB-INF目錄下尋找以servletName加上-servlet為名的xml文件,
? ?即:約定俗成的文件路徑/WEB-INF/servletName-servlet.xml。如:/WEB-INF/test-servlet.xml】
? ?
? ? -->
? ?<servlet-name>test</servlet-name>
? ?<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
? ?<!-- 以初始化參數的方式
? ?<init-param>
? ??<param-name>contextConfigLocation</param-name> 名字不能變,必須是這個(contextConfigLocation意思是上下文配置文件位置)。
? ??
? ??【1.值是我們的配置文件路徑,包括文件名。(src包下的東西在編譯過都會跑到/WEB-INF/classes下,
? ???所以我們這里指定的路徑問/WEB-INF/classes/xxx-servlet.xml).
? ???2.當有多個配置servlet上下文配置文件時,只要我們使用“,”、“空格”等加以分割。
? ???3.也支持通配符*,如xxx-servlet1.xml,xxx-servlet2.xml,xxx-servlet3.xml等任意多個配置文件
? ???? 參數值(param-value)就可以寫成 /WEB-INF/classes/xxx-servlet*.xml了。
? ???? 或/WEB-INF/classes/spring/*.xml了。
? ??】
? ??<param-value>/WEB-INF/classes/xxx-servlet.xml,/WEB-INF/classes/xxx2.xml</param-value>
? ?</init-param> -->
<!-- 系統啟動時自動加載 初始化,否則在初次使用時加載 初始化
??//設置這一項是當系統啟動時自動加載并初始化DispatcherServlet(分發servlet,總的控制中心),以及映射bean(為DispatcherServlet具體分送到哪一個action或者controller所配置的映射bean)。如果不設置則在第一次請求
是初始化,這樣第一次請求比較慢,所以推崇第一種方式。
??-->
??<load-on-startup>1</load-on-startup>?
? </servlet>
??
? <servlet-mapping>
? ?<servlet-name>test</servlet-name>
? ?<url-pattern>*.do</url-pattern>
? </servlet-mapping>
</web-app>
注:如果使用注解可以加上-->?
????<beans>
???????????? <!-- 組件掃描:
?????????? ?? ?? 當我加載配置文件時,到我們指定的包下掃描(讀取)Java文件,尋找標注注解的地方(接口,類,方法或者其他),進行完成初始化。
???????????? ?-->
???????????? <context:component-scan base-package="test.controller"></context:component-scan>
???????????
?????? </beans>
?
servlet上下文配置文件 test-servlet.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:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
?xmlns:mvc="http://www.springframework.org/schema/mvc"
?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/util
???http://www.springframework.org/schema/util/spring-util-3.0.xsd
???http://www.springframework.org/schema/mvc
???http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
?????????? ">
???????????<!-- 當我每添加一個控制器,就會在test-servlet.xml配置一個bean和添加一個路徑的映射。
?????????? ??這樣會很麻煩。
??????????? -->
???????????
?????????? <!-- 請求映射 -->
?????????? <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" ><!--定義映射處理器: 按類別(如:HandlerMapping)尋找所有不需要id -->
?????????? ??<property name="mappings"><!-- 屬性mappings是一個映射列表 鍵值對 key=訪問路徑 value(控制器id)= id為StartController的bean -->
?????????? ???<props>
?????????? ????<prop key="start.do">startController</prop>
?????????? ????<prop key="login.do">loginController</prop>
?????????? ????<prop key="add_emp.do">addEmpController</prop>
?????????? ????<prop key="addEmp.do">addEmpSuccessController</prop>
?????????? ???</props>
?????????? ??</property>
?????????? </bean>
?????????
?????????? <bean id="startController" class="test.StartController" />?<!-- 配置控制器 -->
?????????? <!-- 對于不需要處理只做一個轉發的可以用下面的方式 -->
?????????? <bean id="loginController" class="org.springframework.web.servlet.mvc.ParameterizableViewController" >
?????????? ??<!-- 簡單的返回視圖名 通過viewName的value值login直接調用視圖解析器,轉發到login.jsp -->
?????????? ??<property name="viewName" value="login"></property>
?????????? </bean>
???????????<!-- 使用UrlFilenameViewController進行直接跳轉,必須保證url和最終返回的視圖名(返回的視圖名 也必須有對應視圖add_emp.jsp存在)保持一致。所以prop的key為"add_emp.do" -->
?????????? <bean id="addEmpController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
?????????? <bean id="addEmpSuccessController" class="test.EmpController2">
?????????? ??<property name="commandClass" value="test.Emp"></property><!-- 如何知道command是封裝Emp對象的,是這里設置的,這里會采用反射機制實例化一個指定類別的對象(也就是Emp),并且將表單參數自動注入。 -->
?????????? </bean>
???????????
???????????<!-- 視圖解析器(只需要配置一個就可以了): 從邏輯視圖到真正視圖的映射 -->
?????????? <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">?<!-- url視圖解析器 -->
?????????? ??<!-- 一般基于jsp技術實現的時候,都會幫jsp隱藏起來。什么叫隱藏呢?
?????????? ???將jsp放在WEB-INF下面,直接訪問jsp發現找不到, 避免直接訪問jsp頁面,這就叫隱藏。 -->
?????????? ??<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
?????????? ??<property name="prefix" value="/WEB-INF/jsp/" />?
?????????? ??<property name="suffix" value=".jsp" />
?????????? </bean>
???????????
?????????? </beans>
?
實體類Emp.java:
package test;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Emp {
?private int id;
?private String name;
?private String phone;
?private Date hireDate;
?public String getName() {
???????? ?return name;
?}
?public void setName(String name) {
?????????? ??this.name = name;
?}
?public String getPhone() {
????????????return phone;
?}
?public void setPhone(String phone) {
??????????? ?this.phone = phone;
?}
?
?public int getId() {
?????????? ?return id;
?}
?public void setId(int id) {
???????? this.id = id;
?}
?public Date getHireDate() {
???????????return hireDate;
?}
?public void setHireDate(Date hireDate) {
??????? this.hireDate = hireDate;
?}
?@Override
?public String toString() {
????????? ?return id+","+name+","+phone+","+new SimpleDateFormat("yyyy-MM-dd").format(hireDate);
?}
}
StartController控制器:
package test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class StartController implements Controller {
?@Override
?public ModelAndView handleRequest(HttpServletRequest request,
???HttpServletResponse response) throws Exception {
???System.out.println("成功了!");
??return new ModelAndView("start");?//視圖的邏輯名稱,具體用jsp、framemark還是其他比不知道,也不需要知道。 模塊解耦分離。
?}
}
?
控制器EmpController--以單個參數形式傳遞參數:
package test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class EmpController extends AbstractController {
?@Override
?protected ModelAndView handleRequestInternal(HttpServletRequest request,
???HttpServletResponse response) throws Exception {
??//逐個獲取表單參數,當參數很多時就會變的麻煩。如果我們可以 直接以一個對象的形式獲取就方便的多了。
??//不用擔心EmpController2控制器實現了這個功能。
??String name = request.getParameter("name");
??String phone = request.getParameter("phone");
??Emp emp = new Emp();
??emp.setName(name);
??emp.setPhone(phone);
??//service.addEmp(emp); //一般是這樣用的
??System.out.println(emp);
??return null;
?}
}
?
控制器EmpController2--以對象形式封裝表單參數:
package test; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;
/**
?* 當我每添加一個控制器,就會在test-servlet.xml配置一個bean和添加一個路徑的映射。
?* 這樣會很麻煩。
?*?
?* 視圖解析器只需要配置一個就可以了。
?* @author Administrator
?*
?*/
public class EmpController2 extends AbstractCommandController {
?/**
? * Spring 3.0 已經將AbstractCommandController類標注為過期了,她提倡我們使用注解。
? * 我們這里只是幫助大家理解如何將表單參數自動封裝為command(是一個Object類型的對象)對象的。
? *?
? * 將表單參數自動封裝到command對象中。但是需要在test-servlet.xml里配置command的類型。
? * BindException綁定異常,表單中的參數,在賦給對象Emp是需要類型轉換。當轉換出錯是異常信息就會在這里。
? *?
? * 與SimpleFormController的區別在于,method為post時onSubmit才會提交。
? */
?@Override
?protected ModelAndView handle(HttpServletRequest request,
???HttpServletResponse response, Object command, BindException bindException)
???throws Exception {
??Emp emp = (Emp)command;
??System.out.println(emp.getHireDate());
??System.out.println(emp);
??//return "success"; //當我們不返回模型視圖是我們也可以直接返回一個String字符串,這個字符串表示視圖名。
??return new ModelAndView("success");//返回邏輯視圖名,在test-servlet.xml里會得到 從邏輯視圖到真正視圖的映射。
?}
?
?public Map xxx(HttpServletRequest request, HttpServletResponse response){
??//基于慣例的處理模式,當沒有指定視圖名稱 默認根據請求路徑來返回響應的視圖名有些類似于UrlFilenameViewController。
??return null;
?}
?//注冊時間編輯器
?@Override
?protected void initBinder(HttpServletRequest request,
???ServletRequestDataBinder binder) throws Exception {
??//binder.registerCustomEditor(Date.class, new MyDateProperty());?//完全自己定義編輯器。 MyDateProperty為我們自己實現的時間編輯器。
??binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));?//自定義編輯器(spring提供的一個半成品編輯器)。
??//super.initBinder(request, binder);
?}
}
?
控制器EmpFormController:與繼承AbstractCommandController類型控制器的區別。
package test;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
public class EmpFormController extends SimpleFormController {
?/**
? * 與AbstractCommandController的區別在于FormController 當 method為post時onSubmit才會提交。
? */
?@Override
?protected ModelAndView onSubmit(Object command) throws Exception {
??// TODO Auto-generated method stub
??Emp emp = (Emp)command;
??System.out.println(emp);
??
??//return super.onSubmit(command);
??return new ModelAndView("success");
?}
?
}
?
?
MyDateProperty.java屬性編輯器:
package test;
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
?*?屬性編輯器 - 將文本轉換為xxx對象或將對象轉換成文本。
?* @author Administrator
?*/
public class MyDateProperty extends PropertyEditorSupport {
?@Override
?public String getAsText() {
??return super.getAsText();
?}
?@Override
?public void setAsText(String arg0) throws IllegalArgumentException {
??SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
??try {
???format.parse(arg0);
??} catch (ParseException e) {
???e.printStackTrace();
??}
??//super.setAsText(arg0);
?}
?@Override
?public void setValue(Object arg0) {
??super.setValue(arg0);
?}
?
}
?
add_emp.jap頁面:(其他頁面沒有實質內容就不貼了)
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>
??? <title>My JSP add_emp.jsp starting page</title>
? </head>
??
? <body>
??? This is add emp JSP page. <br>
??? <form action="addEmp.do" method="post">
??? id:<input name="id" /><br />
??? name:<input name="name" /><br />
??? phone:<input name="phone" /><br />
??? hireDate:<input name="hireDate" /><br />
??? <input type="submit" value="add" />
??? </form>
? </body>
</html>