Spring MVC是一個基於MVC模式的WEB框架,它解決WEB開發中常見的問題(參數接收、文件上傳、表單驗證、國際化、等等),使用很是簡單,SpringMVC做爲Spring中的一個模塊,能夠與Spring無縫集成。css
M: Modelhtml
V:View前端
C:Controllerjava
Spring是一個輕量級的Java 開發框架,爲了解決企業應用開發的複雜性而建立。框架的主要優點之一就是其分層架構,分層架構容許使用者選擇使用哪個組件,同時爲 J2EE 應用程序開發提供集成的框架。SpringMVC以Spring框架爲核心,爲應用程序中的Web層(表現層)提出的一套優秀的解決方案。mysql
目前不少公司都使用Spring MVC,90%的招聘單位要求熟悉使用Spring MVC。web
導入spring的基本包,其它包根據須要再加入spring
導入SpringMVC的包sql
在Spring包的基礎上再加上下面的包.數據庫
<servlet>express
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 啓動的時候須要讀取spring的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</init-param>
<!-- 隨着web容器tomcat的啓動,實例化這個servlet .
數字要>=0,數字越小,啓動越早-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<url-pattern>/*</url-pattern>
<url-pattern>/</url-pattern>
兩者的區別
兩者均可以攔截全部的請求。
/*訪問jsp的時候也會攔截,/不會
public class MyController implements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
/*
* ModelAndView對象包含數據對象和視圖對象
* 視圖:目前使用jsp
*/
//實例化ModelAndView對象
ModelAndView modelAndView = new ModelAndView();
//放數據,至關於 request.setAttribute("msg", "helloworld")
modelAndView.addObject("msg", "helloworld");
//放視圖
modelAndView.setViewName("/WEB-INF/jsp/show.jsp");
return modelAndView;
}
}
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--
配置controller
name屬性就是控制器controller的訪問名字,通常加/
-->
<bean name="/myController" class="cn.com.bochy.controller.MyController"/>
<!--
加入了springmvc的不少功能
其中就有HandlerMapping,HandlerAdapter,ViewResolver
還有參數的賦值,靜態資源的訪問,json的處理等等...
-->
<mvc:annotation-driven/>
</beans>
全註解也是開發中寫的
@Controller註解必須配合掃描才能變成控制器(在spring.xml中)
Controller是單例模式,因此不能在Controller的類中定義成員變量,會形成線程安全問題.Struts2中的Action是原型模式,因此在Action中定義成員變量不會形成線程安全問題.
控制器=處理器(Handler Controllers)
SpringMVC工做流程描述
1. 用戶向服務器發送請求,請求被SpringMVC前端控制DispatcherServlet捕獲;
2. DispatcherServlet經過調用HandlerMapping(處理器映射管理對象)得到該請求對應的Handler對象(包括控制器以及Handler對象對應的攔截器)
HandlerExecutionChain對象(包含:控制器+2個攔截器);
3. DispatcherServlet 根據得到的Handler,選擇一個合適的HandlerAdapter。(附註:若是成功得到HandlerAdapter後,此時將開始執行攔截器的preHandler(...)方法)
4. 提取Request中的模型數據,填充Handler入參,開始執行Handler(Controller)。 在填充Handler的入參過程當中,根據你的配置,Spring將幫你作一些額外的工做:
HttpMessageConverter: 將請求消息(如Json、xml等數據)轉換成一個對象,將對象轉換爲指定的響應信息
數據轉換:對請求消息進行數據轉換。如String轉換成Integer、Double等
數據格式化:對請求消息進行數據格式化。 如將字符串轉換成格式化數字或格式化日期等
數據驗證: 驗證數據的有效性(長度、格式等),驗證結果存儲到BindingResult或Error中
5.Handler執行完成後,向DispatcherServlet 返回一個ModelAndView對象;
6.根據返回的ModelAndView,選擇一個適合的ViewResolver(必須是已經註冊到Spring容器中的ViewResolver)返回給DispatcherServlet ;
7. ViewResolver 結合Model和View,來渲染視圖(Model+View合成)
8. 將渲染結果返回給客戶端。
SpringMVC工做流程描述(簡易)
1. 客戶端請求提交到DispatcherServlet
2. 由DispatcherServlet控制器查詢一個或多個HandlerMapping,找處處理請求的handler。
3. DispatcherServlet將請求轉發給到handler。
4. 經過HandlerAdatper執行handler調用業務邏輯處理後,返回ModelAndView
5. DispatcherServlet查詢一個或多個ViewResovler視圖解析器,將model渲染到views。
6.將views結果顯示到客戶端。
首先在web.xml中加入springmvc的核心功能攔截器.
<!-- springmvc核心功能攔截器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-clas>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在config/spring.xml中加入:
<!--
加入了springmvc的不少功能
其中就有HandlerMapping,HandlerAdapter,ViewResolver
還有參數的賦值,靜態資源的訪問,json的處理等等...
-->
<mvc:annotation-driven />
<!--
掃描本包或者子包頭部是否有註解
@Component,@Service,@Controller,@Repository
若是有,實例化該對象,交給spring管理
-->
<context:component-scan base-package="cn.com.bochy"/>
User.java:
package cn.com.bochy.entity;
public class User {
private int id;
private String name;
//省略get,set和toString
}
UserQueryVo.java:
package cn.com.bochy.entity;
public class UserQueryVo {
private List<Integer> ids;
private List<User> users;
private Map<String, String> map;
private Date birthday;
//省略get和set方法
}
index.jsp:
<ol>
<li>簡單類型參數賦值
<form action="user/test1" method="post">
用戶名:<input name="n"/><br />
密碼:<input name="pwd"/><br />
年齡:<input name="age"/><br />
<input value="登陸" type="submit" />
</form>
</li>
</ol>
UserController.java:
package cn.com.bochy.controller;
@Controller
@RequestMapping("/user")
public class UserController{
@RequestMapping("/test1")
public ModelAndView test1(@RequestParam("n")String name,
@RequestParam(required=false)String pwd,
@RequestParam(defaultValue="110")int age){
return null;
}
}
index.jsp:
<li>非簡單類型(對象)參數賦值
<form action="user/test2" method="post">
ID:<input name="id"/><br />
用戶名:<input name="name"/><br />
<input value="登陸" type="submit" />
</form>
</li>
UserController.java:
//@RequestMapping("/test2",)
@RequestMapping(value="/test2",method={RequestMethod.POST,RequestMethod.GET})
public ModelAndView test2(User user){
return null;
}
<li>數組參數賦值
<form action="user/test3">
id1:<input name="ids" value="1"/><br/>
id2:<input name="ids" value="2"/><br/>
id3:<input name="ids" value="3"/><br/>
<input value="登陸" type="submit" />
</form>
</li>
@RequestMapping("/test3")
public ModelAndView test3(Integer[] ids){
return null;
}
必須將集合包裝成某個類的屬性賦值.
<li>list集合(簡單類型泛型約束)賦值
<form action="user/test4" method="post">
id1:<input name="ids[0]" value="1"/><br/>
id2:<input name="ids[1]" value="2"/><br/>
id3:<input name="ids[2]" value="3"/><br/>
<input value="登陸" type="submit" />
</form>
</li>
@RequestMapping("/test4")
public ModelAndView test4(UserQueryVo userQueryVo){
return null;
}
<li>list集合(非簡單類型泛型約束)賦值
<form action="user/test5" method="post">
user1:<input name="users[0].id" value="0"/>
<input name="users[0].name" value="name0"/><br/>
user2:<input name="users[1].id" value="1"/>
<input name="users[1].name" value="name1"/><br/>
user3:<input name="users[2].id" value="2"/>
<input name="users[2].name" value="name2"/><br/>
<input value="登陸" type="submit" />
</form>
</li>
@RequestMapping("/test5")
public ModelAndView test5(UserQueryVo userQueryVo){
return null;
}
<li>map集合賦值
<form action="user/test6" method="post">
1:<input name="map['k1']" value="v1"/><br/>
2:<input name="map['k2']" value="v2"/><br/>
3:<input name="map['k3']" value="v3"/><br/>
<input value="登陸" type="submit" />
</form>
</li>
@RequestMapping("/test6")
public ModelAndView test6(UserQueryVo userQueryVo){
return null;
}
<li>restful風格
<a href="user/test7/10">restful風格</a>
</li>
@RequestMapping("/test7/{id}")
public ModelAndView test7(@PathVariable("id") Integer id){
return null;
}
不能直接處理,必須使用轉換器
1) 定義轉換器,實現接口Converter<From,To>
DateConverter.java:
package cn.com.bochy.converter;
import org.springframework.core.convert.converter.Converter;
//自定義類型轉換器
public class DateConverter implements Converter<String, Date>{
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
@Override
public Date convert(String value) {
Date date = null;
try {
date = sdf.parse(value);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
2) 註冊轉換器
在spring.xml中:
<!-- 註冊轉換器 -->
<bean name="formattingConversionServiceFactoryBean"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<!--匿名bean-->
<bean class="cn.com.bochy.converter.DateConverter"/>
</set>
</property>
</bean>
3) 引用轉換器
<li>使用系統注入對象
<form action="user/test9" method="post">
用戶名:<input name="name"/><br />
<input value="登陸" type="submit" />
</form>
</li>
@RequestMapping("/test9")
public String test9(String name,Model model,HttpServletRequest request,
HttpServletResponse response,
HttpSession session){
model.addAttribute("name", name);
return "/WEB-INF/jsp/show.jsp";
}
show.jsp:
<h1>show.jsp</h1><hr/>${name}
找到tomcat的server.xml,修改
在web.xml中:
<!-- 解決post傳入中文亂碼問題 -->
<filter>
<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1) 導入json插件包
2) 定義方法
public Object 方法名(..){
//定義一個對象,存放須要轉成json的內容
return 對象;
}
UserController.java:
index.jsp:
<a href="user/test1">json測試1</a>
1) 導入包:
2) 設置form的必要屬性
3) 配置對應的resolver
4) 功能方法接收
5) 具體實現
web.xml不變.
spring.xml中加入:
<!-- 配置能夠解析多功能文件的解析器,該bean的name屬性值必須爲multipartResolver,由於spring是根據byName引用的這個bean對象 -->
<bean name="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"/>
</bean>
index.jsp:
<h1>springmvc上傳</h1>
<form action="user/upload" method="post" enctype="multipart/form-data">
用戶名:<input type="text" name="name"/><br/><br/>
上傳文件:<input type="file" name="myfile" /><br/><br/>
<input type="submit" value="上傳">
</form>
UserController.java:
package cn.com.bochy.controller;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/upload")
public String upload(String name,MultipartFile myfile,Model model,
HttpServletRequest request) throws Exception{
/*獲取輸入流*/
InputStream is = myfile.getInputStream();
/*獲取輸出流*/
String realPath = this.getRealPath(request, "/images");
String fileName = this.doFileName(myfile.getOriginalFilename());
OutputStream os = new FileOutputStream(new File(realPath,fileName));
/*copy*/
IOUtils.copy(is, os);
/*關閉流,釋放資源*/
os.close();
is.close();
return "/WEB-INF/jsp/show.jsp";
}
/**
* 傳入一個文件夾的名字返回其在服務器上的真實路徑
* 若是真實路徑不存在,直接建立
* @return
*/
private String getRealPath(HttpServletRequest request,String path){
String realPath =request.getServletContext().getRealPath(path);
File file = new File(realPath);
if(!file.exists()){
file.mkdirs();
}
return realPath;
}
/**
* 處理文件的名字,這裏只是使用UUID實現
* @param fileName
* @return
*/
private String doFileName(String fileName){
//獲取後綴
String extension = FilenameUtils.getExtension(fileName);
//獲取uuid字符串
String uuid = UUID.randomUUID().toString();
return uuid+"."+extension;
}
}
/WEB-INF/jsp/show.jsp:
<h1>上傳成功</h1>
web.xml和spring.xml不變.
index.jsp:
<h1>springmvc下載</h1>
<a href="user/download?name=hehe.jpg">下載1</a>
<a href="user/download?name=奶茶.jpg">下載2</a>
提供兩張圖片供下載:
UserController.java:
package cn.com.bochy.controller;
import java.net.URLEncoder;
import org.apache.tomcat.util.codec.binary.Base64;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/download")
public void download(String name,HttpServletRequest request,HttpServletResponse response) throws Exception{
/*設置響應的內容:下載,預覽*/
response.setHeader("Content-Disposition",
"attachement;filename="+this.setDownloadFileName(name, request));//下載
//response.setHeader("Content-Disposition", "filename="+name);//預覽
/*獲取輸入流*/
String realPath = this.getRealPath(request, "/images");
InputStream is = new FileInputStream(new File(realPath,name));
/*輸出流*/
OutputStream os = response.getOutputStream();
/*copy*/
IOUtils.copy(is, os);
/*關閉流,釋放資源*/
os.close();
is.close();
}
/**
* 傳入一個文件夾的名字返回其在服務器上的真實路徑
* 若是真實路徑不存在,直接建立
* @return
*/
private String getRealPath(HttpServletRequest request,String path){
String realPath =request.getServletContext().getRealPath(path);
File file = new File(realPath);
if(!file.exists()){
file.mkdirs();
}
return realPath;
}
/**
* 根據不一樣瀏覽器的版本設置下載文件名
* @param downloadFileName
*/
public String setDownloadFileName(String fileName,HttpServletRequest request) {
try {
if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) {//火狐瀏覽器
fileName = "=?UTF-8?B?"+(new String(Base64.encodeBase64(fileName.getBytes("UTF-8")))) + "?=";
} else { //其它瀏覽器
fileName = URLEncoder.encode(fileName, "UTF-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return fileName;
}
}
SpringMVC整合mybatis完成用戶註冊的案例
User.java:
package cn.com.bochy.entity;
public class User {
private int id;
private String name;
private String pwd;
//省略get,set和toString
}
UserMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.com.bochy.mapper.UserMapper">
<insert id="insertUser" parameterType="User">
insert into bochy_user(name,pwd) values(#{name},#{pwd})
</insert>
</mapper>
UserMapper.java:
package cn.com.bochy.mapper;
public interface UserMapper {
void insertUser(User user) throws Exception;
}
UserService.java:
package cn.com.bochy.service;
public interface UserService {
void insertUser(User user) throws Exception;
}
UserServiceImpl.java:
package cn.com.bochy.service.impl;
@Component
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public void insertUser(User user) throws Exception {
userMapper.insertUser(user);
}
}
UserController.java:
package cn.com.bochy.controller;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/registerUI")
public String registerUI() throws Exception{
//默認是forward
//return "user/register";設置了視圖解析器的前綴,後綴以後才能夠這樣簡寫.
return "forward:/WEB-INF/jsp/user/register.jsp";
}
@RequestMapping("/register")
public String register(User user) throws Exception{
userService.insertUser(user);
//return "user/success";設置了視圖解析器的前綴,後綴以後才能夠這樣簡寫.
//return "redirect:/WEB-INF/jsp/user/success.jsp";
}
}
config/db.properties:
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://localhost:3306/mybatis
db.user=root
db.password=root
config/log4j.properties:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
config/mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 讀取鏈接數據庫的配置文件 -->
<properties resource="db.properties"/>
<!--
除了Mapper和TypeAliases的其它配置,通常在這裏進行配置,很是直觀,簡單。
-->
</configuration>
config/spring_content.xml:
<!--
掃描base-package這個包,或者子包下的類。
若是發現類的頭部有註解@Component,將次類初始化,默認調用無參的構造方法
而且對象的名字,默認是類名首字母小寫
-->
<context:component-scan base-package="cn.com.bochy" />
<!--
spring整合Mybatis步驟1:配置數據庫的鏈接
具備鏈接池數據源的,通常使用c3p0或者dbcp
這裏須要指定一些屬性:
1、鏈接數據庫的4大件
2、c3p0的屬性
-->
<context:property-placeholder location="classpath:db.properties"/>
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${db.driverClass}"/>
<property name="jdbcUrl" value="${db.jdbcUrl}"/>
<property name="user" value="${db.user}"/>
<property name="password" value="${db.password}"/>
</bean>
<!-- spring整合Mybatis步驟2:配置SqlSessionFactory對象
這裏須要指定一些屬性:
1、數據源對象
2、mybatis的配置文件的位置,
也能夠不配置,將mybatis的配置文件的全部屬性,在SqlSessionFactoryBean的屬性中配置起來
通常不推薦,由於有些複雜屬性仍是配置在mybatis的配置文件中裏比較直觀。
3、mapping文件的位置
也能夠不配置,第2步中若是引用使用mybatis的的配置文件
-->
<bean name="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 掃描此包下的全部的實體類,改別名:類名/類名首字母小寫.之後引用的時候不用再寫全類名 -->
<property name="typeAliasesPackage" value="cn.com.bochy.entity"/>
</bean>
<!-- spring整合Mybatis步驟3:掃描Mapper包獲得mapper對應的的代理對象
必須符合mapper開發的全部格式:Mybatis_04_Mapper
這裏須要指定一些屬性:
1、mapper所在的包
2、SqlSessionFactory對象的名字,是一個字符串
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.com.bochy.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- spring整合Mybatis步驟4:配置DataSourceTransactionManager對象
這裏須要指定一些屬性:
1、dataSource對象
-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--
spring整合Mybatis步驟5:使用xml完成事務的配置
-->
<aop:config>
<aop:pointcut id="trPointCut" expression="execution(public * cn.com.bochy.service.impl.*.*(..))" />
<aop:advisor advice-ref="myTx" pointcut-ref="trPointCut" />
</aop:config>
<tx:advice id="myTx" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="delete*" read-only="false"/>
<tx:method name="update*" read-only="false"/>
<tx:method name="insert*" read-only="false"/>
<tx:method name="select*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:aspectj-autoproxy proxy-target-class="true"/>
config/spring_mvc.xml:
<!--
加入了springmvc的不少功能
其中就有HandlerMapping,HandlerAdapter,ViewResolver
還有參數的賦值,靜態資源的訪問,json的處理等等...
-->
<mvc:annotation-driven/>
web.xml中:
原來:
改成:
index.jsp:
<a href="user/registerUI">去註冊</a>
/WEB-INF/jsp/user/register.jsp:
<form action="user/register" method="post">
用戶名:<input name="name"/><br/><br/>
密碼:<input name="pwd"/><br/><br/>
<input type="submit" value="註冊"/>
</form>
success.jsp:
<h1>註冊成功</h1>
由於web.xml中的dispatcherServlet的url-pattern是/,對除了jsp頁面以外全部的資源都攔截.因此咱們要對靜態資源作一些特殊的配置.
如今訪問: http://localhost:8080/SpringMVC_07_Mybatis/style/images/hehe.jpg
在spring_mvc.xml中加入:
<!-- 設置訪問靜態資源的目錄
好比html,css,image,js...
-->
<mvc:resources location="/script/" mapping="/script/**"/>
<mvc:resources location="/style/" mapping="/style/**"/>
再訪問: http://localhost:8080/SpringMVC_07_Mybatis/style/images/hehe.jpg就沒問題了.
在spring_mvc.xml中加入:
<!--
設置視圖解析器的一些屬性
前綴和後綴,對forward和redirect不起做用
因此,當項目中有重定向的時候,這個標籤不該該配置.
**通常不配置
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
去UserController.java中修改返回的視圖爲簡寫形式.