Spring MVC之开门见山
1、springMVC介绍以及环境搭建
A、SpringMVC是什么?
SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringMVC也是要简化我们日常Web开发。
1)是一个MVC的Web层框架,它采用请求响应模型
2)它可以简化Web开放
B、SpringMVC环境快速搭建
1)编写SpringMVC的配置文件springmvc-servlet.xml
a)存放在WEB-INF/下面,但是它的名字有规则,这就是所谓的约定-契约。它必须在web.xml中配置一个DispatcherServlet中的servlet-name节点的-servlet.xml
b)存放在resources下面,不过需要在web.xml中配置一个DispatcherServlet中的servlet-name节点中配置init-param节点。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--配置Controller,处理器对象, /hello就是请求路径-->
<bean name="/hello" class="com.java.controller.HelloController"></bean>
<!--处理器映射器,作用是请求的时候通过处理器的名字获得对于的Controller-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!--视图解析器,通过Controller中返回的ModelAndView获得物理视图 jsp-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
2)在web.xml中添加一个Servlet,这个Servlet必须是DispatcherServlet,在配置的时候要加上on-load-startup,初始值<=1的整数。然后在里面关联上springmvc-servlet.xml配置文件,把它作为Servlet的上下文参数。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!--springmvc的配置-->
<servlet>
<!--springmvc-servlet.xml 那么springmvc约定servlet-name节点的名字必须是 springmvc-->
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--设置<=1的数字,tomcat启动,那么Servlet就初始化启动-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--用/表示拦截所有的请求-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3)编写处理器Controller
package com.java.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
//Controller处理器
public class HelloController extends AbstractController{
@Override
protected ModelAndView handleRequestInternal(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws Exception {
ModelAndView mv=new ModelAndView();
//hello,是视图的逻辑名称,它对应的物理名称 前缀 + hello+ 后缀 WEB-INF/jsp/hello.jsp物理视图
mv.setViewName("hello");
return mv;
}
}
4)编写物理视图jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
hello springmvc
</body>
</html>
C、SpringMVC的核心组件和执行流程
A、6大组件
1)Handler业务处理器(后端处理器):Controller类,必须要继承AbstractController
2)处理器映射器HandlerMapping,找到url和对应的Controller的字符串全名
3)视图解析器ViewResolver
4)ModelAndView:模型视图对象,它的作用是用来封装视图和模型数据。
5)DispatcherServlet :是spingMVC框架启动的入口,中央处理器(前端处理器)
6)HandlerAdapter:处理器适配器
B、springMVC的执行流程
用户通过浏览器返送url的请求,首先经过入口中央处理器DispatcherServlet,然后中央处理器找到处理器映射器HandlerMapping,处理器映射器根据请求的url找到Controller的名字字符串,然后中央处理器调用映射适配器适配HandlerAdapter,从而找到对应的Controller,Controller处理完毕后,会创建一个ModerAndView,里面存放逻辑视图名和模型数据。把ModelAndView对象返回给DispatcherServlet,通过ViewResolver对象找到物理视图,同时取出ModelAndView存放的模型数据,用来渲染视图,然后视图响应给浏览器。
C、注解驱动
1、修改springmvc的配置文件
<?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: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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描controller所在的包-->
<context:component-scan base-package="com.java.controller"></context:component-scan>
<!--不需要配置处理器映射器,默认的处理器映射器-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
2、修改控制器
1)在类上添加@Controller
2)添加@RequestMapping
A)在类上添加(请求窄化)
B)在请求方法上添加
请求处理规则:请求的url=类上的@RequestMapping中的url+方法上添加@RequestMapping的url,方法上面必须添加。
package com.java.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
@Controller
@RequestMapping("/v")
public class HelloController{
@RequestMapping("/hello")
protected ModelAndView hello() throws Exception {
ModelAndView mv=new ModelAndView();
mv.setViewName("hello");
return mv;
}
@RequestMapping("/say_hello")
protected ModelAndView say_hello() throws Exception {
ModelAndView mv=new ModelAndView();
mv.setViewName("say_hello");
return mv;
}
}
3、Spring MVC入参
A、前端入参
1)@RequestParam绑定单个请求参数值;
2)@PathVariable绑定URI模板变量值;
3)pojo入参
4)HttpServletRequest传统方式入参
package com.java.controller;
import com.java.pojo.Emp;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class TestController {
@RequestMapping(value = "/test1",method = RequestMethod.GET)
public String test1(@RequestParam (value = "empNo",defaultValue = "21") Integer empNo,
@RequestParam ("name") String name,
@RequestParam (value = "age",required = false) Integer age){
System.out.println(empNo);
System.out.println(name);
System.out.println(age);
return "test1";
}
// test2/12/zhangsan/67
@RequestMapping(value = "/test2/{empNo}/{name}/{age}",method = RequestMethod.GET)
public String test2(@PathVariable Integer empNo,
@PathVariable String name,
@PathVariable Integer age){
System.out.println(empNo);
System.out.println(name);
System.out.println(age);
return "test1";
}
@RequestMapping(value = "/test3",method = RequestMethod.GET)
public String test3(Emp emp){
System.out.println(emp);
return "test1";
}
}
4、后端入参
a)作用域对象:
Map、Model、ModelMap、ModelAndView、HttpSession、HttpServletRequest等对象
b)作用域范围:
SpringMVC内部默认时转发规则,不是重定向。
@RequestMapping(value = "/test4",method = RequestMethod.GET)
//public String test4(Emp emp, HttpSession session, Map map, Model model, ModelMap modelMap, ModelAndView mv){
public ModelAndView test4(Emp emp, HttpSession session, Map map, Model model, ModelMap modelMap, ModelAndView mv){
session.setAttribute("emp_session",emp);
map.put("emp_map",emp);
model.addAttribute("emp_model",emp);
modelMap.addAttribute("emp_modelMap",emp);
mv.addObject("emp_mv",emp);
mv.setViewName("test1");
return mv;
}
5、重定向和转发
需求:用户请求的url为test5的时候,重定向到url为test6的资源上,如何处理?如果是转发怎么处理?
方案:
1)重定向:redirect:添加重定向的url
2)转发:forward:添加转发的url
//return test5是逻辑视图名,而重定向和转发的是url
@RequestMapping("/test5")
public String test5(){
//test6是请求的url
//return "redirect:test6"; //重定向
return "forward:test6";//转发
}
@RequestMapping("/test6")
public String test6(){
return "test6";
}
6、类型转换和格式化
1、请求报文结构
2、响应报文
3、生产者和消费者
4、转换的时机
5、数据转换和格式化的过程
当用户通过表单或者url发送请求,首先会把参数封装到HttpServeltRequest,它的结构是k-v,key是字符串,value也是字符串。SpringMVC中通过消息转换器自动对数据进行转换,转成响应的类型和格式填充到Controller中的请求方法的参数中。
6、异常处理
有时候又一些业务执行的过程中出现异常,是不方便直接显示给用户的,需要进行异常的处理,怎么统一处理异常?
1)局部异常:在controller上添加异常处理方法,在方法的上面添加@ExceptionHandler
a)编写业务自定义异常类
package com.java.exceptions;
//专门处理添加数据的业务异常(举例)
public class BizException extends RuntimeException{
public BizException(String message) {
super(message);
}
}
b)在出现异常的Contrlller中添加异常处理的方法
package com.java.controller;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.java.exceptions.BizException;
import com.java.pojo.Emp;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
@Controller
public class TestController {
//业务请求接口
@RequestMapping("/add")
public String add(Integer num){
if(num==1){
//抛出业务的异常
throw new BizException("添加订单业务异常====");
}
return "success";
}
//处理业务异常的方法
@ExceptionHandler({BizException.class})
public ModelAndView BizExceptionHandler(BizException e){
ModelAndView mv=new ModelAndView();
//设置业务异常的提示页面
mv.setViewName("biz_fail");
mv.addObject("code",e.getMessage());
return mv;
}
}
c)添加业务异常错误页面biz_fail
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${code}
</body>
</html>
2)全局异常:编写类,在类上添加@ControllerAdvice,并扫描该类即可。
A)编写业务自定义异常类(同上)
B)编写统一异常处理类
package com.java.exceptions;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice//是Controller的扩展
public class GlobalExceptionHandler {
@ExceptionHandler({BizException.class})
public ModelAndView BizExceptionHandler(BizException e){
ModelAndView mv=new ModelAndView();
//设置业务异常的提示页面
mv.setViewName("biz_fail");
mv.addObject("code",e.getMessage());
return mv;
}
}
C)编写添加业务异常错误页面biz_fail
D)修改springmvc的配置文件,扫描统一异常处理类
<?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: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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描controller所在的包-->
<context:component-scan base-package="com.java.controller,com.java.exceptions"></context:component-scan>
<!--不需要配置处理器映射器,默认的处理器映射器-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!--转换的bean-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<!--自定义的日期格式化类-->
<bean class="com.java.convert.DateConverter">
<constructor-arg index="0" value="yyyy-MM-dd"></constructor-arg>
</bean>
</list>
</property>
</bean>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>