SpringMVC
SpringMVC
SpringMVC
SpringMVC一种开发模式,它是模型视图控制器的简称.所有的web应用都是基于MVC开发.
M:模型层,包含实体类bean,业务逻辑层service,数据访问层mapper V:视图层,html,javaScript,vue等都是视图层,用来显现数据 C:控制器,它是用来接收客户端的请求,并返回响应到客户端的组件,Servlet就是组件
运行流程图
为配置
SpringMVC 常用主要组件
1.ispatcherServlet:前端控制器
2.Controller:处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理
3.HandlerMapping :请求映射到处理器,找谁来处理,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器对象)
4.View Resolver : 视图解析器,找谁来处理返回的页面。把逻辑视图解析为具体的View,进行这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为JSP视图
LocalResolver:本地化、国际化
MultipartResolver:文件上传解析器
HandlerExceptionResolver:异常处理器
永远的HelloWorld
1.新建Web工程,加入 jar 包
spring-aop-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
commons-logging-1.1.3.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
在 web.xml 中配置 DispatcherServlet
!-- 配置SpringMVC核心控制器: --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置DispatcherServlet的初始化參數:设置文件的路径和文件名称 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
解释配置文件的名称定义规则:实际上也可以不通过 contextConfigLocation 来配置 SpringMVC 的配置文件, 而使用默认的.默认的配置文件为: /WEB-INF/<servlet-name>-servlet.xml
加入 Spring MVC 的配置文件:springmvc.xml
增加名称空间
增加配置
<!-- 设置扫描组件的包: -->` <context:component-scan base-package="com.atguigu.springmvc"/> <!-- 配置映射解析器:如何将控制器返回的结果字符串,转换为一个物理的视图文件--> <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean>
4.需要创建一个入口页面,index.jsp
<a href="${pageContext.request.contextPath }/helloworld">Hello World</a>
编写处理请求的处理器,并标识为处理器
package com.atg.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller //声明Bean对象,为一个控制器组件 public class HelloWorldController { /** * 映射请求的名称:用于客户端请求;类似Struts2中action映射配置的action名称 * 1. 使用 @RequestMapping 注解来映射请求的 URL * 2. 返回值会通过视图解析器解析为实际的物理视图, 对于InternalResourceViewResolver视图解析器, * 会做如下的解析: * 通过 prefix + returnVal + suffix 这样的方式得到实际的物理视图, 然后做转发操作. * /WEB-INF/views/success.jsp */ @RequestMapping(value="/helloworld",method=RequestMethod.GET) public String helloworld(){ System.out.println("hello,world"); return "success"; //结果如何跳转呢?需要配置映射解析器 } }
6.1编写视图/WEB-INF/views/success.jsp
<h4>Sucess Page</h4>
HelloWorld请求流程图解
一般请求的映射路径名称和处理请求的方法名称最好一致(实质上方法名称任意)
RequestMapping(value="/helloworld",method=RequestMethod.GET)
public String helloworld(){
//public String abc123(){
System.out.println("hello,world");
return "success";
}
处理请求方式
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
@RequestMapping应用
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {…}
流程
基本步骤:
① 客户端请求提交到DispatcherServlet
② 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller
③ DispatcherServlet将请求提交到Controller(也称为Handler)
④ Controller调用业务逻辑处理后,返回ModelAndView
⑤ DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
⑥ 视图负责将结果显示到客户端
RequestMapping_请求参数&请求头
//可以使用 params 和 headers 来更加精确的映射请求. params 和 headers 支持简单的表达式.
@RequestMapping(value="/testParamsAndHeaders",
params= {"username","age!=10"}, headers = { "Accept-Language=en-US,zh;q=0.8" })
public String testParamsAndHeaders(){
System.out.println("testParamsAndHeaders...");
return "success";
}
RequestMapping支持Ant 路径风格
/user/*/createUser
匹配 /user/aaa/createUser、/user/bbb/createUser 等 URL
/user/**/createUser
匹配 /user/createUser、/user/aaa/bbb/createUser 等 URL
/user/createUser??
匹配 /user/createUseraa、/user/createUserbb 等 URL
@PathVariable
//@PathVariable 注解可以将请求URL路径中的请求参数,传递到处理请求方法的入参中
浏览器的请求: testPathVariable/1001
@RequestMapping(value="/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id){
System.out.println("testPathVariable...id="+id);
return "success";
}
HiddenHttpMethodFilter过滤器
配置HiddenHttpMethodFilter过滤器
<!-- 支持REST风格的过滤器:可以将POST请求转换为PUT或DELETE请求 -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
实例put
@RequestMapping(value="/testRESTPut/{id}",method=RequestMethod.PUT)
public String testRESTPut(@PathVariable("id") Integer id){
System.out.println("testRESTPut id="+id);
return "success";
}
增加控制器方法
/**
* @RequestParam 注解用于映射请求参数
* value 用于映射请求参数名称
* required 用于设置请求参数是否必须的
* defaultValue 设置默认值,当没有传递参数时使用该值
*/
@RequestMapping(value="/testRequestParam")
public String testRequestParam(
@RequestParam(value="username") String username,
@RequestParam(value="age",required=false,defaultValue="0") int age){
System.out.println("testRequestParam - username="+username +",age="+age);
return "success";
}
@RequestMapping(value="/testRequestHeader")
public String testRequestHeader(@RequestHeader(value="Accept-Language") String al){
System.out.println("testRequestHeader - Accept-Language:"+al);
return "success
@CookieValue: 映射一个 Cookie 值. 属性同 @RequestParam
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
System.out.println("testCookieValue: sessionId: " + sessionId);
return "success";
}
* Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配, 自动为该对象填充属性值。
* 支持级联属性
* 如:dept.deptId、dept.address.tel 等
*/
@RequestMapping("/testPOJO")
public String testPojo(User user) {
System.out.println("testPojo: " + user);
return "success";
<!-- 测试 POJO 对象传参,支持级联属性 -->
<form action=" testPOJO" method="POST">
username: <input type="text" name="username"/><br>
password: <input type="password" name="password"/><br>
email: <input type="text" name="email"/><br>
age: <input type="text" name="age"/><br>
city: <input type="text" name="address.city"/><br>
province: <input type="text" name="address.province"/>
<input type="submit" value="Submit"/>
</form>
public class Address {
private String province;
private String city;
//get/set
}
public class User {
private Integer id ;
private String username;
private String password;
private String email;
private int age;
private Address address;
//get/set
}
<!-- 配置字符集 -->
<filter>
<filter-name>encodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
SpringMVC 输出模型数据
1.** ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据
2.Map 或 Model: 入参为 org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中
ModelAndView
1.两个重要的成员变量:private Object view视图信息, private ModelMap model 模型数据
2.添加模型数据:
MoelAndView addObject(String attributeName, Object attributeValue) 设置模型数据
ModelAndView addAllObject(Map<String, ?> modelMap)
3.设置视图:
void setView(View view) 设置视图对象
void setViewName(String viewName) 设置视图名字
4.获取模型数据
protected Map<String, Object> getModelInternal() 获取模型数据
public ModelMap getModelMap()
public Map<String, Object> getModel()
Map
1.Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口存储模型数据具体使用步骤
2.Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
如果方法的入参为 Map 或 Model 类型**,Spring MVC 会将隐含模型的引用传递给这些入参。
4.在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据
//目标方法的返回类型也可以是一个Map类型参数(也可以是Model,或ModelMap类型)
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){
System.out.println(map.getClass().getName());
//org.springframework.validation.support.BindingAwareModelMap
map.put("names", Arrays.asList("Tom","Jerry","Kite"));
return "success";
}
//目标方法的返回类型也可以是一个Map类型参数(也可以是Model,或ModelMap类型)
@RequestMapping("/testMap2")
public String testMap2(Map<String,Object> map,Model model,ModelMap modelMap){
System.out.println(map.getClass().getName());
map.put("names", Arrays.asList("Tom","Jerry","Kite"));
model.addAttribute("model", "org.springframework.ui.Model");
modelMap.put("modelMap", "org.springframework.ui.ModelMap");
System.out.println(map == model);
System.out.println(map == modelMap);
System.out.println(model == modelMap);
System.out.println(map.getClass().getName());
System.out.println(model.getClass().getName());
System.out.println(modelMap.getClass().getName());
/*
true
true
true
org.springframework.validation.support.BindingAwareModelMap
org.springframework.validation.support.BindingAwareModelMap
org.springframework.validation.support.BindingAwareModelMap
*/
return "success";
}
Map, 便于框架移植。
视图和视图解析器
1.请求处理方法执行完成后,最终返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象,它包含了逻辑名和模型对象的视图
2.Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是 Excel、JFreeChart等各种表现形式的视图
3.对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦
视图
1.视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。
2.为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口:
3.视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题
常用的视图实现类
常用的视图解析器
mvc:view-controller标签
<!-- 直接配置响应的页面:无需经过控制器来执行结果 -->
<mvc:view-controller path="/success" view-name="success"/>
重定向
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect");
return "redirect:/index.jsp";
//return "forward:/index.jsp";
}
HttpMessageConverter<T>
1.HttpMessageConverter<T>,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息**
2.HttpMessageConverter<T>接口定义的方法:
1. Boolean canRead(Class<?> clazz,MediaType mediaType): 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json等)
2. Boolean canWrite(Class<?> clazz,MediaType mediaType):指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在MediaType 中定义。
3. List<MediaType> getSupportMediaTypes():该转换器支持的媒体类型。
4. T read(Class<? extends T> clazz,**HttpInputMessage** inputMessage):将请求信息流转换为 T 类型的对象。
5.void write(T t,MediaType contnetType,**HttpOutputMessgae** outputMessage):将T类型的对象写到响应流 中,同时指定相应的媒体类型为 contentType。