SpringMVC课堂笔记1、SpringMVC概述
SpringMVC概念
SpringMVC 也叫 Spring web mvc。是 Spring内置的一个MVC框架,在 Spring3.0 后发布。SpringMVC 框架解决了WEB开发中常见的问题(参数接收、文件上传、表单验证等等),而且使用简单,与Spring无缝集成。支持 RESTful风格的URL请求。采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。
- SpringMVC原理
在没有使用SpringMVC之前我们都是使用Servlet在做Web开发。但是使用Servlet开发在接收请求参数, 数据共享,页面跳转等操作相对比较复杂。servlet是java进行web开发的标准,既然springMVC是对servlet的封装,那么很显然SpringMVC底层就是Servlet,SpringMVC就是对Servlet进行深层次的封 装。
SpringMVC优势
1、基于 MVC 架构,功能分工明确。解决页面代码和后台代码的分离。
2、简单易用。SpringMVC 也是轻量级的,jar 很小。不依赖的特定的接口和类就可以开发一个注解的
SpringMVC 项目。
3、作 为 Spring 框 架 一 部 分 , 能 够 使 用Spring的IoC和AOP 。 方 便 整 合MyBatis,Hiberate,JPA等其他框架。
4、springMVC的注解强大易用。
2、MVC模式回顾
模型1:jsp+javabean模型—在jsp页面中嵌入大量的java代码
模型2:jsp+servlet+javabean模型—jsp页面将请求发送给servlet,由servlet调用javabean,再 由servlet将制定jsp页面响应给用户。
模型2一般就是现在的MVC模式,也是我们一直使用的。
Model-View-Controller:模型–视图–控制器
Model: 模型层 javaBean 负责数据访问和业务处理 dao service pojo View: 视图 JSP技术 负责收集和展示数据
Controller: 控制器 servlet技术 中间调度控制器的工作:
1、接受客户端的请求(包括请求中携带的数据)
2、处理请求:调用后台的模型层中的业务逻辑
3、页面导航:处理完毕给出响应:JSP页面
3、入门程序
- 创建maven项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZVQYjqHt-1629734137926)(media/image1.png)]{width=“5.114583333333333in” height=“4.791666666666667in”}创建项目并补齐目录结构
-
pom.xml文件添加依赖和插件
-
.3 创建Spring和SpringMVC的配置文件
我们一般将除了 Controller 之外的所有 Bean 注册到 Spring 容器中,而将 Controller 注册到
SpringMVC 容器中。所以我们在 resources 目录下添加 applicationContext.xml 作为 spring 的配置, 添加springmvc.xml作为springmvc的配置文件。
-
创建Spring配置文件applicationContext.xml文件
-
创建SpringMVC的配置文件springmvc.xml
- .4 在web.xml中进行Spring和SpringMVC配置
<!–spring的配置–>
<context-param>
<!–contextConfigLocation:表示用于加载 Bean的配置文件–>
<param-name>contextConfigLocation</param-name>
<!–指定spring配置文件的位置
这个配置文件也有一些默认规则,它的配置文件名默认就叫 applicationContext.xml , 如果将这个配置文件放在 WEB-INF 目录下,那么这里就可以不用 指定配置文件位置, 只需要指定监听器就可以。
这段配置是 Spring 集成 Web 环境的通用配置;一般用于加载除控制器层的 Bean(如dao、service 等),以便于与其他任何Web框架集成。
–>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener- class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!–SpringMVC的配置–>
<!–
前端控制器:所有的请求都会经过此控制器,然后通过此控制器分发到各个分控制器. 前端控制器本质上还是一个Servlet,因为SpringMVC底层就是使用Servlet编写的
–>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet- class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 创建前端控制器的时候读取springmvc配置文件启动ioc容器 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- Tomcat启动就创建此对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置拦截路径url,所有以.do结尾的请求都会被前端控制器拦截处理 -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!–
SpringMVC的配置解析:
1、servlet-class:前端控制器的完全限定名,在spring-webmvc-5.2.5.RELEASE.jar包中的org.springframework.web.servlet下
2、load-on-startup:标记是否在Web服务器(这里是Tomcat)启动时会创建这个 Servlet 实例,即是否在 Web 服务器启动时调用执行该 Servlet 的 init()方
法,而不是在真正访问时才创建。 要求取值是整数。
值大于0:表示容器在启动时就加载并初始化这个 servlet,数值越小,该 Servlet的优先级就越高,其被创建的也就越早
值小于0或者省略:表示该 Servlet 在真正被使用时才会去创建。值相同:容器会自己选择创建顺序
3、url-pattern:可以写为 / ,可以写为*.do 、*.action、*.mvc等形式,此处先写*.do,以后介绍不同写法的区别。
4、init-param:表示了springmvc配置文件的名称和位置。如果没有配置,默认在项目的WEB-INF
目录下找名称为 Servlet 名称-servlet.xml 的配置文件。
如果没有配置,启用默认的规则:即如果配置文件放在 webapp/WEB-INF/ 目录下,并且配置文件的名字等于 DispatcherServlet 的名字+ -servlet(即这里的配置文件路径是 webapp/WEB- INF/dispatcherServlet-servlet.xml),如果是这样的话,可以不用添加 init-param 参数,即不用手动配置 springmvc 的配置文件,框架会自动加载。
而一般情况下,配置文件是放在类路径下,即 resources 目录下。所以,在注册前端控制器时, 还需要设置查找 SpringMVC 配置文件路径。
其中contextConfigLocation属性:来自DispatcherServlet的父类FrameworkServlet, 该类中的contextConfigLocation属性用来配置springmvc的路径和名称。
–>
在springmvc.xml配置文件中添加视图解析器的配置
- .7 编写index.jsp页面
webapp文件夹下面创建文件夹jsp,然后jsp文件夹中添加index.jsp页面
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfybIa4Q-1629734137928)(media/image2.jpeg)]{width=“6.1646926946631675in” height=“3.732083333333333in”}.8 测试
将刚刚的地址复制到浏览器之后追加控制中add方法的访问路径hello.do,看到如下页面表示运行成功!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBoc2b9s-1629734137929)(media/image3.png)]{width=“6.207968066491689in” height=“1.3225in”}
- .9 解析
当 Spring 和 SpringMVC 同时出现,我们的项目中将存在两个容器,一个是 Spring 容器,另一个是
SpringMVC 容器,Spring 容器通过 ContextLoaderListener 来加载,SpringMVC 容器则通过
DispatcherServlet 来加载,这两个容器不一样:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEPoo2AM-1629734137930)(media/image4.png)]{width=“6.212380796150481in” height=“6.233333333333333in”}
如图所示:
ContextLoaderListener 初始化的上下文加载的 Bean 是对于整个应用程序共享的,不管是使用什么表现层技术,一般如 dao层、service层 的bean;
DispatcherServlet 初始化的上下文加载的 bean 是只对 Spring Web MVC 有效的 bean,如
Controller、HandlerMapping、HandlerAdapter 等等,该初始化上下文应该只加载 Web相关组件。
4 、SpringMVC工作流程
- .1 工作流程分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r2P4zAxC-1629734137931)(media/image5.jpeg)]{width=“5.783775153105862in” height=“1.92375in”}
-
用户通过浏览器发送请求到前端控制器DispatcherServlet。
-
前端控制器直接将请求转给处理器映射器HandleMapping。
-
处理器映射器HandleMapping会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链HandlerExecutionChina后返回给前端控制器DispatcherServlet。
-
前端控制器DispatcherServlet根据处理器执行链中的处理器,找到能够执行该处理器的处理器适 配器HandlerAdaptor。
-
处理器适配器HandlerAdaptor调用执行处理器Controller。
-
处理器Controller将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器HandlerAdaptor。
-
处理器适配器直接将结果返回给前端控制器DispatcherServlet。
-
前端控制器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。
-
视图解析器ViewResolver将封装了的视图View对象返回给前端控制器DispatcherServlet.
-
前端控制器DispatcherServlet调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对 象。
-
前端控制器响应浏览器。
- .2 SpringMVC组件
- DispatcherServlet:前端控制器,也称为中央控制器或者核心控制器。
用户请求的入口控制器,它就相当于 mvc 模式中的c,DispatcherServlet 是整个流程控制的中心,相当于是 SpringMVC 的大脑,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。SpringMVC框架提供的该核心控制器需要我们在web.xml文件中配置。
- HandlerMapping:处理器映射器
HandlerMapping也是控制器,派发请求的控制器。我们不需要自己控制该类,但是他是springmvc运 转历程中的重要的一个控制器。 HandlerMapping负责根据用户请求找到 Handler 即处理器(也就是我们所说的 Controller),SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式, 实现接口方式,注解方式等,在实际开发中,我们常用的方式是注解方式。
- Handler:处理器
Handler 是继 DispatcherServlet 前端控制器的后端控制器,在DispatcherServlet 的控制下 Handler 对具体的用户请求进行处理。由于 Handler 涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发 Handler。(这里所说的 Handler 就是指我们的 Controller)
- HandlAdapter:处理器适配器
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展处理器适配器,支持更多类型的处理器,调用处理器传递参数等工作。
- ViewResolver:视图解析器
ViewResolver 负责将处理结果生成 View 视图,ViewResolver 首先根据逻辑视图名解析成物理视图名称,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。 SpringMVC 框架提供了很多的 View 视图类型,包括:jstlView、freemarkerView、pdfView 等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务 需求开发具体的页面。
-
@RequestMapping 注 解
- .1@RequestMapping出现的位置
过@RequestMapping 注解定义了处理器对于请求的映射规则。该注解可以定义在类上,也可以定义在方法上,但是含义不同。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4v1xE8qN-1629734137932)(media/image6.png)]{width=“4.968748906386701in” height=“5.1875in”}
一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中。但若这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在类之上的RequestMapping 的 value 属性中。此时的这个 URI 表示模块的名称。URI 的请求是相对于 Web 的根目录。在类的级别上的注解会将一个特定请求或者请求模式映射到一个控制器之上。之后你还可以另外添加方法级别的注解来进一 步指定到处理方法的映射关系。
示例:修改TeamController.java 如下
package com.kkb.controller;
import com.kkb.service.TeamService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView;
/**
- ClassName: TeamController
*
-
@author wanglina
-
@version 1.0
*/
@Controller @RequestMapping(“team”) public class TeamController {
@Autowired
private TeamService teamService;
@RequestMapping(value = “add.do”) public ModelAndView addTeam(){
System.out.println(“TeamController----addTeam—”); ModelAndView mv=new ModelAndView();
mv.setViewName(“team/add”);// 映射成为物理资源路径:/jsp/team/add.jsp
return mv;
}
@RequestMapping(value = “update.do”) public ModelAndView updateTeam(){
System.out.println(“TeamController----updateTeam—”); ModelAndView mv=new ModelAndView();
mv.setViewName(“team/update”);//映射成为物理资源路径:/jsp/team/update.jsp
return mv;
}
@RequestMapping(“hello.do”) public ModelAndView hello(){
System.out.println(“TeamController----add—”); teamService.add();
ModelAndView mv=new ModelAndView(); mv.addObject(“teamName”,“湖人”);//相当于
request.setAttrubuite(“teanName”,“湖人”);
mv.setViewName(“index”);//未来经过springmvc的视图解析器处理,转换成物理资源路径,
相当于request.getRequestDispatcher(“index.jsp”).forward();
//经过InternalResourceViewResolver对象的处理之后加上前后缀就变为了
/jsp/index.jsp
return mv;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZ3oFPh6-1629734137933)(media/image7.jpeg)]{width=“6.149082458442694in” height=“4.1166655730533686in”}
浏览器中访问:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0RpMGXBZ-1629734137934)(media/image8.png)]{width=“5.895833333333333in” height=“2.84375in”}
- .2 指定请求提交方式
@RequestMapping的method属性,用来对被注解方法所处理请求的提交方式进行限制,即只有满足method 属性指定的提交方式的请求,才会执行该被注解方法。
Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GET 与
RequestMethod.POST,分别表示提交方式的匹配规则为 GET 与 POST 提交。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mB7SlLl-1629734137934)(media/image9.jpeg)]{width=“6.1443853893263345in” height=“5.636666666666667in”}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lHc62g0T-1629734137935)(media/image10.jpeg)]{width=“6.1415266841644796in” height=“2.0079166666666666in”}
以下表格列出了常用的提交方式:
请求方式 提交方式
地址栏请求 get请求
超链接请求 get请求
表单请求 默认get,可以指定post
AJAX请求 默认get,可以指定post
-
.3 补充url-pattern解析
- url-pattern解析
在web.xml配置SpringMVC的前端控制器时有这个节点。这个节点中的值一般有两种写法:
案例:在index.jsp页面添加一张图片,如果节点中的值为*.do,图片可以正常访问,但是如果为/就不能访问。
1、项目中添加图片,同时修改index.jsp页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z9WGVHIl-1629734137935)(media/image11.jpeg)]{width=“6.180491032370954in” height=“3.0225in”}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-67Ra4P2z-1629734137936)(media/image12.jpeg)]{width=“6.173140857392826in” height=“2.446353893263342in”}2、修改web.xml
3、此时访问图片无法显示
- 静态资源访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y54zvn3A-1629734137937)(media/image13.png)]{width=“6.136744313210849in” height=“1.96875in”}如果的值配置为/后,静态资源可以通过以下两种方法解决。5.3.2.1使用< mvc:default-servlet-handler/ > 在springmvc的配置文件中添加如下内容:
5.3.2.2 使 用 < mvc:resources/ >
在springmvc的配置文件中添加如下内容:
在 Spring3.0 版本后,Spring 定义了专门用于处理静态资源访问请求的处理器ResourceHttpRequestHandler。并且添加了< mvc:resources/ >标签,专门用于解决静态资源无法访问问题。
6 、处理器方法的参数
处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值.所以我们可以在方法内直 接使用。以下是这四类参数:
HttpServletRequest HttpServletResponse HttpSession
请求中所携带的请求参数
准备工作:创建新的控制器ParamController.java和前端页面hello.jsp页面
-
直接使用方法的参数逐个接收
-
使用对象接收多个参数
-
请求参数和方法名称的参数不一致
-
使用HttpServletRequest 对象获取参数
-
直接使用URL地址传参
-
获取日期类型的参数
-
获取数组类型的参数
-
获取集合类型的参数
SpringMVC不支持直接从参数中获取对象集合类型,需要将对象集合封装到实体类中。案例源码:
修改实体类Team.java
创建实体类QueryVO.java
前端页面hello.jsp
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
<html>
<head>
<title>hello</title>
</head>
<body>
<h3>8、获取集合类型的参数</h3>
<form action="/param/test08" method=“post”>
球队名称1:<input type=“text” name=“teamName”/><br/> 球队名称2:<input type=“text” name=“teamName”/><br/> 球队名称3:<input type=“text” name=“teamName”/><br/>
<button type=“submit”>提交</button>
</form>
<form action="/param/test09" method=“post”>
球队id1:<input type=“text” name=“teamList[0].teamId”/><br/> 球队id2:<input type=“text” name=“teamList[1].teamId”/><br/> 球队id3:<input type=“text” name=“teamList[2].teamId”/><br/>
球队名称1:<input type=“text” name=“teamList[0].teamName”/><br/> 球队名称2:<input type=“text” name=“teamList[1].teamName”/><br/> 球队名称3:<input type=“text” name=“teamList[2].teamName”/><br/>
<button type=“submit”>提交</button>
</form>
<h3>7、获取数组类型的参数</h3>
<form action="/param/test07" method=“post”>
球队名称1:<input type=“text” name=“teamName”/><br/> 球队名称2:<input type=“text” name=“teamName”/><br/> 球队名称3:<input type=“text” name=“teamName”/><br/>
<button type=“submit”>提交</button>
</form>
<h3>6、获取日期类型的参数</h3>
<form action="/param/test06" method=“post”>
球队id:<input type=“text” name=“teamId”/><br/>
球队名称:<input type=“text” name=“teamName”/><br/> 球队位置:<input type=“text” name=“location”/><br/> 创建日期:<input type=“text” name=“createTime”/><br/>
<button type=“submit”>提交</button>
</form>
<h3>5、直接使用URL地址传参</h3>
<h3>4、使用HttpServletRequest 对象获取参数</h3>
<form action="/param/test04" method=“post”>
球队id:<input type=“text” name=“teamId”/><br/>
球队名称:<input type=“text” name=“teamName”/><br/>
球队位置:<input type=“text” name=“location”/><br/>
<button type=“submit”>提交</button>
</form>
<h3>3、请求参数和方法名称的参数不一致</h3>
<form action="/param/test03" method=“post”>
球队id:<input type=“text” name=“teamId”/><br/>
球队名称:<input type=“text” name=“teamName”/><br/>
球队位置:<input type=“text” name=“location”/><br/>
<button type=“submit”>提交</button>
</form>
<h3>2、使用对象接收多个参数</h3>
<form action="/param/test02" method=“post”>
球队id:<input type=“text” name=“teamId”/><br/>
球队名称:<input type=“text” name=“teamName”/><br/>
球队位置:<input type=“text” name=“location”/><br/>
<button type=“submit”>提交</button>
</form>
<h3>1、直接使用方法的参数逐个接收</h3>
<form action="/param/test01" method=“post”>
球队id:<input type=“text” name=“teamId”/><br/>
球队名称:<input type=“text” name=“teamName”/><br/>
球队位置:<input type=“text” name=“teamLocation”/><br/>
<button type=“submit”>提交</button>
</form>
</body>
</html>
控制器ParamController.java
for (String s : nameList) { System.out.println(s);
}
return new ModelAndView(“ok”);
}
@RequestMapping(“test09”)
public ModelAndView test09(QueryVO vo){ System.out.println("test09 ");
for (Team team : vo.getTeamList()) { System.out.println(team);
}
return new ModelAndView(“ok”);
}
//7、获取数组类型的参数@RequestMapping(“test07”)
public ModelAndView test07(String[] teamName,HttpServletRequest request){ System.out.println("test07 ");
//方式1:
for (String s : teamName) { System.out.println(s);
}
System.out.println(" ");
//方式2:
String[] teamNames = request.getParameterValues(“teamName”); for (String name : teamNames) {
System.out.println(name);
}
return new ModelAndView(“ok”);
}
//6、获取日期类型的参数@RequestMapping(“test06”)
public ModelAndView test06(Team team){ System.out.println("test06 ");
System.out.println(team); return new ModelAndView(“ok”);
}
//5、直接使用URL地址传参: 借助@PathVariable 注解
// 例 如 http://localhost:8080/param/test05/1001/lacker/las @RequestMapping(“test05/{id}/{name}/{loc}”)
public ModelAndView test05(@PathVariable(“id”) Integer teamId,
@PathVariable(“name”) String teamName, @PathVariable(“loc”) String teamLocation){
System.out.println("test05 ");
System.out.println(teamId); System.out.println(teamName); System.out.println(teamLocation); return new ModelAndView(“ok”);
}
//4、使用HttpServletRequest 对象获取参数:跟原来的javaWeb项目中使用的方式是一样的
@RequestMapping(“test04”)
public ModelAndView test04(HttpServletRequest request){ System.out.println("test04 ");
String teamId = request.getParameter(“teamId”); String teamName = request.getParameter(“teamName”); String location = request.getParameter(“location”); if(teamId!=null)
System.out.println(Integer.valueOf(teamId)); System.out.println(teamName); System.out.println(location);
return new ModelAndView(“ok”);
}
//3、请求参数和方法名称的参数不一致:使用@RequestParam进行矫正,
// value属性表示请求中的参数名称
// required属性表示参数是否是必须的:true:必须赋值,否则报出400错;false:可以不赋值, 结果就是null
@RequestMapping(“test03”)
public ModelAndView test03(@RequestParam(value = “teamId”,required = false) Integer id,
String name,
@RequestParam(value = “teamName”,required = true)
@RequestParam(“location”) String loc){
System.out.println("test03 ");
System.out.println(id); System.out.println(name); System.out.println(loc); return new ModelAndView(“ok”);
}
//2、使用对象接收多个参数:要求用户请求中携带的参数名称必须是实体类中的属性保持一致,否则就 获取不到
@RequestMapping(“test02”)
public ModelAndView test02(Team team){ System.out.println("test02 ");
System.out.println(team); return new ModelAndView(“ok”);
}
/**
-
1、直接使用方法的参数逐个接收:方法的参数名称必须与用户请求中携带的参数名称保持一致,否则 就获取不到
-
好处:不需要类型转换
*/ @RequestMapping(“test01”)
public ModelAndView test01(Integer teamId,String teamName,String teamLocation){
System.out.println("test01 ");
System.out.println(teamId); System.out.println(teamName); System.out.println(teamLocation); return new ModelAndView(“ok”);
}
@RequestMapping(“hello”) public ModelAndView hello(){
return new ModelAndView(“hello”);
}
}
7 、请求参数中文乱码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a8TYMO57-1629734137937)(media/image14.png)]{width=“5.718748906386701in” height=“3.78125in”}对于前面所接收的请求参数,若含有中文,则会出现中文乱码问题。Spring 对于请求参数中的中文乱码问题,给出了专门的字符集过滤器CharacterEncodingFilter 类。如图所示。
- .1 乱码解决方案
在 web.xml 中注册字符集过滤器,推荐将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。
在web.xml配置文件直接注册字符集
<!–注册字符集过滤器:post请求中文乱码问题的解决方案–>
<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>
<!–强制request使用字符集encoding–>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!–强制response使用字符集encoding–>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UwGVYEyw-1629734137938)(media/image15.png)]{width=“6.198439413823272in” height=“3.930207786526684in”}.2 解决方案原理
7 、处理器方法的返回值
使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:
-
ModelAndView
-
String
-
返回自定义类型对象
-
无返回值 void
咱们根据实际的业务选择不同的返回值。案例准备工作:
创建控制器ResultController.java
在jsp文件夹中添加页面result.jsp
- .1 返回ModelAndView
如果是前后端不分的开发,大部分情况下,我们返回 ModelAndView,即数据模型+视图: 控制器ResultController.java中添加方法:
Model 中,放我们的数据,然后在 ModelAndView 中指定视图名称。
当处理器方法处理完后,需要跳转到其它资源的同时传递数据,选择返回 ModelAndView 比较好,但是如果只是需要传递数据或者跳转之一,这个时候ModelAndView 就不是最优选择。
result.jsp页面中添加如下内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0wXOahkk-1629734137938)(media/image16.png)]{width=“4.572916666666667in” height=“1.8333333333333333in”}
- .2 返回String
上一种方式中的 ModelAndView 可以拆分为两部分,Model 和 View,在 SpringMVC 中,Model 我们可以直接在参数中指定,然后返回值是逻辑视图名,视图解析器解析可以将逻辑视图名称转换为物理视 图地址。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s2GVD8cE-1629734137939)(media/image17.png)]{width=“5.9906167979002625in” height=“0.7039577865266842in”}
视图解析器通过内部资源视图解析器InternalResourceViewResolver将字符串与解析器中的prefix和
suffix结合形成要跳转的额URI。
控制器ResultController.java中添加方法:
result.jsp页面中添加如下内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l0esaIMD-1629734137939)(media/image18.png)]{width=“6.020832239720035in” height=“2.7604166666666665in”}
- .3 返回对象类型
当处理器方法返回Object对象类型的时候,可以是Integer、String、Map、List,也可以是自定义的对 象类型。但是无论是什么类型,都不是作为逻辑视图出现,而是直接作为数据返回然后展示的。一般前 端发起Ajax请求的时候都会使用直接返回对象的形式。
返回对象的时候,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。
pom.xml文件中添加两个依赖
-
返回基础类型
-
返回自定义对象类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cYTLlChK-1629734137940)(media/image19.png)]{width=“5.145833333333333in” height=“4.135416666666667in”}
- 返回集合List
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l7yLGyMD-1629734137941)(media/image20.jpeg)]{width=“5.412905730533684in” height=“4.775624453193351in”}
- 返回集合Map
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nnxOZhue-1629734137942)(media/image21.jpeg)]{width=“6.15in” height=“6.075in”}
- .4 无返回值 void-了解
方法的返回值为 void,并不一定真的没有返回值,我们可以通过其他方式给前端返回。实际上,这种方式也可以理解为 Servlet 中的的处理方案。
8 、页面导航的方式
页面导航分为两种:1、转发 2、重定向
springMVC有以下两种方式实现页面的转发或重定向: 1、返回字符串
2、使用ModelAndView
在SpringMVC中两种导航进行页面导航的时候使用不同的前缀指定转发还是重定向前缀: 转发: forward:url 默 认
重定向: redirect:url
准备工作:创建一个新的控制器NavigationController.java:
-
.1 转发到一个jsp页面
-
字符串方式转发
-
ModelAndView转发
-
-
.2 重定向到一个jsp页面
-
字符串方式重定向
-
ModelAndView重定向方式
-
-
.3 重定向或者转发到控制器
9 、异常处理
SpringMVC框架常用@ExceptionHandler 注解处理异常。
- .1@ExceptionHandler 注 解
@ExceptionHandler 可以将一个方法指定为异常处理方法。
被注解的方法,其返回值可以是 ModelAndView、String,或 void,方法名随意,方法参数可以是Exception 及其子类对象、HttpServletRequest、HttpServletResponse 等。系统会自动为这些方法参数赋值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dV29LQrb-1629734137942)(media/image22.jpeg)]{width=“6.1624890638670164in” height=“1.891353893263342in”}对于异常处理注解的用法,也可以直接将异常处理方法注解于 Controller 之中.
-
.2 实现步骤
- 自定义异常类
编写控制器
编写error.jsp、idError.jsp、nameError.jsp页面
测试:
h ttp://localhost:8080/ex/test01/100/test1 h ttp://localhost:8080/ex/test01/1004/test
h ttp://localhost:8080/ex/test01/1001/test1
- .3优化
一般将异常处理方法专门定义在一个类中,作为全局的异常处理类。
使用注解@ControllerAdvice,就是"控制器增强",是给控制器对象增强功能的。使用
@ControllerAdvice 修饰的类中可以使用@ExceptionHandler。
当使用@RequestMapping 注解修饰的方法抛出异常时,会执行@ControllerAdvice 修饰的类中的异常处理方法。
@ControllerAdvice 注解所在的类需要进行包扫描,否则无法创建对象。
定义全局异常处理类:
1 0、拦截器
SpringMVC 中的 拦截器( Interceptor)是非常重要的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。
拦截的时间点在"处理器映射器HandlerMapping根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器HandlerAdaptor执行处理器之前"。
在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链
HandlerExecutionChain,并返回给了前端控制器。
自定义拦截器,需要实现 HandlerInterceptor 接口。而该接口中含有三个方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U96v4m3Q-1629734137943)(media/image23.png)]{width=“6.222575459317586in” height=“2.906665573053368in”}
- .1 自定义拦截器
package com.kkb.interceptor;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
/**
-
ClassName: MyInterceptor
-
自定义拦截器
-
@author wanglina
-
@version 1.0
*/
public class MyInterceptor2 implements HandlerInterceptor {
//执行时间: 控制器方法执行之前,在ModelAndView返回之前
//使用场景: 登录验证
// 返回值 true : 继续执行控制器方法 表示放行 false: 不会继续执行控制器方法,表示拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle2 ");
return true;
}
//执行时间: 控制器方法执行之hou后,在ModelAndView返回之前,有机会修改返回值
//使用场景: 日记记录,记录登录的ip,时间
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle-2 ");
}
//执行时间: 控制器方法执行之后,在ModelAndView返回之后,没有机会修改返回值
.2 配置拦截器
在springmvc.xml中添加如下配置
1 1、文件上传和下载
Spring MVC为文件上传提供了直接支持,这种支持是通过即插即用的MultipartResolver实现.
Spring中有一个MultipartResolver的实现类:CommonsMultipartResolver。
在SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下不能处理文件上传工作。 如果想使用Spring的文件上传功能,则需要先在上下文中配置MultipartResolver。
- 1 文件上传
(1)添加依赖
(2)springmvc.xml文件中配置MultipartResolver:
-
fileHandle.jsp页面表单
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VQ39RMkG-1629734137944)(media/image24.png)]{width=“4.197916666666667in” height=“3.5208333333333335in”}配置java代码(注意要创建文件夹保存上传之后的文件)
/**
-
ClassName: FileController
-
文件操作的控制器
-
@author wanglina
-
@version 1.0
*/ @Controller
@RequestMapping(“file”) public class FileController {
/**
-
文件上传
-
@param myFile
-
@param request
-
@return
*/ @RequestMapping(“upload”)
public String upload(@RequestParam(“myFile”) MultipartFile myFile, HttpServletRequest request){
//获取文件的原始名称 d:\te.aa\txcat.jpg
String originalFilename = myFile.getOriginalFilename();
// 实际开发中,一般都要将文件重新名称进行存储
// 存储到服务器的文件名称=随机的字符串+根据实际名称获取到源文件的后缀
String fileName= UUID.randomUUID().toString().replace("-","")
+originalFilename.substring(originalFilename.lastIndexOf(".")); System.out.println(fileName);
//文件存储路径
String realPath = request.getServletContext().getRealPath("/uploadFile")+"/";
try {
myFile.transferTo(new File(realPath+fileName));//真正的文件上传到服务器指
定的位置
System.out.println(“上传成功!”+realPath+fileName);
} catch (IOException e) { e.printStackTrace();
}
return “ok”;
}
@RequestMapping(“hello”) public String hello(){
return “fileHandle”;
}
}
优化:如果需要限定文件的大小和类型:
package com.kkb.interceptor;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Iterator;
import java.util.Map;
/**
-
ClassName: FileInterceptor
-
文件后缀处理的拦截器
-
@author wanglina
-
@version 1.0
*/
public class FileInterceptor implements HandlerInterceptor {
/**
- 在文件上传之前判断文件后缀是否合法
*/ @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断是否是文件上传的请求
boolean flag=true;
if(request instanceof MultipartHttpServletRequest){ MultipartHttpServletRequest multipartRequest=
(MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
//遍历文件
Iterator<String> iterator = fileMap.keySet().iterator(); while(iterator.hasNext()){
String key = iterator.next();
MultipartFile file = multipartRequest.getFile(key); String originalFilename = file.getOriginalFilename(); String hz =
originalFilename.substring(originalFilename.lastIndexOf("."));
//判断后缀是否合法if(!hz.toLowerCase().equals(".png") &&
!hz.toLowerCase().equals(".jpg")){
request.getRequestDispatcher("/jsp/fileTypError.jsp").forward(request,response)
;
flag=false;
}
}
}
return flag;
}
}
上传文件类型错误跳转的页面fileError.jsp
- 2 文件下载
(1)前端页面
(2)配置处理类方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PsKZP5zS-1629734137944)(media/image25.jpeg)]{width=“6.106798993875765in” height=“2.3788538932633423in”}
1 2、RESTful风格
- 1 REST概念
REST(英文:Representational State Transfer,简称REST,意思:表述性状态转换,描述了一个架构样式的网络系统,比如web应用)。
它是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件,它主要用于客 户端和服务端交互类的软件。基于这个风格设计的软件可以更简介,更有层次,更易于实现缓存等机 制。
它本身并没有什么使用性,其核心价值在于如何设计出符合REST风格的网络接口。
- 2 RESTful概念
REST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。RESTful的特性:
资源(Resources):互联网所有的事物都可以被抽象为资源 。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特性的URI。要获取这个资源,访问它的URI就可以,因此URI即为每一个资源的独一无二的识别符。
表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式。
状态转换(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议, 是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某 种手段,让服务器端发生"状态转换"(State Transfer)。而这种转换是建立在表现层之上的,所以就是"表现层状态转换"。
具体来说就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。他们分别对应 四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。
原来的操作资源的方式:
http://localhost:8080/getExpress.do?id=1 http://localhost:8080/saveExpress.do http://localhost:8080/updateExpress.do http://localhost:8080/deleteExpress.do?id=1
原来用的方式当然没有问题,但是如果有更简洁的方式就更好了,此时就是RESTful风格。
使用RESTful操作资源:
GET /expresses #查询所有的快递信息列表GET /express/1006 #查询一个快递信息POST /express #新建一个快递信息
PUT /express/1006 #更新一个快递信息(全部更新) PATCH /express/1006 #更新一个快递信息(部分更新) DELETE /express/1006 #删除一个快递信息
-
3 API设计/URL设计
- 动词+宾语
RESTful 的核心思想就是客户端的用户发出的数据操作指令都是"动词 + 宾语"的结构。例如GET
/expresses 这个命令,GET是动词,/expresses 是宾语。
- 宾语必须是名词
宾语就是 API 的 URL,是 HTTP 动词作用的对象。它应该是名词,不能是动词。比如,/expresses 这个 URL 就是正确的。
ps:不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
- 避免多级URL
如果资源中有多级分类,也不建议写出多级的URL。例如要获取球队中某个队员,有人可能这么写:
GET /team/1001/player/1005
这种写法的语义不够明确,所以推荐使用查询字符串做后缀,改写为
GET /team/1001?player=1005.
- 4 HTTP状态码
客户端的用户发起的每一次请求,服务器都必须给出响应。响应包括 HTTP 状态码和数据两部分。
HTTP 状态码就是一个三位数,分成五个类别。这五大类总包含了100多种状态码(不需要全都记住,不用紧张哈,覆盖了绝大部分可能遇到的情况。每一种状态码都有标准的(或者约定的)解释,客户端只 需查看状态码,就可以判断出发生了什么情况,所以服务器应该返回尽可能精确的状态码。
- 状态码2xx
200 状态码表示操作成功,但是不同的方法可以返回更精确的状态码。
- 状态码3xx
API 用不到 301 状态码(永久重定向)和 302 状态码(暂时重定向, 307 也是这个含义),因为它们可以由应用级别返回,浏览器会直接跳转,API 级别可以不考虑这两种情况。
API 用到的 3xx 状态码,主要是 303 See Other ,表示参考另一个 URL。它与 302 和 307 的含义一
样,也是"暂时重定向",区别在于 302 和 307 用于GET 请求,而 303 用于POST 、 PUT 和DELETE 请求。收到 303 以后,浏览器不会自动跳转,而会让用户自己决定下一步怎么办。
- 状态码4xx
4xx 状态码表示客户端错误。
±------±-----------------------------------------------------------------------------------------+
| > 400 | > Bad Request:服务器不理解客户端的请求,未做任何处理。 |
+=+====================================================================================+
| > 401 | > Unauthorized:用户未提供身份验证凭据,或者没有通过身份验证。 |
±------±-----------------------------------------------------------------------------------------+
| > 403 | > Forbidden:用户通过了身份验证,但是不具有访问资源所需的权限。 |
±------±-----------------------------------------------------------------------------------------+
| > 404 | > Not Found:所请求的资源不存在,或不可用。 |
±------±-----------------------------------------------------------------------------------------+
| > 405 | > Method Not Allowed:用户已经通过身份验证,但是所用的 HTTP 方法不在他的权限之内。 |
±------±-----------------------------------------------------------------------------------------+
| > 410 | > Gone:所请求的资源已从这个地址转移,不再可用。 |
±------±-----------------------------------------------------------------------------------------+
| > 415 | > Unsupported Media Type:客户端要求的返回格式不支持。比如,API 只能返回 JSON 格式,但是 |
±------±-----------------------------------------------------------------------------------------+
状态码5xx
5xx 状态码表示服务端错误。一般来说,API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了。
- 5 服务器响应
服务器返回的信息一般不推荐纯文本,而是建议大家选择JSON 对象,因为这样才能返回标准的结构化数据。
所以,服务器回应的 HTTP 头的Content-Type 属性要设为application/json 。客户端请求时,也要明确告诉服务器,可以接受 JSON 格式,即请求的 HTTP 头的ACCEPT 属性也要设成
当发生错误的时候,除了返回状态码之外,也要返回错误信息。所以我们可以自己封装要返回的信息。
-
6 案例
- RESTful风格的查询
前端页面restful.jsp
</html>
<script>
//页面加载完毕之后给按钮绑定事件
$(function () {
//给 查询所有GET 按钮绑定单击事件
$("#btnGetAll").click(function () {
//发起异步请求
$.ajax({
type: “GET”,
url: “/teams”, //RESTful风格的API定义data: “”,
dataType:“json”, success: function(list){
alert( “Data Saved: " + list ); var str=”";
for(var i=0;i<list.length;i++){ var obj=list[i];
str+=obj.teamId+"----"+obj.teamName+"----
“+obj.location+”<br/>";
}
$("#showResult").html(str);
}
});
});
//给 查询单个GET 按钮绑定单击事件
$("#btnGetOne").click(function () {
//发起异步请求
$.ajax({
type: “GET”,
url: “/team/”+$("#teamId").val(), //RESTful风格的API定义data: “”,
dataType:“json”, success: function(obj){
alert( “Data Saved: " + obj ); if(obj==”"){
$("#showResult").html(“没有复合条件的数据!”);
}else
$("#showResult").html(obj.teamId+"----"+obj.teamName+"----
“+obj.location+”<br/>");
}
});
});
});
</script>
控制器RestfulController.java
import java.util.ArrayList; import java.util.List;
/**
-
ClassName: RestfulController
-
restful风格的控制器
-
@author wanglina
-
@version 1.0
*/ @Controller
public class RestfulController {
private static List<Team> teamList; static {
teamList=new ArrayList<>(3); for(int i=1;i<=3;i++){
Team team=new Team(); team.setTeamId(1000+i);
team.setTeamName(“湖人”+i);
team.setLocation(“洛杉矶”+i); teamList.add(team);
}
}
/**
-
查询所有的球队
-
@return
*/
@RequestMapping(value = “/teams”,method = RequestMethod.GET) @ResponseBody
public List<Team> getAll(){
System.out.println("查询所有GET–发起的请求 ");
return teamList;
}
/**
-
根据id 查询单个的球队
-
@return
*/
@RequestMapping(value = “/team/{id}”,method = RequestMethod.GET) @ResponseBody
public Team getOne(@PathVariable(“id”)int id){ System.out.println("查询单个GET–发起的请求 ");
for (Team team : teamList) { if(team.getTeamId()==id){
return team;
}
}
return null;
}
@RequestMapping(“hello”) public String hello(){
return “restful”;
}
}
RESTful风格的添加
前端页面上脚本中添加如下内容:
控制器中添加方法
- RESTful风格的更新
前端页面上脚本中添加如下内容:
控制器中添加方法
- RESTful风格的删除
前端页面上脚本中添加如下内容:
控制器中添加方法
-
RESTful风格的更新和删除遇到的问题
-
遇到的问题:
-
产生的原因:
-
解决方案:
-
1、前端页面中的ajax发送请求的时候在url中加 &_method=“PUT” 或者&_method=“DELETE” 即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kd92IYAd-1629734137945)(media/image26.jpeg)]{width=“6.162700131233596in” height=“4.99875in”}
2、web.xml中配置
配置的时候多个过滤器需要注意顺序
-
7 自己封装响应结果
-
封装的实体类
-
修改控制器的返回值
-
*/ @Controller
public class RestfulController {
private static List<Team> teamList; static {
teamList=new ArrayList<>(3); for(int i=1;i<=3;i++){
Team team=new Team(); team.setTeamId(1000+i);
team.setTeamName(“湖人”+i);
team.setLocation(“洛杉矶”+i); teamList.add(team);
}
}
/**
* 根据ID删除一个球队
*/
@RequestMapping(value = “team/{id}”,method = RequestMethod.DELETE) @ResponseBody
public AjaxResultVO<Team> del(@PathVariable(“id”)int id){ System.out.println("删除DELETE–发起的请求 ");
for (Team team1 : teamList) { if(team1.getTeamId()==id){
teamList.remove(team1);
return new AjaxResultVO<Team>();
}
}
return new AjaxResultVO<Team>(500,“要删除的ID不存在~~~”);
}
/**
* 根据ID更新一个球队
*/
@RequestMapping(value = “team/{id}”,method = RequestMethod.PUT) @ResponseBody
public AjaxResultVO<Team> add(@PathVariable(“id”)int id, Team team){ System.out.println("更新PUT–发起的请求 ");
for (Team team1 : teamList) { if(team1.getTeamId()==id){
team1.setLocation(team.getLocation()); team1.setTeamName(team.getTeamName()); return new AjaxResultVO<Team>();
}
}
return new AjaxResultVO<Team>(500,“要更新的ID不存在~~~”);
}
/**
* 添加一个球队
*/
@RequestMapping(value = “team”,method = RequestMethod.POST) @ResponseBody
public AjaxResultVO<Team> add(Team team){ System.out.println("添加POST–发起的请求 ");
teamList.add(team);
return new AjaxResultVO<>(200,“OK”);
}
修改前端页面的脚步
});
//给 更新PUT 按钮绑定单击事件
$("#btnPut").click(function () { alert($("#myForm").serialize());
//发起异步请求
$.ajax({
type: “POST”,
url: “/team/”+$("#teamId").val(), //RESTful风格的API定义
data: $("#myForm").serialize()+"&_method=PUT",//表单的所有数据以?&
形式追加在URL后面 /team?teamId=1006&teamName=kuaichuan&location=las dataType:“json”,
success: function(vo){ if(vo.code==200){
$("#showResult").html(“更新成功!”);
}else {
$("#showResult").html(vo.msg);
}
}
});
});
//给 添加POST 按钮绑定单击事件
$("#btnPost").click(function () { alert($("#myForm").serialize());
//发起异步请求
$.ajax({
type: “POST”,
url: “/team”, //RESTful风格的API定义
data: $("#myForm").serialize(),//表单的所有数据以?&形式追加在URL后面
/team?teamId=1006&teamName=kuaichuan&location=las dataType:“json”,
success: function(vo){ if(vo.code==200){
$("#showResult").html(“添加成功!”);
}else {
$("#showResult").html(vo.msg);
}
}
});
});
//给 查询所有GET 按钮绑定单击事件
$("#btnGetAll").click(function () {
//发起异步请求
$.ajax({
type: “GET”,
url: “/teams”, //RESTful风格的API定义data: “”,
dataType:“json”, success: function(vo) {
if (vo.code == 200) { var list=vo.list; var str = “”;
for (var i = 0; i < list.length; i++) { var obj = list[i];
str += obj.teamId + “----” + obj.teamName + “----” +
obj.location + “<br/>”;
axResultVO<>(200,“OK”);}
修改前端页面的脚步
});
//给 更新PUT 按钮绑定单击事件
$("#btnPut").click(function () { alert($("#myForm").serialize());
//发起异步请求
$.ajax({
type: “POST”,
url: “/team/”+$("#teamId").val(), //RESTful风格的API定义
data: $("#myForm").serialize()+"&_method=PUT",//表单的所有数据以?&
形式追加在URL后面 /team?teamId=1006&teamName=kuaichuan&location=las dataType:“json”,
success: function(vo){ if(vo.code==200){
$("#showResult").html(“更新成功!”);
}else {
$("#showResult").html(vo.msg);
}
}
});
});
//给 添加POST 按钮绑定单击事件
$("#btnPost").click(function () { alert($("#myForm").serialize());
//发起异步请求
$.ajax({
type: “POST”,
url: “/team”, //RESTful风格的API定义
data: $("#myForm").serialize(),//表单的所有数据以?&形式追加在URL后面
/team?teamId=1006&teamName=kuaichuan&location=las dataType:“json”,
success: function(vo){ if(vo.code==200){
$("#showResult").html(“添加成功!”);
}else {
$("#showResult").html(vo.msg);
}
}
});
});
//给 查询所有GET 按钮绑定单击事件
$("#btnGetAll").click(function () {
//发起异步请求
$.ajax({
type: “GET”,
url: “/teams”, //RESTful风格的API定义data: “”,
dataType:“json”, success: function(vo) {
if (vo.code == 200) { var list=vo.list; var str = “”;
for (var i = 0; i < list.length; i++) { var obj = list[i];
str += obj.teamId + “----” + obj.teamName + “----” +
obj.location + “<br/>”;