SpringMVC
SpringMVC简介
1: avaEE三层结构
Web层:接受页面的请求参数servlet 封装参数到javabean 给页面做响应jsp
service层: 处理业务 处理事务 spring框架
dao层:用来和数据库进行交互 mybatis框架
springmvc框架是对web层的封装 市面又称它为mvc框架
作用:将逻辑,业务,视图相分离的一种思想 各自专注于做自己的事情
M: model(模型) javabean
V: VIEW(视图) jsp
C: Controller(控制器) servlet
结论:springMVC是spring提供的一个子框架,是为web层提供的一个框架,实现了mvc思想所以又被称为MVC框架,可以和spring无缝连接到一起。后期我们要将3大框架做整合完成业务开发(SSM框架)
企业:ssm架构
2: SpringMVC的请求流程
3: SpringMVC的入门案例
步骤实现
1 导入依赖
ioc坐标
springmvc坐标(spring-web,spring-webmvc)
2 创建类和方法编写业务逻辑
3 配置前端控制器
4 配置springmvc的配置文件
依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
</dependencies>
User
@Controller
public class User {
@RequestMapping(value = "/hello")
public String hello(){
System.out.println("hello,浏览器访问到我了..");
return "/jsp/index.jsp";
}
}
web.xml
<web-app>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.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>
</web-app>
spring-mvc.xml
<beans xmlns="http://www.springframework.org/schema/beans"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="cn.itcast.web"></context:component-scan>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
</beans>
demo1.jsp
<html>
<body>
<h2>Hello Springmvc!</h2>
</body>
</html>
4:执行流程图
5:Springmvc中的组件
1) DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2) < mvc:annotation-driven >
自动加载映射器和适配器 简化开发
3) 视图解析器
<!--视图解析器
页面地址的拼接:
prefix + 方法返回值 + suffix
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置页面地址的前缀-->
<property name="prefix" value="/jsp/"></property>
<!--配置页面地址的后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
6:基础注解@RequestMapping(…)
配置浏览器请求路径
/*
* @RequestMapping:映射浏览器地址路径的
* 1 可以配置在类上,也可以配置在方法上,为了区分模块方法
* 2 属性可以使用value也可以使用path
* 3 默认接受所有访问的提交方式(post,get,delete,put..)但是也可以指定请求方式
* //method = RequestMethod.POST method = RequestMethod.GET
* 4 默认请求参数可有可无 但是也可以指定页面必须传递某些参数
* //params={"参数1","参数2"}
扩展:name属性 做当前方法的注释 没有特殊的含义 用来区分不同方法要完成的功能 给程序员区分
* */
@RequestMapping(name="这个方法是用来做用户查询的",value = "/hello",method = RequestMethod.GET,params = {"username","password"})
public String hello(){
System.out.println("浏览器访问到我了..");
return "demo1"; // 请求转发 ---视图解析器 前缀+主体+后缀
}
7: Springmvc中的参数绑定
中文乱码的处理
在web.xml里面配置spirngmvc提供好的中文乱码过滤器即可 (CharacterEncodingFilter)
<!--springmvc提供好了处理中文乱码的filter 名称叫做:charactherEncodingFilter-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--指定使用的是utf-8编码-->
<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>
<form action="${pageContext.request.contextPath}/user/find.do" method="post">
用户名:<input type="text" name="username">
密码:<input type="text" name="password">
<input type="submit" value="访问">
</form>
参数绑定:将页面请求的参数进行接受且封装
#### 封装简单数据类型
页面的请求的参数名 = 方法的参数名
//简单数据: 要求:参数上的参数名要和页面的name属性名一致
@RequestMapping(name="这个方法是用来做用户查询的",value = "/find.do",method =
RequestMethod.POST,params = {"username","password"}) //注解配置的映射
public String find(String username,String password){
System.out.println("User访问到我了..find");
System.out.println(username+":"+password);
return "demo1"; //请求转发 会去视图解析器中 前缀+demo1+后缀
}
<%--简单数据的封装--%>
<form action="/param1" method="post">
用户名:<input type="text" name="username" />
年龄:<input type="text" name="age" />
<input type="submit" value="提交" />
</form>
@RequestMapping(value = "/param1",name = "简单数据的封装")
public String param1(String username,String age){
System.out.println(username);
System.out.println(age);
return "success";
}
封装对象数据类型
页面的请求参数名 = 对象中属性名
<%--对象数据的封装--%>
<form action="/param2" method="post">
用户名:<input type="text" name="username" />
年龄:<input type="text" name="age" />
<input type="submit" value="提交" />
</form>
@RequestMapping(value = "/param2",name = "对象数据的封装")
public String param1(User user){
System.out.println(user);
return "success";
}
封装复杂类型的数据(数组和集合list和map)
list和map不能直接出现在方法的形参上,如果想封装可以作为对象的list和map属性进行封装
list: 页面的请求参数名 =list集合属性名[索引].属性名
map: 页面的请求参数名 =map集合属性名[key值].属性名
@Data
public class User {
// 简单数据
private String username;
private Integer age;
// 复杂数据(list)
private List<Account> lists;
// 复杂数据(map)
private Map<String,Account> maps;
}
<%--复杂数据list--%>
<form action="/param3" method="post">
用户名:<input type="text" name="username" />
年龄:<input type="text" name="age" />
账户名:<input type="text" name="lists[0].name" />
金额:<input type="text" name="lists[0].money" />
账户名:<input type="text" name="lists[1].name" />
金额:<input type="text" name="lists[1].money" />
<input type="submit" value="提交" />
</form>
@RequestMapping(value = "/param3",name = "复杂数据list封装")
public String param3(User user){
System.out.println(user);
return "success";
}
<%--复杂数据map--%>
<form action="/param4" method="post">
用户名:<input type="text" name="username" />
年龄:<input type="text" name="age" />
账户名:<input type="text" name="maps['key1'].name" />
金额:<input type="text" name="maps['key1'].money" />
账户名:<input type="text" name="maps['key2'].name" />
金额:<input type="text" name="maps['key2'].money" />
<input type="submit" value="提交" />
</form>
@RequestMapping(value = "/param4",name = "复杂数据map封装")
public String param4(User user){
System.out.println(user);
return "success";
}
<%--复杂数据数组--%>
<form action="/param7" method="post">
爱好:
<input type="checkbox" name="hobby" value="吃饭">吃饭
<input type="checkbox" name="hobby" value="睡觉">睡觉
<input type="checkbox" name="hobby" value="敲代码">敲代码
<input type="submit" value="提交" />
</form>
@RequestMapping(value = "/param7",name = "复杂数据数组的封装")
public String param7(String[] hobby){
System.out.println(Arrays.toString(hobby));
return "success";
}
请求参数的中文乱码解决方案:配置springmvc提供好的字符编码过滤器即可
<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-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
二 自定义类型转化器【掌握】
springmvc的内置类型转化器只支持:xxxx/xx/xx/格式,我们需要自定义日期类型转化器支持通用格式
springmvc自定义的日期类型转换器不通用 只能转换2018/11/10类型日期 不能转换2018-11-10
需求:自定义一个通用的类型转换器 覆盖掉springmvc的日期类型转换器
自定义类型转化器:StringToDataConverter
package cn.itcast.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringToDataConverter implements Converter<String,Date> {
@Override //s代表的就是页面传递的参数
public Date convert(String s) {
SimpleDateFormat simpleDateFormat =null;
Date date =null;
try {
if (s.contains("/")){
simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
}else{
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
}
date = simpleDateFormat.parse(s);
}catch (Exception e){
e.printStackTrace();
}
return date;
}
}
配置:spring-mvc.xml
<!--指定使用自己的类型转换器-->
<mvc:annotation-driven conversion-service="myCon"></mvc:annotation-driven>
<!--将自定义的类型转化器交给springmvc的转换器集合-->
<bean id="myCon" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean id="stringToData" class="cn.itcast.converter.StringToDataConverter"></bean>
</set>
</property>
</bean>
<form action="/param5" method="post">
日期:<input type="text" name="date" />
<input type="submit" value="提交" />
</form>
@RequestMapping(value = "/param5",name = "使用自己的通用日期类型转化器")
public String param5(Date date){
System.out.println(date);
return "success";
}
三 springMVC提供的注解概述 【了解】
注解
@RequestHeader:获取请求头的信息
@CookieValue:获取cookie的信息
属性:定义在方法形参上
Value:根据请求信息key获取值
Required:是否必须要传递该头信息
False:不是必须的
True: 必须要传递
@ModelAttribute:设置在方法上 用来在执行控制器方法之前先执行的方法
@ModelAttribute //代表在所有控制器controller方法之前执行
public void init(){
System.out.println(1111);
}
@RequestMapping(value = "/param6",name = "请求头的注解概述")
public String param6(@RequestHeader(value = "host",required = true)String value1, @RequestHeader("Connection") String value2,
@CookieValue(value = "JSESSIONID",required = true)String value3){
System.out.println(value1);
System.out.println(value2);
System.out.println(value3);
return "success";
}
四 servlet的api获取
servlet的api获取
方法形参填写request,response,session即可获取该类型对象
条件:导入servlet依赖
<!--servlet的api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
@RequestMapping(value = "/param7",name = "servlet的api获取")
public String param7(HttpServletRequest request, HttpServletResponse response, HttpSession session){
System.out.println(request);
System.out.println(response);
System.out.println(session);
return "success";
}
五 异步ajax的数据封装
@RequestBody
配置到方法参数上,表明将json数据化为java对象
@ResponseBody
配置到方法返回值,表明将对象转化为json数据并响应
1 )导入jason坐标
<!--jackson转换工具-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
2 )ajax.jsp(记得导入axios文件)
<h2>ajax异步封装交互数据</h2>
<input type="button" value="ajax" οnclick="ajaxfn()">
<script src="/js/axios-0.20.0.js"></script>
<script>
function ajaxfn(){
//axios发送请求 json
let data={"name":"工商银行","money":66666};
axios.post("/ajax",data).then(resp=>{
//接受服务器响应的数据 json
let user=resp.data;
alert(user.username);
alert(user.age);
})
}
</script>
- UserController
@RequestMapping(value = "/ajax",name = "springmvc中封装异步数据")
//后台:json对象--jackson--readValue--account对象
public @ResponseBody User ajax(@RequestBody Account account){
System.out.println(account);
//比如:从数据库查询了一个用户User
User user = new User();
user.setUsername("jack");
user.setAge(100);
//user对象返回给ajax jackson--writeValueAsString--json--ajax
return user; //@ResponseBody---{"username":"jack","age":100}
}
六 springmvc的响应方式
响应类型有3种:String Void ModelAndView
响应方式有2种:请求转发 重定向
spring的视图方式有2种: 物理视图 逻辑视图
物理视图:完整的路径地址
逻辑视图:经过视图解析器解析的地址
特点:逻辑视图默认只走请求转发方式
物理视图默认是走请求转发方式,但是也可以手动设置响应方式
String类型返回值
默认:以请求转发的方式跳转(物理视图,逻辑视图)
手动设置响应方式:(forward|redirect):物理视图
Void类型返回值
只能通过request和response设置响应方式
ModelAndView类型返回值
addObject:将数据绑定到request域中
setViewName:指定跳转到页面视图
默认:以请求转发的方式跳转(物理视图,逻辑视图)
手动设置响应方式:(forward|redirect):物理视图
@Controller
public class ReturnController {
/*
* springmvc的响应类型:
* String (掌握)
* void
* Modelandview
*
* 不论何种类型,最终返回的都是视图
* 视图:物理视图 逻辑视图
* 物理视图:就是一串完整的视图路径 例如: return "/jsp/success.jsp";
* 逻辑视图:经过视图解析器解析过后的视图路径 例如:配置视图解析器 return "success";
* 物理视图|逻辑视图: 默认走的都是请求转发方式
* 响应方式:请求转发 重定向
*
* 物理视图可以进行手动设置
* 请求转发 forward return "forward:/jsp/success.jsp";
* 重定向 redirect return "redirect:/jsp/success.jsp";
*
* 总结:一般情况下我们走逻辑视图,特殊的内容需要重定向可以走手动设置物理视图(手动设置物理视图不受逻辑视图的响应)
*
*
* */
@RequestMapping(value = "/return1")
public String return1(HttpServletRequest request){
request.setAttribute("msg","abcd/1234");
return "redirect:/jsp/success.jsp";
}
/*获取request对象和response对象 自己设置响应方式*/
@RequestMapping(value = "/return2")
public void return2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg","1234/abcd");
//request.getRequestDispatcher("/jsp/success.jsp").forward(request,response);
response.sendRedirect("/jsp/success.jsp");
}
@RequestMapping(value = "/return3")
public ModelAndView return3(ModelAndView modelAndView) throws ServletException, IOException {
// 存数据
modelAndView.addObject("msg","123abc"); //reuqest
// 设置要跳转的视图(逻辑视图 手动物理视图)
//modelAndView.setViewName("success"); //逻辑视图
//modelAndView.setViewName("forward:/jsp/success.jsp");
modelAndView.setViewName("redirect:/jsp/success.jsp");
return modelAndView;
}
}
七 RestFul编程风格
可以根据指定的地址参数,做不同提交方式的不同需求
1.区分请求方式
借助@RequestMapping中的method属性
2.定义接受的地址参数
{自定义地址参数名}
3.程序中获取地址参数
@Pathvariable:配置到方法形参上
Value属性:自定义地址参数名
地址参数:http://localhost:8080/12345.html
@Controller
public class RestFulController {
/*
* 1:如何控制方法的提交方式 RequestMapping:method
*
* 2: 如果接受地址参数 格式:{随便写值} 值就是页面的id参数
*
* 3:程序中如何获取地址参数 @PathVariable(value = "id")方法形参 id必须得是{}定义的值
*
* */
//根据id查
@RequestMapping(value = "/{id}.html",method = RequestMethod.GET)
public String findById(@PathVariable(value = "id") String value){
//
System.out.println("我是根据id:"+value+"做查询");
return "success";
}
//根据id改
@RequestMapping(value = "/{id}.html",method = RequestMethod.POST)
public String updateById(@PathVariable(value = "id") String value){
System.out.println("我是根据id:"+value+"做修改");
return "success";
}
//根据id删
@RequestMapping(value = "/{id}.html",method = RequestMethod.DELETE)
public String deleteById(@PathVariable(value = "id") String value){
System.out.println("我是根据id:"+value+"做删除");
return "success";
}
}
八 springmvc做文件上传
A form表单的enctype取值必须是:multipart/form-data
(默认值是:application/x-www-form-urlencoded)
enctype:是表单请求正文的类型
B method属性取值必须是Post
C 提供一个文件选择域<input type=”file” />
<!--文件上传坐标-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
- upload.jsp
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="uploadfile" />
<input type="submit" value="上传">
</form>
@RequestMapping(value = "/upload") //要求MultipartFile的属性名要和页面参数名一致
public String upload(MultipartFile uploadfile, HttpServletRequest request) throws IOException {
String filename = uploadfile.getOriginalFilename();
filename= UUID.randomUUID().toString().replace("-","")+filename;
String path = request.getSession().getServletContext().getRealPath("");
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
System.out.println(date);
path=path+"upload\\"+date;
System.out.println(path);
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
// 读写数据
File file1 = new File(file,filename);
uploadfile.transferTo(file1);
return "success";
}
spring-mvc.xml
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为 5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>