一:响应数据
1. 字符串:controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
2.无返回值:可以通过resquest转向页面 和 response页面重定向和response指定响应结果
3.视图:modelAndView是SpringMVC为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
4.转发和重定向
5.异步请求
依旧先上结构图
1. 导入jar包
<artifactId>spring-context</artifactId>
<artifactId>spring-web</artifactId>
<artifactId>spring-webmvc</artifactId>
<artifactId>servlet-api</artifactId>
//下面三个是用作异步处理的
<artifactId>jackson-databind</artifactId>
<artifactId>jackson-core</artifactId>
<artifactId>jackson-annotations</artifactId>
- 实体类 user
private String username;
private String password;
private Integer money;
- 控制器
@Controller
@RequestMapping("demo01")
public class demo01response {
@RequestMapping("/testVoid")
public String testVoid(Model model){
user user = new user();
user.setUsername("张三");
user.setPassword("123");
user.setMoney(100);
model.addAttribute("user",user);
return "success";
}
@RequestMapping("/testReturnVoid")
public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("测试无返回值");
//1、使用 request 转向页面
//request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
//2、也可以通过 response 指定响应结果
response.sendRedirect("testVoid");
//3、也可以通过 response 指定响应结果
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json 串");
return ;
}
@RequestMapping("/testReturnModelAndView")
public ModelAndView testReturnModelAndView() {
//ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("one","张三");
/*我们在页面上上获取使用的是 requestScope.one取的,所以返回 ModelAndView 类型时,浏
览器跳转只能是请求转发。*/
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping("/testForward")
public String testForward() {
System.out.println("测试转发");;
/*需要注意的是,如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图。
它相当于“request.getRequestDispatcher("url").forward(request,response)”。使用请求
转发,既可以转发到 jsp,也可以转发到其他的控制器方法。
*/
return "forward:/WEB-INF/pages/success.jsp";
}
@RequestMapping("/testRedirect")
public String testRedirect() {
System.out.println("测试转发");
/*它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不
能写在 WEB-INF 目录中,否则无法找到。*/
return "redirect:testReturnModelAndView";
}
/**
* 获取请求体的数据,异步请求
*/
@RequestMapping("/testJson")
public @ResponseBody user testJson(@RequestBody user user){
System.out.println(user);
user.setUsername("bb");
return user;
}
}
- 配置SpringMVC.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置创建 spring 容器要扫描的包 -->
<context:component-scan base-package="lml.demo01"></context:component-scan>
<!-- 配置视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--文件所在的目录-->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!--文件的后缀名-->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 设置静态资源不过滤 -->
<mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
<mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
<!--开启注解springMVC的支持-->
<mvc:annotation-driven />
</beans>
- 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置初始化参数,用于读取springmvc的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<!--配置servlet 的对象的创建时间点,应用加载时创建,取值只能时非0正整数,表示启动顺序-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有的都要拦截-->
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--解决乱码问题-->
<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>
<!-- 启动过滤器 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
- 前端
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>lml</title>
<script src="js/jquery.min.js"></script>
<script>
$(function(){
//绑定点击事件
$("#bt1").click(function () {
$.ajax({
url:"demo01/testJson",
contentType:"application/json;charset=UTF-8",
data:'{"username":"aa","password":"123","money":"100"}',
type:"post",
success:function (data) {
alert(data);
alert(data.username)
}
})
})
}
)
</script>
</head>
<body>
<a href="demo01/testVoid">测试</a>
<a href="demo01/testReturnVoid">测试无返回值</a>
<br/>
<a href="demo01/testReturnModelAndView">测试模型视图</a>
<br/>
<a href="demo01/testForward">测试转发</a>
<a href="demo01/testRedirect">测试重定向</a>
<br/>
<button id="bt1">测试响应json,发送json请求</button>
</body>
</html>
- 此外 需要导入
jquery.min.js 文件
- 跳转成功的页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>成功了</h4>
${user}
${user.username}
${user.password}
<br/>
测试modelAndView ${requestScope.one}
</body>
</html>
二:文件上传
1. 文件上传的必要前提
a. form表单的enctype(是表单请求正文的类型)取值必须是multipart/form-data。
b. method属性值必须是Post
2.文件上传原理的分析
当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。
enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:
key=value&key=value&key=value
当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成:
每一部分都是 MIME 类型描述的正文
3.代码实现
依旧上结构图
跟上面的项目相比
不变的是:跳转成功的jsp页面、实体类user,web.xml
变的是:
控制器:
@Controller
@RequestMapping("demo01")
public class demo01response {
/**
* 传统文件上传的方式
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/fileLoad1")
public String fileLoad1(HttpServletRequest request) throws Exception {
//先获取到要上传得文件目录
String path = request.getSession().getServletContext().getRealPath("/upLoad");
//创建file对象,一会向该路径下上传文件
File file = new File(path);
System.out.println(path);
//判断路径是否存在,如果不存在,创建该路径
if (!file.exists()){
file.mkdirs();
}
//创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//解析request对象
List<FileItem> list = fileUpload.parseRequest(request);
//遍历
for (FileItem fileItem : list) {
//判断文件项,还是上传得文件
if (fileItem.isFormField()){
}else {
//获取到上传文件得名称
String name = fileItem.getName();
//上传文件
fileItem.write(new File(file,name));
//删除临时文件
fileItem.delete();
}
}
return "success";
}
/**
* springMVC传统方式文件上传
* @param request
* @param upload
* @return
* @throws Exception
*/
@RequestMapping("/fileLoad2")
public String fileLoad2(HttpServletRequest request, MultipartFile upload) throws Exception {
//先获取到要上传得文件目录
String path = request.getSession().getServletContext().getRealPath("/upLoad");
//创建file对象,一会向该路径下上传文件
File file = new File(path);
//判断路径是否存在,如果不存在,创建该路径
if (!file.exists()){
file.mkdirs();
}
//获取到上传文件的名称
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
filename= uuid+"_"+filename;
//上传文件
upload.transferTo(new File(file,filename));
return "success";
}
}
springMVC.xml
添加了配置文件解析器对象,要求id名称必须是multipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"></property>
</bean>
前端页面
<%--
Created by IntelliJ IDEA.
User: ASUS
Date: 2021/5/3
Time: 18:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="demo01/fileLoad1" method="post" enctype="multipart/form-data">
选择文件 <input type="file" name="upload"><br/>
<input type="submit" value="提交">
</form>
<form action="demo01/fileLoad2" method="post" enctype="multipart/form-data">
选择文件 <input type="file" name="upload"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
pom文件 因为需要文件流
<artifactId>commons-io</artifactId>
<artifactId>commons-fileupload</artifactId>
ps:还有跨服务器实现文件上传
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。
三:异常处理
1. 流程
客户端请求->springmvc DispatcherServlet-controller-Service-dao异常抛出
-Service-controller-springmvc DispatcherServlet-HandlerExceptionResolver(异常处理器)
Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进
行异常的处理。
2. 代码实现
2.0 pom.xml web.xml 文件与第一份的一样
2.1 前端页面
<a href="demo01/testException" >异常处理</a>
2.2 控制器
@Controller
@RequestMapping("demo01")
public class contro {
@RequestMapping("/testException")
public String testException() throws SysException {
System.out.println("testException执行了...");
try {
// 模拟异常
int a = 11/0;
} catch (Exception e) {
// 打印异常信息
e.printStackTrace();
// 抛出自定义异常信息
throw new SysException("查询所有用户出现错误了...");
}
return "success";
}
}
public class SysException extends Exception {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
public class SysExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//获取到异常对象
SysException s=null;
if (e instanceof SysException){
s = (SysException) e;
}else {
e=new SysException("系统正在维护");
}
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}
}
2.3 springMVC.xml
<!-- 配置创建 spring 容器要扫描的包 -->
<context:component-scan base-package="lml"></context:component-scan>
<!-- 配置视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--文件所在的目录-->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!--文件的后缀名-->
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="lml.SysExceptionResolver"/>
<mvc:annotation-driven />
<!--开启注解springMVC的支持-->
2.4 错误页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${errorMsg}
</body>
</html>
四:拦截器
1. 基础知识:SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
2.拦截器和过滤器的区别
2.1 过滤器是servlet规范中的一部分,任何java web都可以使用
过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截
2.2 拦截器是springMVC框架,只有使用了springMVC框架才可以使用
拦截器只会拦截访问的控制器方法,如果访问的是jsp,html,js…是不会拦截的。
想要自定义拦截器,需要实现HandlerInterceptor接口。
3. 代码简单的实现
3.0 pom.xml 、web.xml 、success、error一样
3.1 前端
<a href="demo01/testInterceptor" >异常处理</a>
3.2 控制器
@Controller
@RequestMapping("/demo01")
public class demo01 {
@RequestMapping("/testInterceptor")
public String testInterceptor(){
System.out.println("运行成功");
return "success";
}
}
public class HandlerInterceptorDemo1 implements HandlerInterceptor {
/**
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法,controller方法执行后,success.jsp执行之前
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了...后1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp页面执行后,该方法会执行
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1执行了...最后1111");
}
}
3.3 SpringMVC.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置创建 spring 容器要扫描的包 -->
<context:component-scan base-package="lml"></context:component-scan>
<!-- 配置视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--文件所在的目录-->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!--文件的后缀名-->
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/demo01/*"/><!-- 用于指定对拦截的 url -->
<bean class="lml.interceptoe.HandlerInterceptorDemo1"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!--开启注解springMVC的支持-->
<mvc:annotation-driven />
</beans>
注:
- preHandle方法是controller方法执行前拦截的方法
- 可以使用request或者response跳转到指定的页面
- return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
- return false不放行,不会执行controller中的方法。
- postHandle是controller方法执行后执行的方法,在JSP视图执行前。
- 可以使用request或者response跳转到指定的页面
- 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
- postHandle方法是在JSP执行后执行
- request或者response不能再跳转页面了
对了 创建maven文件时
添加 archetypeCatalog - internal