一、spring-mvc的执行流程
1.启动服务器,tomcat服务器加载web.xml文件,解析xml文件中的相关信息web.xml文件中配置了一个
DispatcherServlet前端控制器。
2.创建前端控制器对象。(DispatcherServlet)里面配置了spring-mvc.xml。
3.解析spring-mvc.xml配置文件,扫描com.itheima.controller包(将UserController加入到IOC容器中,扫
描方法上的注解),这时候生成了一个处理器映射器(handlerMapping)
-------------------------------------------------------------------------------------------
浏览器访问/quick
浏览器的请求来了之后先经过前端控制器,前端控制器会截取到方法名去处理器映射器(作用:建立请求路径
和方法之间的对应关系)里找,找到了就返回对应的方法的全限定名。返回给前端控制器。
然后把返回的全限定名交给处理器适配器。
处理器适配器(完成方法的适配,让指定的方法执行):截取拿到类的全限定名,创建类对象,获得方法的字
节码文件,反射来执行方法。方法执行后,会返回一个MODEandView.
处理器适配器拿到后返回给前端控制器。
核心控制器会直接把MODEandView交给视图解析器,视图解析器会拼接前缀和后缀,完成请求转发或重定向。
并且把信息装载到页面中返回前端控制器。
最后由前端控制器返回给浏览器。
二、SpringMVC环境搭建
创建maven的web项目
1.导入jar包的坐标
2.准备spring-mvc.xml文件
3.在web.xml文件中配置前端总控制器,和加载springMVC的配置文件
<!-- 3.1 配置前端总控制器 -->
<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>
=====================================
<!--3.2 配置过滤器 -->
<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>
4.配置spring-mvc.xml文件
<!-- 配置需要扫描的包 -->
<context:component-scan base-package="com.itheima.controller"></context:component-scan>
<!-- 配置注解驱动: 将适配器需要的具体实现类加载进来 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 公布静态资源: 静态资源不需要SpringMVC处理 -->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!-- 配置视图解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- /jsp/success.jsp -->
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
5.编写处理器(我们自己的功能代码-Controller层的相关代码)
5.1: 在类上添加注解(@Controller)
5.2: 在方法上添加注解(@RequestMapping)
三、web作用(请求和响应):
作用和前端交互
1.响应:常见的数据格式
页面的跳转情况:
页面跳转:
请求转发
重定向
直接写会数据信息()
直接写会字符串(同步请求下,将字符串写会到一个新的页面)
直接写会Json字符串(异步请求,将返回给结果交个ajax的回调函数)
2.SpringMVC作出响应:
1、返回一个字符串,页面跳转
@RequestMapping("/quick")
public String test01(String name){
System.out.println(name+"执行..............");
return "/success.jsp";
}
2、返回一个modelAndView ,页面跳转并且携带信息
@RequestMapping("/quick2")
public ModelAndView test02(String name){
System.out.println(name+"执行222222..............");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/success.jsp");
modelAndView.addObject("username","zhaolei");
return modelAndView;
}
@RequestMapping("/quick3")
public ModelAndView save3(ModelAndView modelAndView){
modelAndView.addObject("username","heima tiancai 赵磊");
modelAndView.setViewName("success");
return modelAndView;
}
3用字符串跳转,用model携带信息
@RequestMapping(value="/quick4")
public String save4(Model model){
model.addAttribute("username","赵磊");
return "success";
}
4用字符串跳转,用request 携带信息
@RequestMapping("/quick5")
public String save5(HttpServletRequest request){
request.setAttribute("username","酷丁鱼");
return "success";
}
5用response 直接写回一个字符串
@RequestMapping("/quick6")
public void save6(HttpServletResponse response) throws IOException {
response.getWriter().print("hello itcast zhaolei");
}
6直接返回一个字符串 但是,告知SpringMVC框架 不进行视图跳转 直接进行数据响应
@RequestMapping(value="/quick7")
@ResponseBody //告知SpringMVC框架 不进行视图跳转 直接进行数据响应
public String save7() {
return "hello itheima wangye ";
}
7直接写回一个Json字符串
@RequestMapping(value="/quick8")
@ResponseBody
public String save8() throws IOException {
return "{\"username\":\"zhaolei\",\"age\":\"24\"}";
}
8 jackson转换 对象返回 json 字符串
@RequestMapping("/quick9")
@ResponseBody
public String save9() throws JsonProcessingException {
User user = new User();
user.setUsername("zhaolei");
user.setAge(23);
ObjectMapper mapper =new ObjectMapper();
String json = mapper.writeValueAsString(user);
return json;
}
9返回对象或集合
@RequestMapping("/quick10")
@ResponseBody
//期望SpringMVC自动将User转换成json格式的字符串
public User save10() throws IOException {
User user = new User();
user.setUsername("lisi2");
user.setAge(32);
return user;
}
3.SpringMVC获取请求
基本参数类型
1、获取请求携带的参数
//http://localhost:8080/quick11?username=zhangsan&age=12
@RequestMapping("/quick11")
@ResponseBody
public void save11(String username,int age) throws IOException {
System.out.println(username);
System.out.println(age);
}
2 、用数组获取请求携带的多个参数(参数值会自动映射匹配)
//http://localhost:8080/quick13?strs=123&strs=789&strs=7410520 参数值会自动映射匹配
@RequestMapping(value="/quick13")
@ResponseBody
public void save13(String[] strs) throws IOException {
System.out.println(Arrays.asList(strs));
pojo类型
3、请求参数如果与实体bean参数吻合会自动封装
@RequestMapping(value="/quick12")
@ResponseBody
public void save12(User user) throws IOException {
System.out.println(user);
}
4、获得集合类型参数(集合中的每个参数还都是一个对象)
服务器:
//表单获得集合参数时,要将集合参数包装到一个POJO(ValueObject值对象)中才可以
@RequestMapping(value = "/quick14",produces ="text/html;charset=utf-8" )
@ResponseBody
public void save14(VO vo) throws IOException {
System.out.println(vo);
}
=========================================================================================
浏览器: <form action="${pageContext.request.contextPath}/user/quick14" method="post">
<%--表明是第一个User对象的username age--%>
<input type="text" name="userList[0].username"><br/>
<input type="text" name="userList[0].age"><br/>
<input type="text" name="userList[1].username"><br/>
<input type="text" name="userList[1].age"><br/>
<input type="submit" value="提交">
</form>
封装的实体bean(VO):
public class VO {
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("VO{");
sb.append("userList=").append(userList);
sb.append('}');
return sb.toString();
}
5、当获取到的请求是json形式的数据,无需使用POJO封装
服务器:
//当使用ajax提交时,可以指定contentType为json形式,
// 那么在方法参数位置使用@RequestBody可以直接接收集合数据而无需使用POJO进行包装
@RequestMapping(value="/quick15")
@ResponseBody
public void save15(@RequestBody List<User> userList) throws IOException {
System.out.println(userList);
}
浏览器:
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
<script>
function sendAjax() {
var url = "${pageContext.request.contextPath}/demo5";
// json对象不能直接传递给服务器
// 解决方案1
//var params = '{"username":"张三","password":"123456"}';
// 解决方案2
var params = [
{"username":"张三","password":"123456"},
{"username":"李四","password":"666666"}
];
params = JSON.stringify(params);
// 发送ajax请求
$.post({
url:url, // 设置ajax请求的路径
contentType: "application/json;charset=utf-8",
dataType:"json", // 设置返回值的类型
data:params, // 设置请求参数
success:function (data) {
alert(data.username+" : "+data.password);
}
});
}
</script>
</head>
<body>
<h2>首页</h2>
<button onclick="sendAjax()">发送ajax请求</button>
</body>
</html>
四、其他的一些东西
4.1@RequestParam:
//当请求参数的名称和方法中的名称不一致时,建立对应关系,就要用到RequestParam value和请求参数名同,然后这个方法的参数是什么就无所谓了
// ;required设置是否强制携带;defaultValue :设置 如果携带参数默认是什么
//http://localhost:8080/quick16?name=zhaolei
@RequestMapping(value="/quick16")
@ResponseBody
public void save16(@RequestParam(value="name",required = false,defaultValue = "itcast") String username) throws IOException {
System.out.println(username);
}
4.2自定义类型转换器:
首先springMVC内部已经具备一些类型转换器了:但是如果有时候不满足我们的需求
第一步: 定义一个类,实现 Converter 接口,该接口有两个泛型
public class DateConverter implements Converter<String, Date> {
public Date convert(String dateStr) {
//将日期字符串转换成日期对象 返回
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
第二步:在 spring-MVC.xml 配置文件中配置类型转换器(ConversionServiceFactoryBean)。
<!--声明转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<!--自己编写的类的全限定名-->
<bean class="com.itheima.converter.DateConverter"></bean>
</list>
</property>
</bean>
第三步:在 annotation-driven 标签中引用配置的类型转换服务
<!--mvc的注解驱动-->
<mvc:annotation-driven conversion-service="conversionService"/>
使用
@RequestMapping(value="/quick18")
@ResponseBody
public void save18(Date date) throws IOException {
System.out.println(date);
}
4.3使用 ServletAPI 对象作为方法参数:
想要获取,就在想要获取的方法的形参位置注入就可以了。方法是我们定义的,但不是我们调用的,最终是框架帮我们调用,调用的时候框架会帮我们传递。
HttpServletRequest、HttpServletResponse、 HttpSession消息头相关的两个注解
4.4获取请求头信息
//@RequestHeader : 获取请求头
@RequestMapping(value="/quick20")
@ResponseBody
public void save20(@RequestHeader(value = "User-Agent",required = false) String user_agent) throws IOException {
System.out.println(user_agent);
}
//@CookieValue : 专门获取cookie的值
@RequestMapping(value="/quick21")
@ResponseBody
public void save21(@CookieValue(value = "JSESSIONID") String jsessionId) throws IOException {
System.out.println(jsessionId);
}
4.5spring-mvc获取RestFul风格的参数
RestFul 风格,携带参数的另一种方式
它的请求是:请求方式 + 参数
GET:用于获取资源 /user/1 GET :得到ID=1的user
POST:用于新建资源 /user/1 POST :新增user
PUT:用于更新资源 /user/1 PUT :更新id=1de user
DELETE:;用于删除资源 /user/1 DELETE :删除id=1的user
// localhost:8080/quick17/zhangsan
@RequestMapping(value="/quick17/{name}")
@ResponseBody
public void save17(@PathVariable(value="name") String username) throws IOException {
System.out.println(username);
}