第5节:注解详解
5.1 RequestMapping
用于定义映射路径,建立请求url和控制层方法之间的对应关系;
(1 )注解位置:
a. 类上:定义一级映射路径;
b. 方法上:定义二级映射路径;
(2 )注解属性:
value:用于指定映射路径url。它和 path 属性的作用是一样的。
method:用于指定请求的方式。method = { RequestMethod . POST } 只能处理post请求。 状态码405
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。eg: params = { "username" } ,表示请求参数必须有 username;
如果没有携带username的参数:前端浏览器400 bad request
5.2 RequestParam
5.2.1 RequestParam注解介绍
使用在方法入参位置,用于指定请求参数名称,将该请求参数绑定到注解参数位置。
属性:name:指定要绑定的请求参数名称;
required:指定请求参数是否必传; true:表明必须提交参数, 没有400
defaultValue:指定当没有传入请求参数时的默认取值;
5.2.2 RequestParam注解使用案例
@RequestMapping ( "test1" )
public String test1 ( @RequestParam ( name = "pname" , required = true , defaultValue = "李四" ) String name) {
System . out. println ( name) ;
return "main" ;
}
5.3 RequestHeader
5.3.1 RequestHeader注解介绍
注解在方法入参位置,用于获取请求头信息。
5.3.2 RequestHeader注解使用案例
value:指定头的名称;
require:是否是必须, true ,必须传递, 没传递。400
defaultValue: 如果前台没传递头信息, 指定默认值。 require冲突。
@RequestMapping ( "test2" )
public String test2 ( @RequestHeader ( "Upgrade-Insecure-Requests" ) String data) {
System . out. println ( data) ;
return "main" ;
}
#### 5.4 RequestBody
##### 5.4.1 RequestBody注解介绍
```java
用于方法入参位置,获取请求体内容。直接使用得到是 key=value&key=value...结构的数据。get 请求方式不适用。通常用于将json格式字符串绑定到bean对象中;
5.4.2 RequestBody注解使用案例
(1 )直接获取请求体内容:
< form action= "/annotation/test3" method= "post" >
用户名:< input name= "userName" type= "text" >
年龄:< input name= "age" type= "text" >
< input type= "submit" value= "提交" >
< / form>
@RequestMapping ( "test3" )
public String test3 ( @RequestBody String data) {
System . out. println ( data) ;
return "main" ;
}
(2 )将json格式请求参数绑定到指定对象bean中:
< button onclick= "sendCar()" > 发起ajax请求< / button>
< script>
function sendCar ( ) {
$. ajax ( {
type: "POST" ,
url: "/annotation/test4" ,
data: '{ "cname" : "宝马" , "cprice" : "20" } ',
contentType: "application/json" ,
success: function ( msg) {
alert ( "Data Saved: " + msg ) ;
}
} ) ;
}
< / script>
@RequestMapping ( "test4" )
public String test4 ( @RequestBody Car car) {
System . out. println ( car) ;
return "main" ;
}
注意: 使用json 需要引入json的解析器~
< dependency>
< groupId> com. fasterxml. jackson. core< / groupId>
< artifactId> jackson- databind< / artifactId>
< version> 2.9 .9 < / version>
< / dependency>
5.5 CookieValue
5.5.1 CookieValue注解介绍
用于方法入参位置,把指定 cookie 名称的值传入控制器方法参数。
5.5.2 CookieValue注解使用案例
@RequestMapping ( "test5" )
public String test5 ( @CookieValue ( "JSESSIONID" ) String data) {
System . out. println ( data) ;
return "main" ;
}
5.6 ModelAttribute
5.6.1 ModelAttribute注解介绍
该注解是SpringMVC4 .3 版本以后新加入的。它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值。
5.6.2 ModelAttribute注解使用案例
(1 )注解在方法上:
@ModelAttribute ( "shareParam" )
public String test6 ( ) {
System . out. println ( "我是公共方法" ) ;
return "公共参数" ;
}
(2 )注解在参数位置:
@RequestMapping ( "test7" )
public String test7 ( @ModelAttribute ( "shareParam" ) String data) {
System . out. println ( data) ;
return "main" ;
}
5.7 SessionAttributes
5.7.1 SessionAttributes注解介绍
注解在类上,作用将请求域中的参数存放到session域中,用于参数共享。
5.7.2 SessionAttributes注解使用案例
@RequestMapping ( "test8" )
public ModelAndView test8 ( ModelAndView modelAndView) {
modelAndView. addObject ( "aa" , "aa1" ) ;
modelAndView. addObject ( "bb" , "bb1" ) ;
modelAndView. addObject ( "cc" , "cc1" ) ;
modelAndView. setViewName ( "main" ) ;
return modelAndView;
}
@Controller
@RequestMapping ( "annotation" )
@SessionAttributes ( value = { "aa" , "bb" } )
public class AnnotationController {
. . .
}
第6节:Rest风格编程
6.1 Rest风格URL规范介绍
6.1.1 restful介绍
RESTful 架构,就是目前最流行的一种互联网软件架构风格。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。REST这个词,是Roy Thomas Fielding 在他2000 年的博士论文中提出的. Fielding 将他对互联网软件的架构原则,定名为REST,即Representational State Transfer 的缩写。即"表现层状态转化" 。如果一个架构符合REST原则,就称它为RESTful 架构。值得注意的是 REST 并没有一个明确的标准,而更像是一种设计的风格。
它本身并没有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口。
6.1.2 restful的优点
它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
6.1.3 restful 的特性
(1 )资源(Resources ):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二的识别符。
(2 )表现层(Representation ):把资源具体呈现出来的形式,叫做它的表现层 (Representation )。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
(3 )状态转化(State Transfer ):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP 协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer )。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
(4 )传统请求url:
新增:http: / / localhost: 8888 / annotation/ addPerson POST
修改:http: / / localhost: 8888 / annotation/ updatePerson POST
删除:http: / / localhost: 8888 / annotation/ deletePerson? id= 1 GET
查询:http: / / localhost: 8888 / annotation/ findPerson? id= 1 GET
(4 )REST风格请求:
新增:http: / / localhost: 8888 / annotation/ person POST
修改:http: / / localhost: 8888 / annotation/ person PUT
删除:http: / / localhost: 8888 / annotation/ person/ 1 DELETE
查询:http: / / localhost: 8888 / annotation/ person/ 1 GET
6.2 PathVariable注解详解
该注解用于绑定 url 中的占位符。例如:请求 url 中/ annotation/ test9/ { id} ,这个{ id} 就是 url 占位符。url 支持占位符是 spring3. 0 之后加入的。是springmvc 支持 rest 风格 URL 的一个重要标志。
属性:
value:用于指定 url 中占位符名称。
required:是否必须提供占位符。
6.2.1 构建页面发起请求
REST风格编程:
新增:
< form action = " /annotation/person" method = " post" >
用户名:< input name = " userName" type = " text" >
年龄:< input name = " age" type = " text" >
< input type = " submit" value = " 提交" >
</ form>
修改:
< form action = " /annotation/person" method = " post" >
< input type = " hidden" name = " _method" value = " PUT" >
用户名:< input name = " userName" type = " text" >
年龄:< input name = " age" type = " text" >
< input type = " submit" value = " 提交" >
</ form>
删除:
< form action = " /annotation/person/1" method = " post" >
< input type = " hidden" name = " _method" value = " DELETE" >
< input type = " submit" value = " 提交" >
</ form>
查询:
< a href = " /annotation/person/1" > 查询用户</ a>
6.2.2 定义控制层执行器处理请求
@RequestMapping ( value = "person" , method = RequestMethod . POST)
public String addPerson ( String userName, int age) {
System . out. println ( "新增用户:" + userName) ;
return "main" ;
}
@RequestMapping ( value = "person" , method = RequestMethod . PUT)
public String updatePerson ( String userName, int age) {
System . out. println ( "修改用户:" + userName) ;
return "main" ;
}
@RequestMapping ( value = "person/{id}" , method = RequestMethod . DELETE)
public String deletePerson ( @PathVariable ( value = "id" ) int id) {
System . out. println ( "删除用户:id" + id) ;
return "main" ;
}
@RequestMapping ( value = "person/{id}" , method = RequestMethod . GET)
public String findPerson ( @PathVariable ( value = "id" ) int id) {
System . out. println ( "查询用户信息:id" + id) ;
return "main" ;
}
6.2.3 引入请求方式转换过滤器
< filter>
< filter-name> hiddenMethodFilter</ filter-name>
< filter-class> org.springframework.web.filter.HiddenHttpMethodFilter</ filter-class>
</ filter>
< filter-mapping>
< filter-name> hiddenMethodFilter</ filter-name>
< url-pattern> /*</ url-pattern>
</ filter-mapping>
第7节:响应数据和结果视图
7.1 返回值分类
7.1.1 返回值为字符串
用于指定返回的逻辑视图名称;
控制器代码:
@RequestMapping ( "test1" )
public String test1 ( String pname) {
System . out. println ( pname) ;
System . out. println ( "返回string类型测试" ) ;
return "main" ;
}
7.1.2 void类型
通常使用原始servlet处理请求时,返回该类型;
控制器代码:
@RequestMapping ( "test2" )
public void test2 ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
System . out. println ( "返回void类型测试" ) ;
request. getRequestDispatcher ( "/response/test1" ) . forward ( request, response) ;
}
7.1.3 ModelAndView
用于绑定参数和指定返回视图名称;
控制器代码:
@RequestMapping ( "test3" )
public ModelAndView test3 ( ModelAndView modelAndView) {
modelAndView. addObject ( "aa" , "aa1" ) ;
modelAndView. setViewName ( "main" ) ;
return modelAndView;
}
7.2 转发和重定向
7.2.1 forward请求转发
控制器代码:
@RequestMapping ( "test4" )
public String test4 ( ) {
System . out. println ( "我是请求转发" ) ;
return "forward:/response/test1" ;
}
7.2.2 redirect重定向
控制器代码:
@RequestMapping ( "test5" )
public String test5 ( RedirectAttributes redirectAttributes, String pname) {
System . out. println ( "我是重定向" ) ;
redirectAttributes. addFlashAttribute ( "pname" , pname) ;
return "redirect:/response/test1" ;
}
第8节:Postman工具使用
8.1 Postman工具介绍
用户在开发或者调试网络程序或者是网页B / S 模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug 等网页调试工具。今天给大家介绍的这款网页调试工具不仅可以调试简单的css、html、脚本等简单的网页基本信息,它还可以发送几乎所有类型的HTTP请求!Postman 在发送网络HTTP请求方面可以说是Chrome 插件类产品中的代表产品之一。
8.2 Postman工具的下载安装
1 、下载地址:https: / / www. postman. com/ downloads/
2 、安装步骤:
(1 )下载安装文件
(2 )运行安装程序
(3 )重启电脑自动安装
(4 )运行
8.3 Postman工具的使用
第9节:父子容器解析
Spring和SpringMVC的容器具有父子关系,Spring容器为父容器,SpringMVC为子容器,子容器可以引用父容器中的Bean,而父容器不可以引用子容器中的Bean。
配置spring的配置文件时,排出扫描控制层注解:
< context: component-scan base-package = " com.offcn" >
< context: exclude-filter type = " annotation" expression = " org.springframework.stereotype.Controller" />
</ context: component-scan>
配置springMVC的配置文件时,扫描控制层注解:
< context: component-scan base-package = " com.offcn.controller" >
< context: include-filter type = " annotation" expression = " org.springframework.stereotype.Controller" />
</ context: component-scan>
第10节:文件上传
10.1 文件上传的必要前提
1 、form 表单的 enctype 取值必须是:multipart/ form- data ( 默认值是: application/ x- www- form- urlencoded) enctype: 是表单请求正文的类型
2 、 method 属性取值必须是 Post
3 、提供一个文件选择域< input type= ”file”/ >
10.2 文件上传原理分析
当 form 表单的 enctype 取值不是默认值后,request. getParameter ( ) 将失效。 enctype= ”application/ x- www- form- urlencoded”时,form 表单的正文内容是:key= value& key= value& key= value;
当 form 表单的 enctype 取值为 Mutilpart / form- data 时,请求正文内容就变成:每一部分都是 MIME 类型描述的正文;
10.3 文件上传
10.3.1 添加相关依赖
< dependency>
< groupId> commons-fileupload</ groupId>
< artifactId> commons-fileupload</ artifactId>
< version> 1.3.1</ version>
</ dependency>
10.3.2 编写 jsp 页面
< form enctype = " multipart/form-data" method = " post" action = " /file/fileUpload" >
< input type = " file" name = " file" >
< input type = " submit" value = " 上传" >
</ form>
10.3.3 编写控制器
@RequestMapping ( "fileUpload" )
public String fileUpload ( MultipartFile file) {
File dest = new File ( "C:\\Users\\mwx\\Pictures\\" + file. getOriginalFilename ( ) ) ;
try {
file. transferTo ( dest) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
return "main" ;
}
10.3.4 配置文件解析器
< bean id = " multipartResolver" class = " org.springframework.web.multipart.commons.CommonsMultipartResolver" > </ bean>
第11节:异常处理
11.1 项目开发中异常处理的方式介绍
系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。
11.2 异常处理的设计思路
系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理。
11.3 异常处理的步骤
11.3.1 编写异常类和错误页面
@RequestMapping ( "test2" )
public String test2 ( ) {
System . out. println ( "模拟出现异常" ) ;
int i = 10 / 0 ;
return "main" ;
}
11.3.2 自定义异常处理器
public class MyExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException ( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ex. printStackTrace ( ) ;
System . out. println ( "自定义异常处理" ) ;
ModelAndView modelAndView = new ModelAndView ( ) ;
modelAndView. setViewName ( "error" ) ;
return modelAndView;
}
}
11.3.3 配置异常处理器
< bean class = " com.offcn.util.MyExceptionHandler" > </ bean>
第12节:拦截器使用
12.1 拦截器的介绍和作用
SpringMVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter ,用于对处理器进行预处理和后处理。用户可以自己定义一些拦截器来实现特定的功能。谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain )。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
12.2 拦截器与过滤器的区别
过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。拦截器是 SpringMVC 框架自己的,只有使用了SpringMVC框架的工程才能用。过滤器在web.xml中的 url-pattern 标签中配置了/*之后,可以对所有要访问的资源拦截。拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者js是不会进行拦截的。它也是 AOP 思想的具体应用。
我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。
12.3 自定义拦截器的步骤
12.3.1 编写一个普通类实现 HandlerInterceptor 接口
public class MyIntercepter implements HandlerInterceptor {
@Override
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System . out. println ( "我是控制层执行器方法前的拦截器" ) ;
HttpSession session = request. getSession ( ) ;
String pname= ( String ) session. getAttribute ( "pname" ) ;
if ( pname!= null ) {
return true ;
} else {
request. getRequestDispatcher ( "/login.jsp" ) . forward ( request, response) ;
return false ;
}
}
@Override
public void postHandle ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System . out. println ( "我是控制层执行器方法返回时拦截器" ) ;
}
@Override
public void afterCompletion ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
System . out. println ( "我是控制层执行器方法结束后的拦截器" ) ;
}
}
12.3.2 配置拦截器
< mvc: interceptors>
< mvc: interceptor>
< mvc: mapping path = " /**" />
< mvc: exclude-mapping path = " /file/login" />
< bean class = " com.offcn.util.MyIntercepter" > </ bean>
</ mvc: interceptor>
</ mvc: interceptors>
12.4 拦截器的注意事项
12.4.1 拦截器的放行
拦截器中的放行指的是:如果有下一个拦截器就执行下一个,如果该拦截器处于拦截器链的最后一个,则执行控制器中的方法。
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler) 方法返回true 表示继续执行控制层执行器方法,返回false 表示方法结束,不会执行控制层执行器方法。
12.4.2 拦截器中方法的说明
public class MyInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System . out. println ( "我是控制器方法前拦截器2" ) ;
return true ;
}
@Override
public void postHandle ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System . out. println ( "我是控制层执行器方法返回时拦截器2" ) ;
}
@Override
public void afterCompletion ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
System . out. println ( "我是控制层执行器方法结束后的拦截器2" ) ;
}
}
12.4.3 拦截器的作用路径
< mvc: interceptors>
< mvc: interceptor>
< mvc: mapping path = " /**" />
< mvc: exclude-mapping path = " /file/login" />
< bean class = " com.offcn.util.MyIntercepter" > </ bean>
</ mvc: interceptor>
</ mvc: interceptors>
12.4.4 多个拦截器的执行顺序
(1)多个拦截器放行的情况:
拦截器1 :
public class MyInterceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System . out. println ( "我是控制器方法前拦截器1" ) ;
return true ;
}
@Override
public void postHandle ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System . out. println ( "我是控制层执行器方法返回时拦截器1" ) ;
}
@Override
public void afterCompletion ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
System . out. println ( "我是控制层执行器方法结束后的拦截器1" ) ;
}
}
拦截器2 :
public class MyInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System . out. println ( "我是控制器方法前拦截器2" ) ;
return true ;
}
@Override
public void postHandle ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System . out. println ( "我是控制层执行器方法返回时拦截器2" ) ;
}
@Override
public void afterCompletion ( HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
System . out. println ( "我是控制层执行器方法结束后的拦截器2" ) ;
}
}
执行结果如下:
(2)多个拦截器阻断的情况:
第一个拦截器返回true,第二个拦截器返回false时,执行结果如下:
第一个拦截器返回false,第二个拦截器返回true时,执行结果如下:
第13节:拦截器的简单案例(验证用户是否登录)
13.1 实现思路分析
1 、定义登录页面,并定义请求映射。
2 、判断用户名密码是否正确
3 、如果正确 向 session 中写入用户信息
4 、返回登录成功。
5 、拦截用户请求,判断用户是否登录
6 、如果用户已经登录。放行
7 、如果用户未登录,跳转到登录页面
13.2 案例代码
1 、登录页面login. jsp定义:
< html>
< head>
< title> Title < / title>
< / head>
< body>
< form action= "/file/login" method= "post" >
用户名:< input type= "text" name= "pname" >
密码:< input type= "text" name= "password" >
< input type= "submit" value= "登录" >
< / form>
< / body>
< / html>
2 、控制器实现:
@RequestMapping ( "login" )
public String login ( String pname, String password, HttpSession session) {
System . out. println ( "登录校验成功" ) ;
session. setAttribute ( "pname" , pname) ;
return "main" ;
}
3 、拦截器实现:
@Override
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System . out. println ( "我是控制层执行器方法前的拦截器" ) ;
HttpSession session = request. getSession ( ) ;
String pname= ( String ) session. getAttribute ( "pname" ) ;
if ( pname!= null ) {
return true ;
} else {
request. getRequestDispatcher ( "/login.jsp" ) . forward ( request, response) ;
return false ;
}
}
4 、注册拦截器:
< mvc: interceptor>
< mvc: mapping path= "/**" / > < ! -- 用于指定拦截的 url-- >
< mvc: exclude- mapping path= "/file/login" / > < ! -- 用于指定排除的 url-- >
< bean class = "com.offcn.util.MyIntercepter" > < / bean>
< / mvc: interceptor>