文章目录
SpirngMVC有一套比较完善的注解,SpringMVC是负责Controller,web层的注解,Spring是负责dao层,service层。
需求:客户端发送请求,服务器端接收请求,执行逻辑并进行视图跳转。
1.SpringMVC的开发步骤
1.导入springMVC相关坐标
2.配置springMVC核心控制器DispatcherServlet
3.创建Controller类和视图页面
4.使用注解配置Controller类中业务方法的映射地址
5.配置springMVC核心文件spring-mvc.xml
6.客户端发送请求测试
1.1 导入springMVC相关坐标
<!-- 导入springMVC的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
1.2 配置springMVC核心控制器DispatcherServlet
web.xml
<!-- 配置springMVC的前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
1.3 创建Controller类和视图页面
1.4 使用注解配置Controller类中业务方法的映射地址
创建UserController.java
@Controller
public class UserController {
@RequestMapping("/quick")
public String save(){
System.out.println("Controller save running---");
return "success.jsp";
}
}
1.5 配置springMVC核心文件
spring-mvc.xml
<!-- controller的组件扫描 -->
<context:component-scan base-package="com.itheima.controller"></context:component-scan>
我们配置好了spring-mvc.xml,还要在加载的时候读它,在web.xml配置springMVC的前端控制器的时候配置初始化参数去读spring-mvc.xml
<!-- 配置springMVC的前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.从前端url的角度去看springMVC的实现逻辑
3.SpringMVC的执行流程
1.用户发送请求到前端控制器DispatcherServlet。
2.DispatcherServlet收到请求调用处理器映射器HandlerMapping。
3.处理器映射器HandlerMapping找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4.DispatcherServlet调用处理器适配器HandlerAdapter。
5.HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6.Controller执行完成返回ModelAndView。
7.HandlerAdapter将controller的执行结果ModelAndView返回给DispatcherServlet。
8.DispatcherServlet将ModelAndView传给视图解析器ViewReslover。
9.ViewReslover解析后返回具体的View。
10.DispatcherServlet根据View进行渲染视图(即将数据模型填充至视图中)。DispatcherServlet响应用户。
4.SpringMVC的注解解析
@RequestMapping
作用:用于建立请求URL和处理请求方法之间的对应关系。
位置:类上,请求URL的一级访问目录,此处不写的话,就相当于应用的根目录;
方法上,请求URL的二级访问目录,与类上的使用@RequestMapping标注的一级目录一起组成访问虚拟路径属性。
属性:
value:用于指定请求的URL。它和path属性的作用一样
method:用于制定请求的方式
params:用于制定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须和配置的一模一样;params用的不多,例如:params={“accountName”},表示请求参数必须有accountName ;params={“money!100”},表示请求参数中money不能是100。
@Controller
@RequestMapping("/user")
public class UserController {
//访问地址为:localhost:8080/user/quick /user是找到这个controller,/quick是找到这个方法
@RequestMapping("/quick")
public String save(){
System.out.println("Controller save running---");
//因为类上有@RequestMapping("/user"),所以这里返回的地址加上/,因为success.jsp是在webapp下的,
//这里的一级目录是/user,不加的
参数绑定注解@RequestParam
当请求的参数名称与Controller的业务方法参数名称不一致时,就需要通过@RequestParam注解显示的绑定。
@RequestParam的参数:value:与请求参数名称匹配
required:此在指定的请求参数是否必须包括,默认是true,提交时如果没有此参数则报错.
defaultValue:当没有指定请求参数时,则使用指定的默认值赋值.
@RequestMapping("/quick16")
@ResponseBody
public void save16(@RequestParam("name") String username) throws IOException {
System.out.println(username);
}
访问http://localhost:8080/user/quick16?name=zhangsan 控制台打印zhangsan
@RequestBody
告知SpringMVC框架 不进行视图跳转 直接进行数据响应
@RequestHeader
使用@RequestHeader可以获得请求头信息,相当于request.getHeader(name)
@RequestHeader注解的属性如下:
value:请求头的名称
required:是否必须携带此请求头
@CookieValue
使用@CookieValue可以获得指定Cookie的值
@CookieValue注解的属性如下:
value:请求头的名称
required:是否必须携带此cookie
5.Springmvc的数据响应方式
5.1 页面跳转
直接返回字符串,或者通过ModelAndView对象返回
5.1.1 返回字符串
5.1.2 通过ModelAndView对象返回
UserController.java
@RequestMapping("/user")
public class UserController {
@RequestMapping("/quick1")
public ModelAndView save(){
//Model:模型,作用封装数据, View:视图,作用展示数据
ModelAndView modelAndView = new ModelAndView();
//设置数据模型
modelAndView.addObject("username","itcast");
//设置视图名称
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping("/quick3")
public ModelAndView save3( ModelAndView modelAndView){
modelAndView.addObject("username","itheima");
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping("/quick4")
public String save4(Model model){
model.addAttribute("username","it123");
return "success";
}
@RequestMapping("/quick5")
public String save5(HttpServletRequest req){
req.setAttribute("username","it456");
return "success";
}
}
spring-mvc.xm配置视图解析器l:视图解析器的作用是只对Controller类中每个函数返回值那里的String类型前后加路径,而不对@RequestMapping处加路径,对@RequestMapping处无影响!关键字forward和redirect不和视图解析器一起工作,即return “redirect:/login.jsp”;仍然需要带上.jsp
<!-- 配置内部资源视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
//视图解析器的作用是只对Controller类中每个函数返回值那里的String类型前后加路径,
//而不对@RequestMapping处加路径,对@RequestMapping处无影响!
5.2 回写数据
直接返回字符串,或者返回对象或集合
5.2.1 通过HttpServletResponse回写数据
@RequestMapping("/quick6")
public void save6(HttpServletResponse resp) throws IOException {
resp.getWriter().println("hello itcast");
}
5.2.2 直接返回数据串
需要通过@ResponseBody注解告知SpringMVC框架,方法返回的字符串不是跳转而是直接在http响应体中返回。
@RequestMapping("/quick7")
@ResponseBody //如果不加这个这个会跳转到/jsp/hello itheima.jsp
public String save7(HttpServletResponse resp) throws IOException {
return "hello itheima";
}
5.2.3 以JSON格式返回字符串(常用)
@RequestMapping("/quick8")
@ResponseBody
public String save8() throws IOException {
User user = new User();
user.setUsername("lisi");
user.setAge(18);
//使用json转换工具讲对象转换成json格式字符串再返回,需要导入依赖
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(user);
return json;
}
所需依赖的pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
5.2.4 返回对象或集合
@RequestMapping("/quick9")
@ResponseBody
//期望SpringMVC自动将user对象转换为JSON格式的字符串
public User save9() throws IOException {
User user = new User();
user.setUsername("lisi");
user.setAge(18);
return user;
}
需要配置处理器映射器,spring-mvc.xml
<beans xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- mvc的注解驱动-->
<mvc:annotation-driven />
6.获得请求参数
SpringMVC可以接收如下的参数:基本数据类型参数、POJO数据类型参数、数组类型参数、集合类型参数
6.2.1 获得基本数据类型参数
Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配。
@RequestMapping("/quick11")
@ResponseBody
public void save11(String username,int age) throws IOException {
System.out.println(username);
System.out.println(age);
}
运行访问http://localhost:8080/user/quick11?username=lisa&age=18,控制台输出lisa 18
6.2.2 获得POJO类型参数
Controller中的业务方法的POJO参数的属性名要与请求参数的name一致,参数值会自动映射匹配。
@RequestMapping("/quick12")
@ResponseBody
public void save12(User user) throws IOException {
System.out.println(user);
}
运行访问http://localhost:8080/user/quick12?username=lisa&age=18,控制台输出User{username=‘lisa’, age=18}
6.2.3 获得数组类型参数
Controller中的业务方法的数组名称要与请求参数的name一致,参数值会自动映射匹配。
@RequestMapping("/quick13")
@ResponseBody
public void save13(String[] strs) throws IOException {
System.out.println(Arrays.asList(strs));
}
运行访问http://localhost:8080/user/quick13?strs=aaa&strs=bbb&strs=ccc,控制台输出[aaa, bbb, ccc]
5.2.4 获得集合类型参数
获得集合参数时,要将集合参数包装到一个POJO中才可以。
创建一个POJO对象,VO.java,用于封装集合参数:
public class VO{
private List<User> userList;
Getter,Setter,Tostring方法
}
@RequestMapping("/quick14")
@ResponseBody
public void save14(VO vo) throws IOException {
System.out.println(vo);
}
5.2.5 获得Restful风格的参数
Restful风格的请求时使用“url+请求方式”表示一次请求目的的,HTTP协议里面四个表示操作方式的动词如下:
GET:用于获取资源 POST:用于新建资源
PUT:用于更新资源 DELETE:用于删除资源
例如:
/user/1 GET: 得到id=1的user
/user/1 DELETE: 删除id=1的user
/user/1 PUT: 更新id=1的user
/user POST: 新增user
例子:url地址/user/1中的1就是要获取的参数,在springmvc中可以使用占位符进行参数绑定,地址/user/1可以写成/user/{id},占位符{id}对应的就是1的值。在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作。
//http://localhost:8080/user/quick17/zhangsan
@RequestMapping("/quick17/{name}")//这里的name要和注解里value中的值一样,但是不用和方法参数一样
@ResponseBody
public void save17(@PathVariable(value = "name") String username) throws IOException {
System.out.println(username);
}
访问http://localhost:8080/user/quick17/zhangsan 控制台打印zhangsan
7.异常处理
7.1 异常处理的思路
系统中的异常通常包括两类:预期异常和运行时异常RunningtimeException,前者通过捕获异常从而获得异常信息,后者主要是通过规范代码开发、测试等手段减少运行时异常的发生。
系统的Dao,Service,Controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理,如下图:
7.2 异常处理的两种方式
1.使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver
2.实现Spring的异常处理接口HandleExceptionResolver自定义自己的异常处理器
7.2.1 简单异常处理器SimpleMappingExceptionResolver
<!--配置异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="error"/>
<property name="exceptionMappings">
<map>
<entry key="java.lang.ClassCastException" value="error1"/>
<entry key="com.itheima.exception.MyException" value="error2"/>
</map>
</property>
</bean>
7.2.2 自定义异常处理器
自定义异常的步骤:
1.创建异常处理器实现HandleExceptionResolver
2.配置异常处理器
3.编写异常页面
4.测试异常跳转
第一步创建异常处理器实现HandleExceptionResolver:
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
//处理异常的代码实现
//创建ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("exceptionPage");
return modelAndView;
}
}
第二步,配置异常处理器spring-mvc.xml
<!--自定义异常处理器-->
<bean id="exceptionResolver" class="com.itheima.resolver.MyExceptionResolver"/>
第三步,编写异常页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
这是一个最终异常的显示页面
</body>
</html>
第四步,测试异常跳转
@RequestMapping("/quick22")
@ResponseBody
public void quickMethod22() throws IOException, ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
simpleDateFormat.parse("abcde");
}