笔记参考:黑马程序员相关课程
目录
1、Spring MVC概述
1.1、三层架构和MVC
1.2、Spring MVC概述
Spring MVC是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架,属于Spring FrameWork的后续产品,已经融合在Spring Web Flow里面。
Spring MVC的优势:
- 清晰的角色划分
- 分工明确,拓展点相当灵活,可以很容易拓展。
Spring MVC和Structs2的区别:
- 共同点
- 都是表现层架构,都是基于MVC模型编写的
- 底层都离不开ServletAPI
- 处理请求的机制都是一个核心控制器
- 区别
- Spring MVC的入口是Servlet,Structs2是Filter
- Spring MVC是基于方法设计的,而Structs2是基于类,structs2每次执行动作都会创建一个动作类。所以Spring MVC会比Structs2快一些
- Spring MVC更简洁,同时还支持JSR303,处理ajax的请求更方便
1.3、SpringMVC的入门
1、创建java的web工程(使用骨架)
2、导入依赖的坐标
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
3、在web.xml配置文件中核心控制器DispatcherServle
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- SpringMVC的核心控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 配置servlet启动时加载对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4、在main-resources中编写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在创建ioc容器时要扫描的包-->
<context:component-scan base-package="controller"></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>
<!--开启springmvc注解的支持-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
5、编写index.jsp和HelloController控制器类
index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>入门程序</title>
</head>
<body>
<h3>入门程序</h3>
<a href="hello">入门程序</a>
</body>
</html>
在main-java-controller中创建HelloController:
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 控制器类
*/
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String sayHello(){
System.out.println("Helllo SpringMVC");
return "success";
}
}
6、在WEB-INF目录下创建pages文件夹,编写success.jsp的成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
</head>
<body>
<h3>入门成功!</h3>
</body>
</html>
7、启动Tomcat服务器进行测试
步骤总结:
1.4、一些小细节
@RequestMapping注解的作用:用于建立请求URL和处理请求方法之间的对应关系
- value属性:用于指定请求的URL。和path属性的作用是一样的。
- method:用于指定请求的方法。例如:method={RequestMethod.POST}
- params:用于指定限制请求的参数的条件。他支持简单的表达式,要求请求参数的key和value必须和配置一模一样。例如:params={“accountName”}表示请求参数必须有accountName,params={money!100},表示请求参数中money不能是100
- headers:用于指定限制请求消息头的条件。发送的请求中必须包含的请求头。
2、请求参数的绑定(拿到请求参数)
1、 请求参数的绑定说明
- 绑定机制
- 表单提交的数据都是k=v格式的 username=haha&password=123
- SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
- 要求:提交表单的name和参数的名称是相同的
- 支持的数据类型
- 基本数据类型和字符串类型
- 实体类型(JavaBean)
- 集合数据类型(List、map集合等)
基本数据类型和字符串类型:
<a href="hello?username=hehe">入门程序</a>
HelloController:
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String sayHello(String username){
System.out.println("Helllo SpringMVC"+username);
return "success";
}
}
请求参数绑定实体类型:
1、在main-domain中写要封装的javaBean:Account
<%--把数据封装到Account类中--%>
<form action="saveAccount" method="post">
姓名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"><br>
金额:<input type="text" name="money"><br>
<%--Account类中有User作为成员变量--%>
用户姓名:<input type="text" name="user.uname"><br>
用户年龄:<input type="text" name="user.age"><br>
<input type="submit" value="提交">
</form>
HelloController:
@RequestMapping("/saveAccount")
public String saveAccount(Account account){
System.out.println(account);
System.out.println("成功保存了用户..");
return "success";
}
解决post请求中文乱码问题:在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>
请求参数绑定集合类型:
<%--把数据封装到Account类中,类中存在list和map集合--%>
<form action="saveAccount" method="post">
姓名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"><br>
金额:<input type="text" name="money"><br>
用户姓名:<input type="text" name="list[0].uname">
用户年龄:<input type="text" name="list[0].age">
用户姓名:<input type="text" name="map['one'].uname">
用户年龄:<input type="text" name="map['one'].age">
<input type="submit" value="提交">
</form>
2.1、自定义类型转换器
提出问题:页面提交的参数都是string类型的,但是像是Integer类型的数据也成功封装了,说明springMVC可以帮我们自动类型转化。但是,如果是日期类型怎么办呢,这个时候就需要我们自定义类型转换器了。
1、在main-java-utils下定义类型转换器StringToDateConverter:
package utils;
import org.springframework.core.convert.converter.Converter;
import java.text.SimpleDateFormat;
import java.util.Date;
//字符串到日期的转换器
public class StringToDateConverter implements Converter<String, Date> {
/**
* @param source 传入进来的字符串
* @return
*/
@Override
public Date convert(String source) {
if(source==null){
throw new RuntimeException("请您传入数据...");
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.parse(source);
} catch (Exception e) {
throw new RuntimeException("数据类型转换出现错误!");
}
}
}
2、在main-resources-springmvc.xml中配置自定义类型转换器:
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<!--把自定义的类型转换器注册进来-->
<property name="converters">
<set>
<bean class="utils.StringToDateConverter"></bean>
</set>
</property>
</bean>
<!--开启springmvc注解的支持-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
2.2、获取Servlet原生的API
<a href="testServlet">获取Servlet原生的API</a>
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response){
System.out.println("获取Servlet原生的API");
System.out.println(request);
System.out.println(request.getSession());
System.out.println(request.getSession().getServletContext());
System.out.println(response);
return "success";
}
3、SpringMVC常用注解
3.1、RequestParam注解
作用:把请求中指定名称的参数给控制器中的形参赋值。
<a href="testRequestParam?uname=哈哈">testRequestParam</a>
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(name = "uname") String username){
System.out.println("testRequestParam。。。");
System.out.println(username);
return "success";
}
3.2、RequestBody注解
作用:用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。get 请求方式不适用。
<form action="testRequestBody" method="post">
姓名:<input type="text" name="uname">
年龄:<input type="text" name="age">
<input type="submit" value="提交">
</form>
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String body){
System.out.println("testRequestParam。。。");
System.out.println(body);
return "success";
}
3.3、PathVariable注解
作用:用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。
属性:
- value:用于指定 url 中占位符名称。
- required:是否必须提供占位符。
<a href="testPathVariable/10">PathVariable注解</a><br>
@RequestMapping("/testPathVariable/{sid}")
public String testPathVariable(@PathVariable(name = "sid") String id){
System.out.println("testPathVariable...");
System.out.println(id);
return "success";
}
3.4、RequestHeader注解
作用:用于获取请求消息头。
属性:
- value:提供消息头名称
- required:是否必须有此消息头
<a href="testRequestHeader">RequestHeader注解</a><br>
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept") String header){
System.out.println("testRequestHeader...");
System.out.println(header);
return "success";
}
3.5 CookieValue注解
作用:用于把指定 cookie 名称的值传入控制器方法参数。
属性:
- value:指定 cookie 的名称。
- required:是否必须有此 cookie。
<a href="testCookieValue">CookieValue注解</a><br>
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue(value = "JSESSIONID") String cookieValue){
System.out.println("testRequestHeader...");
System.out.println(cookieValue);
return "success";
}
3.6、ModelAttribute注解
作用:它可以用于修饰方法和参数。
- 出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
- 出现在参数上,获取指定的数据给参数赋值。
属性:value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。
有返回值:
<form action="testModelAttribute" method="post">
姓名:<input type="text" name="uname">
年龄:<input type="text" name="age">
<input type="submit" value="提交">
</form>
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){
System.out.println("testModelAttribute执行了..");
System.out.println(user);
return "success";
}
@ModelAttribute
public User showUser(String uname){
System.out.println("showUser方法执行了..");
//通过用户名查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(20);
user.setBirthday(new Date());
return user;
}
没有返回值:
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("one") User user){
System.out.println("testModelAttribute执行了..");
System.out.println(user);
return "success";
}
@ModelAttribute
public void showUser(String uname, Map<String,User> map){
System.out.println("showUser方法执行了..");
//通过用户名查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(20);
user.setBirthday(new Date());
map.put("one",user);
}
3.7、SessionAttributes注解
作用:用于多次执行控制器方法间的参数共享。
属性:
- value:用于指定存入的属性名称
- type:用于指定存入的数据类型。
index.jsp:
<a href="testSessionAttributes">SessionAttributes注解</a><br>
<a href="getSessionAttributes">getSessionAttributes</a><br>
<a href="deleteSessionAttributes">deleteSessionAttributes</a><br>
HelloController:
@Controller
@SessionAttributes(value = "msg") //将msg=hello存到session域中
public class HelloController {
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Model model){
System.out.println("testSessionAttributes执行了..");
model.addAttribute("msg","hello"); //将msg=hello存到request域对象中
return "success";
}
//从session域中获取值
@RequestMapping("/getSessionAttributes")
public String getSessionAttributes(ModelMap model){
System.out.println("testSessionAttributes执行了..");
String msg=(String)model.get("mag");
System.out.println(msg);
return "success";
}
//从session域中删除
@RequestMapping("/deleteSessionAttributes")
public String deleteSessionAttributes(SessionStatus status){
System.out.println("testSessionAttributes执行了..");
status.setComplete();
return "success";
}
}
success.jsp:
${requestScope.msg}
${sessionScope}
4、SpringMVC返回值类型及响应数据类型
4.1、响应之返回值是String类型
index.jsp:
<a href="testString">返回字符串</a><br>
@Controller
public class ResponseController {
@RequestMapping("testString")
public String testString(Model model){
System.out.println("testString...");
//模拟从数据库中查询出user对象
User user = new User();
user.setName("Julia");
user.setAge(22);
//model对象
model.addAttribute("user",user);
return "success";
}
}
success.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>success</title>
</head>
<body>
<h3>成功了...</h3>
${user.name}
${user.age}
${user.toString()}
</body>
</html>
4.2、响应之返回值是void类型
<a href="testVoid">testVoid</a><br>
@RequestMapping("testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("testVoid...");
//编写请求转发程序.请求转发是一次请求,不用写项目的名称
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
//重定向,是两次请求
response.sendRedirect(request.getContextPath()+"/response.jsp");
//设置中文乱码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//直接响应
response.getWriter().print("哈哈");
return;
}
4.3、响应之返回值是ModelAndView类型
ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图。
<a href="testModelAndView">testModelAndView</a><br>
@RequestMapping("testModelAndView")
public ModelAndView testModelAndView(){
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView...");
//模拟从数据库中查询出user对象
User user = new User();
user.setName("Julia");
user.setAge(22);
//将user对象存储到mv对象中,也会把user对象存到request域中
mv.addObject("user",user);
//跳转到哪个页面
mv.setViewName("success");
return mv;//用视图解析器
}
<h3>成功了...</h3>
${user.name}
${user.age}
${user.toString()}
4.4、响应之使用forward和redirect关键字进行页面跳转
<a href="testForwardOrRedirect">testForwardOrRedirect</a><br>
@RequestMapping("testForwardOrRedirect")
public String testForwardOrRedirect(){
System.out.println("testForwardOrRedirect...");
//请求转发
return "forward:/WEB-INF/pages/success.jsp"; //因为使用了forward关键字就不会使用视图解析器
//重定向
return "redirect:/response.jsp";
}
4.5、发送异步请求和响应json数据
1、前期准备:告诉前端控制器哪些资源不拦截(设置静态资源不过滤)、导入坐标,使json字符串和javaBean对象自动转换
在main-resources-springmvc.xml中配置:
<!--告诉前端控制器哪些资源不拦截-->
<!-- 设置静态资源不过滤 -->
<mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
<mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.2</version>
</dependency>
2、发送异步请求以及相应
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>index</title>
<script src="js/jquery-3.3.1.min.js"></script> <%--引入jquery,搭建异步请求环境--%>
<script>
//页面加载,绑定点击事件
$(function () {
$("#btn").click(function () {
/*发送ajax请求*/
$.ajax({
/*编写json格式,设置属性和值*/
url:"testAjax", /*请求的url*/
contentType:"application/json;charset=UTF-8", /*告诉服务器发送的数据类型*/
data:'{"name":"julia","age":"22"}', /*里面也是json的格式*/
dataType:"json", /*告诉服务器响应的数据类型*/
type:"psot", /*请求方式*/
success:function (data) {
//data是服务器端响应的json数据,我们可以对数据进行解析
alert(data);
alert(data.name);
alert(data.age);
} /*请求成功后的回调函数*/
});
});
});
</script>
</head>
<body>
<button id="btn">发送ajax请求</button>
</body>
</html>
/**
* 模拟异步请求和响应
*/
@RequestMapping("testAjax")
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("testAjax...");
//客户端发送ajax请求,传的是json字符串,后端把json字符串封装到User对象中
System.out.println(user);
//响应,模拟查询数据库
user.setAge(23);
//做响应
return user;
}
5、文件上传
5.1、文件上传之传统方式上传
1、导入坐标
<!--文件上传坐标-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
2、文件上传
<h2>文件上传</h2>
<form action="fileUpload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
@RequestMapping("/fileUpload1")
public String fileUpload1(HttpServletRequest request) throws Exception {
System.out.println("文件上传...");
//使用fileupload组件完成文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断该路径是否存在
File file = new File(path);
if(!file.exists()){
//创建该文件夹
file.mkdirs();
}
//解析request对象,获取到的文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> items = upload.parseRequest(request);
//遍历
for (FileItem item : items) {
//判断item是否是上传文件项
if(item.isFormField()){
//普通表单项
}else {
//上传的文件项
//获取上传文件的名称
String filename = item.getName();
//把文件的名称设置为唯一值
filename=filename+"_"+ UUID.randomUUID().toString().replace("-","");
//文件上传
item.write(new File(path,filename));
//删除临时文件
item.delete();
}
}
return "success";
}
5.2、文件上传之Springmvc方式
原理分析:
1、前期工作:在main-resources-springmvc.xml中配置文件解析器:可以将文件项封装起来
<!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"/> <!--配置上传文件的大小-->
</bean>
2、文件上传:
<h2>springmvc文件上传</h2>
<form action="fileUpload2" method="post" enctype="multipart/form-data">
选择文件: <input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
@RequestMapping("/fileUpload2")
public String fileUpload2(HttpServletRequest request,MultipartFile upload) throws Exception {
System.out.println("fileUpload2...");
//上传位置
String path = request.getSession().getServletContext().getRealPath("/upload/");
//判断该路径是否存在
File file = new File(path);
if(!file.exists()){
//创建该文件夹
file.mkdirs();
}
//获取上传文件的名字
String filename = upload.getOriginalFilename();
//把文件名变成唯一值
filename=filename+"_"+UUID.randomUUID().toString().replace("-","");
//上传文件
upload.transferTo(new File(path,filename));
return "success";
}
5.3、文件上传之跨服务器
分服务器的目的:
在实际开发中,我们会有很多处理不同功能的服务器。例如:
- 应用服务器:负责部署我们的应用
- 数据库服务器:运行我们的数据库
- 缓存和消息服务器:负责处理大并发访问的缓存和消息
- 文件服务器:负责存储用户上传文件的服务器。
1、搭建环境:模拟创建一个图片服务器fileuploadServer
2、在fileuploadServer服务器中main-wbeapp下创建uploads文件夹用于存储上传的文件
3、在springmvc服务器中的pom.xml导入跨服务器文件上传的坐标
<!-- 跨服务器上传 -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.19.4</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.19.4</version>
</dependency>
4、index.xml
<h2>跨服务器文件上传</h2>
<form action="fileUpload3" method="post" enctype="multipart/form-data">
选择文件: <input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
5、ResponseController:
@RequestMapping("/fileUpload3")
public String fileUpload3(MultipartFile upload) throws Exception {
System.out.println("fileUpload3...");
//定义上传文件服务器路径
String path="http://localhost:9090/fileuploadServer/uploads/";
//获取上传文件的名字
String filename = upload.getOriginalFilename();
//把文件名变成唯一值
filename=filename+"_"+UUID.randomUUID().toString().replace("-","");
//完成跨服务器上传
//创建客户端对象
Client client = Client.create();
//和图片服务器进行连接
WebResource webResource = client.resource(path + filename);
//上传文件
webResource.put(upload.getBytes());
return "success";
}
结果:文件上传成功:
跨服务器上传文件常见错误:
报错403:找到 Tomcat 目录—conf下—web.xml,加入:
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
报错409
原因:上传图片到图片服务器时,失败,上传到的文件夹没有被创建,需要手动创建
解决办法:找到项目的文件夹,打开存图片服务器项目的文件—target-----项目名下----创建文件夹uploads
6、SpringMVC中的异常处理
步骤:
- 编写自定义异常类(做提示信息的) 在main-java-exception中创建SysException类
package exception;
/**
* 自定义异常类
*/
public class SysException extends Exception {
//存储提示信息
private String message;
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
- 编写异常处理器,在main-java-exception中创建SysExceptionResolver 异常处理器类
package exception;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 异常处理器
*/
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常业务逻辑
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//获取到异常对象
SysException ex=null;
if (e instanceof SysException){
ex=(SysException)e;
}else {
ex=new SysException("系统正在维护...");
}
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",ex.getMessage());
mv.setViewName("error");
return mv;
}
}
- 配置异常处理器(跳转到友好提示页面) 在springmvc.xml中配置
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="exception.SysExceptionResolver"></bean>
- 编写跳转的友好错误页面,在main-webapp-WEB-INF中创建error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>error</title>
</head>
<body>
${errorMsg}
</body>
</html>
7、 SpringMVC拦截器
Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
过滤器和拦截器的区别:
- 过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
- 拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
- 过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
- 拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。
步骤:
- 编写拦截器类,实现 HandlerInterceptor 接口。在main-java-interceptor中创建类。ctrl+o实现接口的方法
package interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义拦截器
*/
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 预处理:controller执行前
* return true表示放行,表示执行下一个拦截器,如果没有就执行controller中的方法
* return false不放行,可以使用req和resp来跳转页面
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("前:拦截器1执行了...");
//也可以使用跳转
//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("后:拦截器1执行了...");
//也可以指定跳转页面
//request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp执行后该方法执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("最后:拦截器1执行了...");
}
}
- 配置拦截器,在main-java-resources-springmvc.xml中配置
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/*"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="interceptor.MyInterceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
- success.jsp
<h3>成功了...</h3>
<% System.out.println("success.jsp....");%>
结果: