01SpringMVC
一、SrpingMVC概述
一、SpringMVC简介
SpringMVC是一种基于Java实现MVC模型的轻量级Web框架。
二、SpringMVC优点
1.使用简单
2.性能突出(和现有的框架技术相比)
3.灵活性强
二、SpringMVC原理
在项目启动的时候:
1.Tomcat会解析web.xml
1.1 初始化DispatcherServlet,在init方法里面获取init-param的信息
1.2 得到配置springmvc的xml文件
1.3 解析springmvc.xml文件
1.4 扫描包下的所有类
1.5 得到类的字节码信息,然后得到类身上的注解信息
1.5.1 如果那个类身上有@Controller注解,那么他就是用来处理请求的
1.5.2 进一步获取类中的所有方法,然后查看是否有注解@RequestMapping
1.5.3 执行到这里之后,那么就知道了,什么请求,对应什么类中的什么方法
也可以理解为:使用一个map集合来存储这层对应关系
2. 请求到来之后,由Tomcat把请求交给DispatcherServlet来处理
2.1 进一步拆解请求的地址:localhost:8080/sayHi : req.getRequestURL()
2.2 切割字符串,得到sayHi字样
2.3 拿着这个字符去上面的map集合里面找到对应的方法,然后调用方法。
三、使用步骤
1.导依赖
2.创建有关Controller类,处理的请求
3.创建页面
4.配置springmvc.xml
5.配置web.xml启动时加载springmvc.xml【配置DispatcherServlet】
一、Controller配置
/**
* @Controller:
* 1. 表示这个类是专门用来接收请求和处理请求的
* 2. 表示每一个方法产生页面的跳转,只要是有返回值
* @RequestMapping:
* 1. 请求映射,什么样的请求过来,这个方法就会执行
* 2. 属性解释:
* value : 用来表示映射地址
* method : 用来表示请求方式
* RequestMapping.GET : 职能配置GET
* {RequestMapping.POST, RequestMapping.GET} : 能够同时匹配GET和POST
* 不写就是匹配所有请求方式
* params : 用来表示请求参数 string数组形式
* 要求客户端一定要携带username和password的值
* params = {"username=admin", "password=123"}
*/
@Controller
public class Controller01 {
/**
* 逻辑视图写法
* 1. 只要写页面的名字即可,比较简单,不直观
* 2. 需要搭配视图解析器才能知道页面在哪里
*
*/
@RequestMapping("/sayHi")
public String sayHi2(){
return "success";
}
}
二、springmvc.xml
<!--1. 扫描包-->
<context:component-scan base-package="com.cwl"/>
<!--
2. 打开注解驱动
2.1 如果不写这个标签,则@RequestBody @ResponseBody等一些注解就无法使用。
-->
<mvc:annotation-driven/>
<!--
3. 视图解析器
3.1 视图解析器要配置前缀和后缀
3.2 当springmvc调用方法得到方法的返回值之后,会和前缀和后缀进行拼接,得到完整的路径地址。
前缀 + 返回值 + 后缀
3.3. 视图解析器一旦配置了之后,将会对所有的方法产生影响!
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--
4. 静态资源处理
静态资源无法访问的原因:
4.1 当DispatcherServlet映射地址配置成 / 了之后,那么静态资源将无法展示,
都是404
4.2 在Tomcat内部有一个类 DefaultServlet,专门用来处理静态资源的请求,它
的映射地址也是 /
4.3 DispatcherServlet 把 DefaultServlet给覆盖了,导致静态资源无法正常处理
解决办法:
a. 在这个文件中配置静态资源的映射,告诉springmvc 什么样的请求地址就到什么地址里面去找静态资源 【不建议】
<!--第一种解决办法-->
<!-- <mvc:resources mapping="/html/**" location="/html/">
-->
<!--b. 收到静态资源请求之后,直接把静态资源转交给Tomcat里面的DefaultServlet来处理
-->
<!--第二种解决办法 让Tomcat的DefaultServlet 来处理静态资源-->
<mvc:default-servlet-handler/>
三、web.xml
<!--
1. springmvc 里面有一个servlet,可以接收请求,然后分发请求给到
controller类,所以需要去配置这个servlet
2. 配置DispatcherServlet,需要把springmvc.xml传递进去,以便
能够解析springmvc.xml文件
3. 为了让dispatcherservlet初始化的时机更早些,所以要配置load-on-startup
-->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
告诉DispatcherServlet, springmvc的配置文件在哪里
1. 在DispatcherServlet里面的init方法会读取这段配置!
2. 要在这里配置springmvc.xml文件,以便解析该文件
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--让springmvc初始化的时机更早一些,去完成那些扫描的工作!-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--
映射地址解释:
1. 为了让DispatcherServlet能够捕获到更多的请求,所以这里通常会配置
成任意路径 写法: / 或 /*
2. 这里不能配置 /*
2.1 配置 /* 之后,JSP会看不了
a. 在Tomcat里面也有一个专门处理JSP的servlet : JspServlet ,
它的映射地址是: *.jsp
b. /* 的优先级 > *.jsp的优先级要高!所以就没有人去转化jsp 成
servlet, 执行servlet。
c.为啥写成 / 就OK 呢?
还是优先级的问题:
精确匹配 > 目录匹配 > /* >后缀名匹配 > /
/ : 可以认为是缺省匹配,就是当没有人处理这个请求的时候,就交给它
处理,跟清道夫差不多的工作。
3. 其实这里也可以写 *.后缀名的写法
既不会污染静态资源的处理,也不会污染到jsp的处理。但是,在访问controller的
方法时,必须带上后缀,否则无法访问.
-->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
四、请求参数绑定
1、绑定机制
SpringMVC的参数绑定过程是把表单提交的请求参数,与Controller的方法参数进行绑定
(要求:提交表单的name和方法的参数的名称是相同的)
2、获取参数
2.1 获取简单的参数
/**
* 1. 获取简单的参数
* 客户端提交参数的名字必须和形参的名字一样
*/
@RequestMapping("/requestSimpleParam")
public String requestSimpleParam(String username, String password, int age){
return "success";
}
2.2 获取对象的参数
/**
* 2. 获取对象的参数
* 客户端提交参数的名字必须和类的属性名字要一样
*/
@RequestMapping("/requestObjectParam")
public String requestObjectParam(User user){
return "success";
}
2.3 使用数组获取集合的参数
/**
* 3. 使用数组获取集合的参数
* 客户端提交参数的名字必须要和形参的名字一样
*/
@RequestMapping("/requestArrays")
public String requestArrays(String[] hobby){
return "success";
}
2.4 使用集合获取集合的参数
/**
* 4. 使用集合获取集合的参数
* 1. 客户端提交的名字必须要和形参的名字一样
* 2. 要在形参前面加上注解 @RequestParam
*/
@RequestMapping("/requestList")
public String requestList(@RequestParam List<String > hobby){
return "success";
}
五、中文乱码
1、解决get请求中文乱码
在pom.xml的tomcat的配置中的配置
<!--解决get乱码问题-->
<uriEncoding>utf-8</uriEncoding>
2、解决POST请求中文乱码
在web.xml配置
<!--1. 配置过滤器-->
<filter>
<filter-name>filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--1.1 指定编码-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
六、常用注解
1.@RequestParam ===> 可以对浏览器请求做出参数上的要求,要求一定要有指定名字的参数
2.@RequestBody ===> 获取客户端传递过来的json数据,转化为JavaBean对象(常用)
3.@PathVarible ===> 用于截取请求地址(url)里面的某些部分的数据
4.@RequestHeader ===> 获取指定名字的请求头数据,赋值给方法参数
5.@CookieValue ===> 用于把指定cookie名称的值传入控制器方法参数
1.@RequestParam
/**
* 1. @RequestParam
* 1. 要求客户端来访问的时候一定要携带指定名字的参数
* 2. 属性介绍
* name | value : 用来指定客户端一定要携带指定名字的参数,如果没有设置,那么以形参名为准
* required : 默认值是true, 表示是否必须携带此参数
* defaultValue : 默认值, 只有在没有携带参数的时候,他才会有默认值
*/
@RequestMapping("/RequestParamDome01")
public String RequestParamDome01(@RequestParam(value = "aa", required = false, defaultValue = "管理员") String username, String password){
System.out.println("username = " + username);
System.out.println("password = " + password);
return "success";
}
2.@RequestBody
/*
不常用
@RequestBody:
作用: 用来获取请求体的内容,赋值给方法的形参,得到形如: a=b&c=d 样式
注意:
只有针对post请求才有效,只有post请求才有请求体
*/
@RequestMapping("/RequestBodyDemo")
public String RequestBodyDemo(@RequestBody String body){
System.out.println("body = " + body);
return "success";
}
/*
常用:
使用@RequestBody来接收JSON数据
1.提交的必须是一份JSON数据
2.JavaBean里面的属性名必须和JSON的name一样
3.导入jackson-databind的依赖
如果不写会报 415
4.在参数的前面加上注解:@RequestBody
如果不加,则是默认值
*/
@RequestMapping("/RequestBodyJSON")
public String RequestBodyJSON(@RequestBody User user){
System.out.println("user = " + user);
return "success";
}
3.@PathVarible
/*
原始: localhost/delete?id=8
RestFul : localhost/delete/8
@PathVariable:
1. 用来获取地址栏中的数据,通常是搭配RestFul风格使用
2. 具体步骤
2.1 在映射地址里面使用{}来占位,要写一个占位的名字,可以随意写,也可以写成形参的名字
2.2 在形参的前面加上注解@PathVariable,表示要把占位的数据赋值给方法的形参
2.2.1 如果占位的名字和形参的名字一样,那么@PathVariable就可以不写value属性
*/
@RequestMapping("/delete/{id}")
public String pathVariable(@PathVariable int id){
System.out.println("id = " + id);
return "success";
}
4.@RequestHeader
/*
使用@RequestHeader 获取指定名字的请求头,赋值给方法的形参
*/
@RequestMapping("/RequestHeader")
public String RequestHeader(@RequestHeader(value = "Accept") String value){
System.out.println("value = " + value);
return "success";
}
5.@CookieValue
/*
使用@CookieValue来获取指定名字的cookie 赋值给方法的形参
*/
@RequestMapping("/CookieValue")
public String CookieValue(@CookieValue(value = "JSESSIONID") String value){
System.out.println("value = " + value);
return "success";
}
七、相对路径与绝对路径
1、相对路径:
相对路径:
1. 相对路径不能以 / 打头。 / 打头都是绝对路径
2. 相对路径永远相对于当前的位置。在这个页面发起请求,那么当前位置就是这个页面所处的位置。
2.1 index.jsp 路径地址: http://localhost:8080/a1/b1/c1/index.jsp
2.2 看出当前位置就是: http://localhost:8080/a1/b1/c1
../ ===> http://localhost:8080/a1/b1
../ ===> http://localhost:8080/a1
../ ===> http://localhost:8080
3. 目标位置是: http://localhost:8080/user/add
4. 如果写的地址是: abc, 那么浏览器的地址栏就是: http://localhost:8080/a1/b1/c1/abc
5. 如果写的地址是: user/add, 那么浏览器的地址栏就是: http://localhost:8080/a1/b1/c1/user/add
2、绝对路径:
绝对路径
1. 永远以 / 打头!
2. 永远会把内容拼接到 端口号的后面去
3. 需要拼接出来: localhost:8080/user/add