SpringMVC
概述
1. 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架。
2. Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供
了构建 Web 应用程序的全功能 MVC 模块。
3. 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的
SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等
springMVC的环境搭建
创建WEB工程,引入开发的jar包
解决maven创建项目过慢问题
archetypeCatalog
internal
5.0.2.RELEASE
org.springframework
spring-context
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-webmvc
${spring.version}
javax.servlet
servlet-api
2.5
provided
web.xml配置SpringMVC核心控制器
在web.xml文件中配置SpringMvc核心控制器 本质就是Servlet 注意事项:配置启动加载, 配置文件路径
classpath:springmvc.xml, 拦截路径 /
web.xml配置中文乱码的过滤器
javax.servlet.jsp
jsp-api
2.0
provided
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_3_0.xsd"
version="3.0">
Archetype Created Web Application
dispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
dispatcherServlet
/
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
springmvc.xml的配置文件
开启基包扫描, 配置三大组件(处理器映射器,处理器适配器,视图解析器)
springMVC执行原理
characterEncodingFilter
/*
xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
base-package="com.itheima">
id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
name="prefix" value="/WEB-INF/pages/">
name="suffix" value=".jsp">
1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,
就会加载springmvc.xml配置文件
2. 开启了注解扫描,那么HelloController对象就会被创建
3. 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解
找到执行的具体方法
4. 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件
5. Tomcat服务器渲染页面,做出响应springMVC的组件
DispatcherServlet:前端控制器
HandlerMapping:处理器映射器
HandlAdapter:处理器适配器
View Resolver:视图解析器
mvc:annotation-driven说明
整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
根据请求的路径在很多Controller中找到对应的handler方法,返回给核心控制器
只执行handler方法,并将结果返回给核心控制器
View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名
即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户
处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
使 用 自动加载 RequestMappingHandlerMapping (处理映射器) 和
RequestMappingHandlerAdapter ( 处 理 适 配 器 ) ,
***可用在 SpringMVC.xml 配置件中使 用替代注解 处理器 和 适配器 的配置请求参数的绑定
基本数据类型或者 String 类型
请求参数名称 与 方法中的参数名称 对应, 参数多了少了无所谓
POJO类型作为参数
请求参数名称 与 实体类中的属性对应, 实体类的变量名随便
Servlet:
@Controller //装入到spring容器中
@RequestMapping("/account") //一级包
public class HelloController {
@RequestMapping("/findAccount")//二级包
public String findAccount(String accountName,Integer accountId){
System.out.println(accountId+accountName);
return "success"; //把值返回 根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件
}
}
//jsp: 发送请求 参数对应
account/findAccount?accountName=zhangsan&accountId=10
//Account User:
public class Account implements Serializable{
private String username;
private String password;
private Double money;
private User user;//Account封装User
//Controller:
@Controller //装入IOC容器
@RequestMapping("/account")//一级包
public class HelloController {
@RequestMapping("/saveAccount")//二级包
public String saveAccount(Account account){//实体类中的属性
System.out.println(account);
return "success"; //带值返回jsp页面
}
//jsp:form表单 请求参数名称 与 实体类中的属性对应
<form action="account/saveAccount" method="post">
用户:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
金额:<input type="text" name="money"><br>
姓名:<input type="text" name="user.uname"><br>
年龄:<input type="text" name="user.age"><br>
<input type="submit" value="提交"><br>
form>
//运行结果
Account{username='zhangsan', password='123', money=100.0, user=User{uname='zhangsan', age=18}}POJO 类中包含集合类型参数
自定义类型转换器
第一步: 创建一个实现类 Converter
第二步: 在springmvc文件中配置
//User:
public class User implements Serializable{
private String uname;
private Integer age;
private List<Account> accounts;
private Map<String,Account> accountMap;
//Controller:
@Controller
@RequestMapping("/account")
public class HelloController {
@RequestMapping("/updateUser")
public String updateUser(User user){
System.out.println(user);
return "success";
}
//jsp:
<form action="account/updateUser" method="post">
姓名:<input type="text" name="uname"><br>
年龄:<input type="text" name="age"><br>
用户:<input type="text" name="accounts[0].username"><br>
密码:<input type="text" name="accounts[0].password"><br>
金额:<input type="text" name="accounts[0].money"><br>
用户:<input type="text" name="accounts[1].username"><br>
密码:<input type="text" name="accounts[1].password"><br>
金额:<input type="text" name="accounts[1].money"><br>
用户:<input type="text" name="accountMap['one'].username"><br>
密码:<input type="text" name="accountMap['one'].password"><br>
金额:<input type="text" name="accountMap['one'].money"><br>
用户:<input type="text" name="accountMap['two'].username"><br>
密码:<input type="text" name="accountMap['two'].password"><br>
金额:<input type="text" name="accountMap['two'].money"><br>
<input type="submit" value="提交"><br>
form>
运行结果:
User{uname='张三', age=18, accounts=[Account{username='zhangsan', password='123', money=300.0},
Account{username='lisi', password='456', money=100.0}], accountMap=
{one=Account{username='wangwu', password='356', money=200.0}, two=Account{username='zhaoliu',
password='345', money=500.0}}}
springmvc/account/deleteAccount?date=2000-10-10常用注解
@Controller
把表现层的对象交给IOC容器
@RequestMapping
p g
错误信息:date类型转换转换错误
警告 [http-nio-8080-exec-53]
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.handleTypeMismatch
Failed to bind request element:
org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert
value of type 'java.lang.String' to required type 'java.util.Date'; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to convert from type
[java.lang.String] to type [java.util.Date] for value '2000-10-10'; nested exception is
java.lang.IllegalArgumentException
//第一步: 创建一个实现类 Converter
public class StringToDateConverter implements Converter<String,Date> {
/**
* 用于把 String 类型转成日期类型
*/
@Override
public Date convert(String source) {
DateFormat format = null;
try {
if(StringUtils.isEmpty(source)) {
throw new NullPointerException("请输入要转换的日期");
}
format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(source);
return date;
} catch (Exception e) {
throw new RuntimeException("输入日期有误");
//第二步: 在springmvc文件中配置
<mvc:annotation-driven conversion-service="converterService">mvc:annotation-driven>
<bean id="converterService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<array>
<bean class="cn.itcast.utils.StringToDateConverter">bean>
array>
property>
bean>
运行结果:springmvc/account/deleteAccount?date=2000-10-10
日期:Tue Oct 10 00:00:00 CST 2000@RequestParam
@RequestBody
@PathVariable
返回值的类型
String
作用:
用于建立请求 URL 和处理请求方法之间的对应关系
出现位置:
类上:
请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录。写的话需要以/开头。
它出现的目的是为了使我们的 URL 可以按照模块化管理
方法上:
请求 URL 的第二级访问目录
属性:
value:用于指定请求的 URL。它和 path 属性的作用是一样的。
method:用于指定请求的方式 get|post。
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和
配置的一模一样。
@RequestParam(name= "username",required=true,defaultValue="1")
作用:
把请求中指定名称的参数给控制器中的形参赋值。
属性:
value:请求参数中的名称。
required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错
作用:
用于获取请求体内容。直接使用得到是 key=value&key=value...结构的数据。
get 请求方式不适用。
属性:
required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值
为 false,get 请求得到是 null。
作用:
用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。
url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。
属性:
value:用于指定 url 中占位符名称。
required:是否必须提供占位符controller 方法返回字符串 String 可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
void
Servlet原始API可以作为控制器中方法的参数,在controller方法形参上可以定义request和response,使用request
或response指定响应结果
ModelAndView
代表 request 域数据和试图名称
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws
Exception {
System.out.println("void....");
//请求转发
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
//重定向
response.sendRedirect(request.getContextPath()+"/response.jsp");
//设置中文乱码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//直接进行响应
response.getWriter().print("你好");
}
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
System.out.println("testModelAndView...");
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
User user = new User();Request Response
使用关键字的方式进行转发或者重定向
ResponseBody 响应 json
通常和 @ResponseBody 结合使用, 将object 转成json字符串响应输出( 导出3个 jaskon)
@ResponseBody
该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的 数据如:
json,xml 等,通过 Response 响应给客户端
需要加入jackson 的包
user.setUsername("皇子");
user.setPassword("456");
user.setAge(20);
//将user存入域中
mv.addObject("user",user);
//跳转页面
mv.setViewName("success");
return mv;
}
//success.jsp 页面中EL表达式获取域中的user
${user.username}
${user.password}
${user.age}
@RequestMapping("/testRequestOrResponse")
public String testRequestOrResponse(){
System.out.println("testRequestOrResponse...");
//请求转发
return "forward:/WEB-INF/pages/success.jsp";
//重定向
return "redirect:/response.jsp";
}
com.fasterxml.jackson.core
jackson-databind
2.9.0
com.fasterxml.jackson.core
jackson-core
2.9.0
com.fasterxml.jackson.core代码
文件上传(springMVC)
jackson-annotations
2.9.0
<head>
<title>Titletitle>
//引入jquery
<script src="js/jquery.min.js">script>
<script>
//页面加载,绑定单击事件
$(function () {
$("#btn").click(function () {
//发送ajax请求
$.ajax({
//编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"hehe","password":"123","age":30}',
dataType:"json",
type:"post",
success:function (data) {
//data服务器端响应json的数据,进行解析
alert(data);
alert(data.username);
alert(data.password);
alert(data.age);
}
})
});
})
script>
head>
<input type="button" value="测试 ajax 请求 json 和响应 json" id="testJson"/>
控制器中的代码:
@RequestMapping("/testAjax")
@ResponseBody
public User testAjax(@RequestBody User user){
System.out.println("testAjax方法执行了...");
System.out.println(user);
user.setUsername("赵信");
return user;
}文件上传三要素
文件上传的原理
需要加入jar包
传统方式的文件上传
传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。 并且上传完成之后,浏览器可
能跳转
编写 jsp 页面
1.表单的enctype属性必须为 multipart/from-data
2.method 属性取值必须是 Post
3.提供一个文件选择域
当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。
enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:
key=value&key=value&key=value
当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成:
每一部分都是 MIME 类型描述的正文
-----------------------------7de1a433602ac 分界符
Content-Disposition: form-data; name="userName" 协议头
aaa 协议的正文
-----------------------------7de1a433602ac
Content-Disposition: form-data; name="file";
filename="C:\Users\zhy\Desktop\fileupload_demofile\b.txt"
Content-Type: text/plain 协议的类型(MIME 类型)
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-----------------------------7de1a433602ac--
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.4
action="/user/fileupload1" method="post" enctype="multipart/form-data">
选择文件:type="file" name="upload" />
type="submit" value="上传" />
编写控制器
Springmvc文件上传
编写 jsp 页面
@RequestMapping("/fileupload1")
public String fileupload1(HttpServletRequest request) throws Exception {
System.out.println("文件上传...");
//使用fileupload组件完成文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断, 路劲是否存在
File file = new File(path);
if (!file.exists()){
file.mkdirs();
}
// 创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> items = upload.parseRequest(request);
//遍历
for (FileItem item : items) {
//进行判断, 当前item对象是否是上传文件项
if (item.isFormField()){
//说明普通表单向
}else {
//说明上传文件项
//获取上传文件的名称
String filename = item.getName();
//把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+" "+filename;
//完成文件上传
item.write(new File(path,filename));
//删除临时文件
item.delete();
}
}
return "success";
}
action="/user/fileupload2" method="post" enctype="multipart/form-data">
选择文件:type="file" name="upload" />
type="submit" value="上传" />
编写控制器
配置文件解析器
SpringMVC跨服务器方式文件上传
分服务器的目的
spring异常处理机制
spring的拦截器机制
@RequestMapping("/fileupload2")
//注意:MultipartFile upload 与jsp页面的 name="upload" 相同
public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception {
System.out.println("mvc文件上传...");
//使用fileupload组件完成文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断, 路径是否存在
File file = new File(path);
if (!file.exists()){
file.mkdirs();
}
获取上传文件的名称
String filename = upload.getOriginalFilename();
//把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+" "+filename;
// 完成文件上传
upload.transferTo(new File(path,filename));
return "success";
}
id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
name="maxUploadSize" value="10485760">//设置上传文件的最大尺寸为10MB