SpringMVC
开发步骤
1.导入SpringMVC包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.25</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
2.配置SpringMVC核心控制器DispathcerServlet和监听器
<!--配置spring监听器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在web.xml中添加
<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>
3.编写Controller类和视图
在com.包名下创建controller包,然后创建Controller类
4.将Controller使用注解配置到Spring容器中(@Controller)
@Controller
public class UserController {
@RequestMapping("/quick")
public String Save(){
System.out.println("Controller save running...");
return "success.jsp";
}
}
5.配置spring-mvc.xml文件(配置组件扫描)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="com.zy.controller"/>
</beans>
6.执行访问测试
SpringMVC执行流程
- 用户发送请求到前端控制器DispatcherServlet
- DipatcherServlet收到请求调用HandlerMapping处理器映射器
- 处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器,一并返回给DispatcherServlet
- DispatcherServlet调用HandlerAdaoter处理器适配器
- HandlerAdapter经过适配调用具体的处理器(Controller)
- Controller执行完成后返回ModelAndView
- HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- ViewReslover解析后返回具体View
- DispatcherServlet根据View进行渲染视图,DispatcherServlet响应用户
SpringMVC注解解析
@RequestMapping
作用:用于建议请求URL和处理请求方法之间的对应关系
位置:
- 类上,请求URL的第一级访问目录。此处不写的话,就相当于应用的根目录。
- 方法上,请求URL的第二级访问目录,与类上是使用标注的一级目录组成访问虚拟路径
- value:用户指定请求的URL。它和Path属性的作用是一样的
- method:用户指定请求的方法
@RequestMapping(value = "/quick",method = RequestMethod.POST)
- params:用户指定限制请求参数的条件。它支持简单的表达式,要求参数的key和value必须配置一样。
- params=["accountName"],表示请求参数必须有accountName
- params=["moeny!100"],表示请求参数中money不能是100
SpringMVC组件扫描
spring-mvc.xml用于扫描Controller层
<context:component-scan base-package="com.zy.controller"/>
或
<context:component-scan base-package="com.zy">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
SpringMVC的视图XML配置解析(资源解析器)
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
配置完成后可以直接返回return "success";
,不需要retrun "/jsp/success.jsp"
SpringMVC知识要点
SpringMVC的相关组件
- 前端控制器:DispatcherServlet
- 处理器映射器:HandlerMapping
- 处理器适配器:HandlerAdapter
- 处理器:Handler
- 视图解析器:ViewResolver
- 视图:view
SpringMVC的注解和配置
- 请求映射注解:@RequestMapping
- 视图解析配置
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
SpringMVC的数据响应
数据响应方式
1)页面跳转
- 直接返回字符串
- 通过ModelAndView对象返回
2)回写数据
- 直接返回字符串
- 返回对象或集合
页面跳转
1.返回字符串形式
直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转。
2.返回ModelAndView对象
<%@ page language="java" pageEncoding="utf-8" isELIgnored="false"%>
<h1>Success: ${username}</h1>
@RequestMapping(value = "/quick2",method = RequestMethod.GET)
public ModelAndView Save2(){
/*
* Model 模型 封装数据
* View 视图 展示数据
* */
ModelAndView modelAndView = new ModelAndView();
//设置模型数据
modelAndView.addObject("username","itcast");
//设置视图名称
modelAndView.setViewName("success");
return modelAndView;
}
或者
@RequestMapping(value = "/quick3",method = RequestMethod.GET)
public ModelAndView Save3(ModelAndView modelAndView){
//设置模型数据
modelAndView.addObject("username","itcast");
//设置视图名称
modelAndView.setViewName("success");
return modelAndView;
}
或
@RequestMapping(value = "/quick4", method = RequestMethod.GET)
public String Save4(Model model) {
model.addAttribute("username","zy");
return "success";
}
回写数据
直接返回字符串
① 通过SpringMVC框架注入的response对象,使用response.getWriter().print("hello")回写数据,此时不需要视图跳转,业务方法返回值为void。
@RequestMapping(value = "/quick6", method = RequestMethod.GET)
public void Save6(HttpServletResponse response) throws IOException {
response.getWriter().println("hello zy");
}
② 将需要回写的字符串直接返回,但此时需要通过@ResponseBody
注解告知SpringMVC框架,方法返回的字符串不是跳转是直接http响应体中返回
@RequestMapping(value = "/quick7", method = RequestMethod.GET)
@ResponseBody
public String Save7() throws IOException {
return "zy";
}
返回json格式数据
导入json包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.13.5</version>
</dependency>
实现
@RequestMapping(value = "/quick8", method = RequestMethod.GET)
@ResponseBody
public String Save8() throws IOException {
User user = new User();
user.setUsername("zy");
user.setAge(30);
ObjectMapper objectMapper = new ObjectMapper();
String Json = objectMapper.writeValueAsString(user);
return Json;
}
返回对象和集合
在spring-mvc.xml中配置处理器映射器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
然后就能直接返回对象,返回的数据为json格式
@RequestMapping(value = "/quick9", method = RequestMethod.GET)
@ResponseBody
public User Save9() throws IOException {
User user = new User();
user.setUsername("zy");
user.setAge(30);
return user;
}
或者在spring-mvc.xml使用mvc注解驱动
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
<mvc:annotation-driven/>
SpringMVC获取请求数据
1.获得请求参数
客户端请求参数的格式是:name=value&name=value。。。
SpringMVC可以接收如下类型的参数:
- 基本类型参数
- POJO类型参数
- 数组类型参数
- 集合类型参数
2.获得基本类型参数
Controller中的业务方法的参数名称要与请求参数的name一直,参数值会自动映射匹配
http://localhost:8080/zy_spring_mvc_war_exploded/quick10?username=zy&age=18
@RequestMapping(value = "/quick10", method = RequestMethod.GET)
@ResponseBody
public void Save10(String username,int age) throws IOException {
System.out.println(username);
System.out.println(age);
}
3.获取POJO类型参数
Controller中的业务方法的POJO参数的属性名要与请求参数的name一致,参数值会自动映射匹配
http://localhost:8080/zy_spring_mvc_war_exploded/quick11?username=zy&age=18
@RequestMapping(value = "/quick11", method = RequestMethod.GET)
@ResponseBody
public void Save11(User user) throws IOException {
System.out.println(user);
}
4.获取数组类型参数
http://localhost:8080/zy_spring_mvc_war_exploded/quick12?strs=aaa&strs=bbb
@RequestMapping(value = "/quick12", method = RequestMethod.GET)
@ResponseBody
public void Save12(String[] strs) throws IOException {
System.out.println(Arrays.asList(strs));
}
5.获得集合类型参数
[
{
"username":"zy",
"age":18
},
{
"username":"zz",
"age":18
}
]
@RequestMapping(value = "/quick13", method = RequestMethod.POST)
@ResponseBody
public void Save13(@RequestBody List<User> userList) throws IOException {
System.out.println(userList);
}
6.请求数据乱码问题
在idea中添加
-Dfile.encoding=UTF-8
在web.xml中配置
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
7.参数绑定注解@RequestParam
当请求的参数名称与Contoller的业务方法参数名称不一致时,就需要通过@RequestParam注解显示绑定
http://localhost:8080/zy_spring_mvc_war_exploded/quick14?name=张杨
@RequestMapping(value = "/quick14", method = RequestMethod.GET)
@ResponseBody
public void Save14(@RequestParam("name") String username) throws IOException {
System.out.println(username);
}
注解@RequestParam参数
value:与请求参数名称一样
required:指定请求参数是否必须,默认为true
defalutValue:当没有指定请求参数时,则使用指定的默认值赋值
8.获得Restful风格参数(@PathVariable)
http://localhost:8080/zy_spring_mvc_war_exploded/quick15/张杨
@RequestMapping(value = "/quick15/{username}", method = RequestMethod.GET)
@ResponseBody
public void Save15(@PathVariable("username") String username) throws IOException {
System.out.println(username);
}
9.自定义类型转换器
- SpringMVC默认已经提供了一些常用的类型转换器,例如客户端提交的字符转换成int类型进行参数设置。
- 但是不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自己定义转换器。
自定义类型转换器的开发步骤
①定义转换器类实现Converter接口
创建com.converter包和DataConverter类,基础Converter<String, Date>
接口
public class DataConverter implements Converter<String, Date> {
@Override
public Date convert(String dateStr) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
②在spring-mvc配置文件中声明转换器
<bean id="ConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.zy.converter.DataConverter"></bean>
</list>
</property>
</bean>
③在
<mvc:annotation-driven conversion-service="ConversionService"/>
10.获得Servlet相关API
SpringMVC支持使用原始ServletApi对象作为控制器方法参数进行注入,常用对象如下:
- HttpServletRequest
- HttpServletResponse
- HttpSession
@RequestMapping(value = "/quick17", method = RequestMethod.GET)
@ResponseBody
public void Save17(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession) throws IOException {
System.out.println(request);
System.out.println(response);
System.out.println(httpSession);
}
11.获取请求头
1.@RequestHeader
使用@RequestHeader可以获得请求头信息,相当于web阶段学习的request.getHeader(name)
@RequestHeader注解属性如下
- value:请求头的名称
- required:是否必须携带请求头
@RequestMapping(value = "/quick18", method = RequestMethod.GET)
@ResponseBody
public void Save18(@RequestHeader(value = "User-Agent",required = false) String user_Agent) throws IOException {
System.out.println(user_Agent);
}
2.@CookieValue
使用@CookieValue可以获得指定Cookie的值
@CookieValue注解的属性如下:
- value:指定cookie的名称
- required:是否必须携带此cookie
@RequestMapping(value = "/quick19", method = RequestMethod.GET)
@ResponseBody
public void Save19(@CookieValue(value = "JSESSIONID",required = false) String jessionId) throws IOException {
System.out.println(jessionId);
}
12.单文件上传步骤
①导入fileupload和io坐标(pom.xml)
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
②在spring-mvc.xml中配置文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxUploadSize" value="50000"/>
</bean>
③编写文件上传代码
<form action="/quick20" method="post" enctype="multipart/form-data">
名称:<input type="text" name="username"/><br/>
文件:<input type="file" name="upload"/><br/>
<input type="submit" value="提交"/>
</form>
@RequestMapping(value = "/quick20", method = RequestMethod.POST)
@ResponseBody
public void Save20(String username, MultipartFile upload) throws IOException {
System.out.println(username);
String originalFilename = upload.getOriginalFilename();
upload.transferTo(new File("D:\\Spring入门开发\\"+originalFilename));
}
13.多文件上传实现
SpringMVC静态资源访问的开启
在sping-mvc.xml中添加
<mvc:resources mapping="/路径/**" location="/路径/"/>
或者
<mvc:defalut-servlet-handler/>
SpringMVC拦截器
1.1拦截器(interceptor)的作用
SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链成为拦截器链(Interceptor Chain),在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用,拦截器也是AOP思想的具体实现。
1.2拦截器和过滤器的区别
区别 | 过滤器(Filter) | 拦截器(Interceptor) |
---|---|---|
使用范围 | 是servlet规范中的一部分,任何Java Web工程都可以使用 | 是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用 |
拦截范围 | 在url-pattern中配置了/*之后,可以对所有要访问的资源拦截 | 在<mvc:mapping path=/>中配置了/**之后,也可以对所有资源进行拦截,但是可以通过<mvc:exclude-mapping path=/>标签排除不需要拦截的资源 |
1.3 拦截器快速入门
三步:
① 创建拦截器类实现HandlerInterceptor接口
在com.名字.interceptor包中创建Myinterceptor类
public class Myinterceptorone implements HandlerInterceptor {
//在目标方法执行之前执行
public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
//如果为false ,后面的方法都不会执行
return true/false;
}
//在目标方法执行之后 视图返回之前执行
public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
//在流程都执行完毕后 执行
public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
String param = request.getParameter("param");
if("yes".equals(param)){
return true;
}else {
request.getRequestDispatcher("/error.jsp").forward(request,response);
return false;
}
}
//在目标方法执行之后 视图返回之前执行
public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
modelAndView.addObject("name","zzzzzzz");
System.out.println("postHandle");
}
② 在spring-mvc.xml配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<!--对哪些资源执行拦截操作-->
<mvc:mapping path="/**"/>
<bean class="com.zy.interceptor.Myinterceptorone"/>
</mvc:interceptor>
</mvc:interceptors>
③ 测试拦截器的拦截效果
@Controller
public class TargetController {
@RequestMapping("/target")
public ModelAndView show(){
System.out.println("目标资源执行。。。");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("name","zy");
modelAndView.setViewName("index");
return modelAndView;
}
}
1.4拦截器方法说明
方法名 | 说明 |
---|---|
preHandler() | 方法将在请求处理之前进行调用,该方法的返回值是布尔值Boolean类型的,当它返回为false时,表示请求结束,后续的Interceptor和Controller都不会在执行;当返回值为true时就会继续调用下一个Interceptor的preHandler方法。 |
postHandle() | 该方法是在当前请求进行处理之后被调用,前提是preHandler方法的返回值为true是才能被调用,且它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行操作。 |
afterCompletion() | 该方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行,前提是preHandler方法的返回值为true时才能被调用 |
1.5案例-用户登录权限控制
需求:用户没有登录的情况下,不能对后台菜单进行访问操作,点击菜单跳转到登录页面,只有用户登录成功后才能进行后台功能操作。
SpringMVC异常处理
1.1异常处理思路
系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发送。
系统的Dao、Service、Controller出现都通过throws Exception向上抛出,最后有SpringMVC前端控制器交由异常处理器进行异常处理
1.2异常处理的两种方式
- 使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver
- 实现Spring的异常处理接口HanlderExptionResolver自定义自己的异常处理器
简单异常处理器SimpleMappingExceptionResolver
<!--2、配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--配置异常处理器-->
<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>
<entry key="com.itheima.exception.MyException" value="error2"></entry>
</map>
</property>
</bean>
自定义异常处理步骤
①创建异常处理器类实现HandlerExceptionResolver
在com.名字下创建一个resolver包,在包内创建MyExceptionResolver
类,实现HandlerExceptionResolver
接口
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView = new ModelAndView();
if(e instanceof MyException){
modelAndView.addObject("info","自定义异常");
}else if(e instanceof ClassCastException){
modelAndView.addObject("info","类转换异常");
}
modelAndView.setViewName("error");
return modelAndView;
}
/*
参数Exception:异常对象
返回值ModelAndView:跳转到错误视图信息
*/
}
②在spring-mvc.xml配置异常处理器
<bean class="com.名字.resolver.MyExceptionResolver"></bean>
③编写异常页面
<body>
<h1>通用的错误提示页面</h1>
<h1>${info}</h1>
</body>
④测试异常跳转
1.3知识要点
异常处理方式
- 简单异常处理器SimpleMappingExceptionResolver
- 自定义异常处理器
自定义异常处理步骤
①创建异常处理器类实现HandlerExceptionResolver
②在spring-mvc.xml配置异常处理器
③编写异常页面
④测试异常跳转