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中修改返回的视图为简写形式.