目录
简介
springmvc是基于spring Framwork衍生出来的一个mvc框架,主要解决原有mvc架构中,控制器(Controller)的问题,常见的控制器有servlet,struts2等,控制器的核心功能是根据用户的请求调用对应业务功能,然后依据业务处理的结果,控制程序的运行流程。
开发方式
- 传统的开发方式 通过作用域(request,session)实现数据的传递,通过视图技术进行视图的渲染(jsp thymleaf freeMarker)
- 前后端分离开发方式,多种新的访问方式(get 、post 、put、 delete)Restful风格的访问
实现流程
1. 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器); 2. 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。 3. DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器); 4. HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller); 5. Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息); 6. HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ; 7. DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析; 8. ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet; 9. DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图); 10. 视图负责将结果显示到浏览器(客户端)
组件介绍
Spring MVC 涉及到的组件有 DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)、Handler(处理器)、ViewResolver(视图解析器)和 View(视图)。下面对各个组件的功能说明如下。
- DispatcherServlet DispatcherServlet 是前端控制器,从图 1 可以看出,Spring MVC 的所有请求都要经过 DispatcherServlet 来统一分发。DispatcherServlet 相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展。
- HandlerMapping HandlerMapping 是处理器映射器,其作用是根据请求的 URL 路径,通过注解或者 XML 配置,寻找匹配的处理器(Handler)信息。
- HandlerAdapter HandlerAdapter 是处理器适配器,其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)。
- Handler Handler 是处理器,和 Java Servlet 扮演的角色一致。其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至 ModelAndView 对象中。
- View Resolver View Resolver 是视图解析器,其作用是进行解析操作,通过 ModelAndView 对象中的 View 信息将逻辑视图名解析成真正的视图 View(如通过一个 JSP 路径返回一个真正的 JSP 页面)
- View View 是视图,其本身是一个接口,实现类支持不同的 View 类型(JSP、FreeMarker、Excel 等)。 以上组件中,需要开发人员进行开发的是处理器(Handler,常称Controller)和视图(View)。通俗的说,要开发处理该请求的具体代码逻辑,以及最终展示给用户的界面
快速构建
1、创建普通maven工程 2、添加WEB支持(项目右键->Add framework support) 3、导入maven依赖 4、配置tomcat,并在Project Structure的Artifacts的WEB-INF里创建lib导入mavenjar包 5、编写springmvc-config.xml 6、修改web.xml,加入servlet
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.24.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<!--springmvc-config.xml-->
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--注解实现mvc-->
<!-- 自动扫描包,实现支持注解的IOC -->
<context:component-scan base-package="com.xx.springmvc" />
<!-- 支持mvc注解驱动 注册处理器映射器 注册处理器适配器 参数的类型转换 页面跳转 响应处理 -->
<mvc:annotation-driven />
<!-- 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀,返回的页面前缀 -->
<property name="prefix" value="/view/" />
<!-- 后缀,返回的页面后缀-->
<property name="suffix" value=".jsp" />
</bean>
</beans>
<!--配置DispatcherServlet 核心:前端控制器,请求分发器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置DispatcherServlet 绑定Spring的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别 1 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<url-pattern/>的作用:将请求当作一个controller处理,然后dispatchServlet去调用HandleMapping查找到相应的处理器。简单的来说就是匹配到的请求会去寻找controller。
/:匹配根目录下的所有请求,包括静态资源的获取请求,例如:.css
,.js
,.html
等静态资源,但是不会匹配到.jsp这样的后缀的url。
/*:匹配根目录下的所有请求,包括静态资源的获取请求,也包括.jsp
这样的后缀的url。
一些老版本老项目会匹配*.do。,即匹配后缀名是.do的所有请求
参数绑定
客户端请求key/value数据,经过参数绑定,将 key/value数据绑定到controller方法的形参上。 springmvc中,接收页面提交的数据是通过方法形参来接收 ,而不是在controller类定义成员变量接收。
默认支持的类型处理器形参中添加如下类型的参数,处理适配器会默认识别并 进行赋值。
- HttpServletRequest :通过request对象获取请求信息
- HttpServletResponse :通过response处理响应信息
- HttpSession:通过session对象得到session中存放的对象
- Model/ModelMap:ModelMap是Model接口的实现类,将model数据填充到 request域,向页面传递数据
简单数据类型绑定
基本数据类型、String、数组、包装数据类型、JavaBean
方法参数中定义的是基本数据类型,但是从页面提交过来的数据为null或者”"的话,会出现数据转换的异常。在开发过程中,对可能为空的数据,最好将参数数据类型定义成包装类型。
1.客户端参数名字和形参的名字保持一致;如果是Javabean,客户端名字要和属性名保持一致
2.使用@RequestParam,在形参前绑定客户端参数
属性:name ="",value="",defaultValue = ""
复杂数据类型绑定
List、Map、Date、复合类型的对象等
注意:此时客户端传参方式必须是post
步骤:封装Vo类,在Vo类里定义List/Map类型的变量。形参类型为Vo类,客户端参数名要和Vo类的List/Map变量名一致
Date类型要使用转换器
//需要实现Converter接口,这里是将String类型转换成Date类型
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
//实现将字符串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
SimpleDateFormat dateFormat = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss");
try {
return dateFormat.parse(source);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//如果参数绑定失败返回null
return null;
}
}
<!--注册到ConversionServiceFactory-->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters">
<!-- 自定义转换器的类名 -->
<bean class="org.kgc.springmvc.convert.DateConverter"></bean>
</property>
</bean>
<!--注册到注解驱动-->
<mvc:annotation-driven conversion-service="conversionService"/>
复合类型的对象接收:实体类嵌套(一个实体类是另一个的属性)
使用@ResponseBody 嵌套对象
返回数据
ModelAndView:使用ModelAndView来存储数据,SpringMVC会自动把 ModelAndView 对象传递到方法参数上;也可以自己new一个,并且可以直接在构造器中指定视图名称,返回前台的参数默认是放到request域当中。
@RequestMapping(path = "/res")
public ModelAndView test(ModelAndView modelAndView){
modelAndView.setViewName("hello");
modelAndView.addObject("msg", "ModelAndView");
return modelAndView;
}
Model:通过Model返回数据到视图
区别:ModelAndView、Model都可以完成返回数据到视图的任务,但ModelAndView是一个实体类,而Model则是一个接口,Model没有指定视图的功能,也就是不能像ModelAndView那样指定视图名称。虽然Model是个接口,不过我们并不需要去实现Model接口,只需要在方法参数上进行声明,SpringMVC就会自动把Model对象传递过来。
Map:通过Map返回数据到视图,使用Map返回数据与使用Model类似,在方法上声明Map参数,然后添加数据即可。SpringMVC会自动把对象传递进来,返回的数据也是一样会存储到request对象中。
ModelMap:通过ModelMap返回数据到视图,Model 和 ModelMap 的实例都是spirng mvc框架来自动创建并作为控制器方法参数传入,用户无需自己创建。 而且需要return 返回指定的页面路径。 ModelMap继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性。
Map、Model、ModelMap之间本质无太大区别。
跳转方式
Spring MVC默认采用服务器内部转发的形式展示页面信息,同时也支持重定向页面
HttpServletResponse的跳转:response.sendRedirect("redirect.jsp");
springmvc的response跳转:return "redirect:redirect.jsp";
HttpServletRequest跳转:request.getRequestDispatcher("redirect.jsp").forward(request, response);
springmvc的forward跳转:return "forward:redirect.jsp";
默认跳转:return "redirect";
总结
springmvc格式:return:"forward/redirect: /xxx.jsp ";这里的"/"代表根目录,不加会找不到,如果跳转页面不在根目录则需要拼接
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort() + path + "/";
return "redirect:" + basePath + "redirect.jsp";
HttpServletRequest/Response的格式:和Servlet的格式一样
json处理
处理json请求
1、直接使用实体类即可接收,但要在参数前加上@RequestBody注解
2、客户端ajax请求
获取json数据
1.如果数据不多(例如单个属性),可以在参数前用@RequestParam接收
2.如果是json类型的对象、list、map,则需要用@RequestBody 接收
返回json数据
springmvc四种方式处理json响应
1、使用response的输出流输出json字符串
res.setContentType("application/json;charset=utf-8");
String result = "{"+"\"success\":"+"true,"+"\"msg\":"+“request success"+"}";
res.getWriter().write(result);
2、使用@ResponseBody ,return json字符串
方法加上@ResponseBody
String result = "{"+"\"success\":"+"true,"+"\"msg\":"+" request success "+"}";
return result;
3、使用 ResponseEntity 类
@RequestMapping("/login")
public ResponseEntity<Result> login() {
Result result = new Result();
result.setSuccess(true);
result.setMsg(“request success");
return ResponseEntity.ok(result);
}
4、返回对象
导入依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
方法上加入@ResponseBody,结果返回一个对象
json乱码问题
1.@RequestMapping里加上,produces配置,它的作用是指定返回值类型,不但可以设置返回值类型还可以设定返回值的字符编码。
@RequestMapping(value=“/login3”, produces = {"application/json;charset=UTF-8"})
2.配置全局message-converters
<mvc:annotation-driven>
<!-- 转换字符编码,springmvc默认为ISO-8859-1 -->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="#{T(java.nio.charset.Charset).forName('UTF-8')}"/>
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>applicaiton/javascript;charset=UTF-8</value>
</list>
</property>
<property name="writeAcceptCharset"><value>false</value></property>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json; charset=UTF-8</value>
<value>application/x-www-form-urlencoded; charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
静态资源过滤
如果将DispatcherServlet请求映射配置为“/”,则Spring MVC将捕获Web容器所有的请求,包括静态资源的请求,Spring MVC会将它们当成一个普通请求处理,因此找不到对应处理器将导致错误。解决方案如下:
<mvc:default-servlet-handler/>
<mvc:default-servlet-handler default-servlet-name="customServlet"/> 或者使用mvc:resources方式来处理,如下: <mvc:resources mapping="/static/**" location="/static/"/>使用<mvc:resources/>元素把static /**映射到ResourceHttpRequestHandler进行处理,location指定静态资源的位置
RestFul风格
REST:Representational State Transfer,表述层资源状态转移。(表现层:视图+控制器)
如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构风格。 REST本身并没有创造新的技术、组件或服务,简单来说,REST的目的就是设立规定,促使人们更好地使用Http协议。
四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源,PATCH部分更新(很少使用)。控制层 @RequestMapping也相应的换成@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping。
restful风格带参数:
controller里使用@PathVariable 注解映射 URL 绑定的占位符接受参数
@PathVariable和@RequestParam 的区别
@PathVariable是以“/”方式来获取参数值,例:" /path/{param1}/{param2}" 也是RSET风格的springmvc取值,是从一个URI模板里面来填充。
@RequestParam,例:"/path?param1=value1¶m2=value2" 是从request里面拿取值。
@RequestParam和@RequestBody 的区别
@RequestParam是把请求中的指定名称的参数传递给控制器中的形参赋值 ,用来处理Content-Type 为 application/x-www-form-urlencoded 编码的内容;
@RequestBody 接收的参数是来自requestBody中,即请求体。处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交;
浏览器只支持发送get和post方式的请求,必须使用SpringMVC的HiddenHttpMethodFilter将 POST 请求转换为 DELETE 或 PUT 请求。
<!--web.xml中注册-->
<!--必须先注册CharacterEncodingFilter再注册HiddenHttpMethodFilter-->
<!--解决中文乱码-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--注册bean-->
<filter>
<filter-name>Hidden</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Hidden</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--示例,隐藏框里是put方式-->
<form action="rest/patchAction" method="post">
<input type="hidden" name="_method" value="PUT"><br>
姓名:<input type="text" name="username"/>
<input type="submit" value="提交">
</form>
操作session、cookie
session
1.使用HttpSession,在形参中声明HttpSession变量
2.用ModelMap设置Session(注意一定要写,@SessionAttributes注解)
3.将Model中key为msg1, code1的属性共享到session中
cookie
1.new cookie对象, Cookie ck = new Cookie("cookie","cookieValue");
2.参数上使用注解,@CookieValue("cookie")
拦截器
原理
SpringMVC中的Interceptor拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登录等操作。
实现接口: HandlerInterceptor
HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。
preHandle:请求处理之前进行调用,可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中 进行一些判断来决定请求是否要继续进行下去。(最常用)
postHandle:Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用。可以ontroller处理之后的ModelAndView 对象进行操作。
afterHandle:整个请求结束之后执行,主要作用是用于进行资源清理工作的。
多个拦截器执行顺序
preHandle1 -> preHandle2 -> handleRun -> hostHandle2 -> hostHandle1 ->
page.jsp -> afterHandle2 -> afterHandle1。preHandle是顺序,postHandle和afterHandle是逆序
步骤
1.导入Log4J pom依赖
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.16.0</version>
</dependency>
2.编写log4j.properties
3.配置web.xml,加载log4j.properties文件
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value><!-- log4j配置文件路径 -->
</context-param>
4.编写拦截器
import org.apache.log4j.Logger;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LogInterceptor implements HandlerInterceptor {
private static final Logger logger = Logger.getLogger(LogInterceptor.class);
private ThreadLocal<Double> startTimeThreadLocal = new NamedThreadLocal<Double>("StartTime-EndTime");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
double startTime = System.currentTimeMillis();
logger.debug("开始执行时间:" + startTime);
startTimeThreadLocal.set(startTime);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.debug("正在执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
double endTime = System.currentTimeMillis();
logger.debug("结束执行时间:" + endTime);
double startTime = startTimeThreadLocal.get();
logger.debug("总共执行时间:" + (endTime - startTime) / 1000 + "秒");
}
}
5.配置springmvc-config.xml
<mvc:interceptors >
<!—拦截所有控制器请求-->
<!-- <bean class="org.kgc.springmvc.interceptor.LogInterceptor"/>-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!—不需要拦截的路径-->
<mvc:exclude-mapping path="/**/login"/>
<bean class="org.kgc.springmvc.interceptor.LogInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
文件上传
单个文件上传步骤
1.导入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
2.配置解析器
<!-- 文件上传配置文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 允许上传的最大文件 单位字节-->
<property name="maxUploadSize" >
<value>104857600</value>
</property>
<!-- 内存中的最大缓存超出写出临时文件到硬盘-->
<property name="maxInMemorySize" >
<value>4096</value>
</property>
<property name="defaultEncoding">
<value>utf-8</value>
</property>
</bean>
3.编写控制层方法
//获取项目的真实路径
String realPath = request.getSession().getServletContext().getRealPath("/");
System.out.println(realPath);
//创建文件上传的目录
File dir = new File(realPath, "/upload");
System.out.println(dir);
//判定文件夹是否存在 不存在创建
if(!dir.exists()){
dir.mkdir();
}
if(!file.isEmpty()){
//获取文件的名字
String fileName = file.getOriginalFilename();
//截取文件的后缀 生成新的文件名 避免文件名字重复
String suffix= fileName.substring(fileName.lastIndexOf("."));
//获取当前系统时间
String fileLastName = System.currentTimeMillis()+suffix;
System.out.println(fileLastName);
//将文件写入目标文件夹
try {
file.transferTo(new File(dir,fileLastName));
request.setAttribute("msg", "文件上传成功");
} catch (IOException e) {
e.printStackTrace();
request.setAttribute("msg", "文件上传失败");
}
}else{
request.setAttribute("msg", "未选择文件");
}
return "success";
多个文件上传
前端:
<!--使用 multiple属性 实现ctrl多选-->
<form method="post" action="/test/files" enctype="multipart/form-data">
<input type="file" name="files" multiple="multiple">
<input type="submit" value="文件提交">
</form>
后端:使用 @RequestParam("files") List<MultipartFile> files 接收,使用foreach循环处理
文件异步上传
<body>
<div class="content">
<input id="fileupload" type="file" name="file">
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>
<img id="uploadimg" src="__PUBLIC__/images/bg.jpg" width="400px" height="408px"/>
</div>
<script>
$('#fileupload').fileupload({
dataType: 'json',
url: "upload/file2",//文件的后台接受地址
//设置进度条
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100);
$('#progress .bar').css(
'width',
progress + '%'
);
},
//上传完成之后的操作,显示在img里面
done: function (e, data){
$("#uploadimg").attr({src: data.result.pic_url});
$("#uploadimg").css({width: "400px", height: "400px"});
}
});
</script>
</body>
异常统一处理
局部异常处理
1.使用 @ExceptionHandler(Exception.class) 在类中定义一个异常的方法,处理本类中的指定异常
@RestController
@RequestMapping("/exception")
public class ExceptionController01 {
@ExceptionHandler(Exception.class)
public Result handlerException(Exception e){
Result result = new Result();
result.setSuccess(false);
result.setMsg("发生异常:"+e.getMessage());
return result;
}
}
全局异常处理
2.全局处理模式 定义ExceptionAdvice类
@ControllerAdvice/@RestControllerAdvice
public class ExceptionAdvice {
@ExceptionHandler(value ={Exception.class})
public Object handlerException(Exception e){
Result r = new Result();
r.setSuccess(false);
r.setMsg("发生了点异常,被全局捕获:"+e.getMessage());
return r;
}
}
@RestController作用等同于@Controller + @ResponseBody
@ControllerAdvice主要用于返回视图,可以全局异常处理、全局数据绑定、全局数据预处理。
属性:assignableTypes:指定一个或多个 Controller 类;basePackageClasses:是 basePackages 的一种变形,指定一个或多个 Controller 类;annotations:指定一个或多个注解
@RestControllerAdvice用于直接返回错误信息,@RestControllerAdvice由@ControllerAdvice、@ResponseBody组成
两个同时存在,类里的优先
SSM整合
1.创建maven项目,添加web框架
2.导入依赖
<dependencies>
<!-- 1.引入mybatis依赖-->
<!-- myBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- mybatis分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.3</version>
</dependency>
<!--mybatis spring 插件不能用3,jdk必须是17-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.1.1</version>
</dependency>
<!-- /1.引入mybatis依赖-->
<!-- 2.引入spring依赖 -->
<!--spring-context-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.24.RELEASE</version>
</dependency>
<!--支持切入点表达式-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>
<!--支持aop相关注解-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.19</version>
</dependency>
<!--spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- /2.引入spring依赖 -->
<!-- 3.spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.24.RELEASE</version>
</dependency>
<!--jsonjson解析器,序列化和反序列化-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.2</version>
</dependency>
<!--json数据绑定-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<!--jackson-annotations-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.15.2</version>
</dependency>
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- /3.spring-webmvc -->
<!--4.log4j-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.16.0</version>
</dependency>
<!--/4.log4j-->
<!--5.数据库驱动和连接池-->
<!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!-- druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.18</version>
</dependency>
<!--/5.数据库驱动和连接池-->
<!--6.servlet+jsp依赖-->
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!--jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<!--/6.servlet+jsp依赖-->
<!--7.jstl-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--/7.jstl-->
<!--8.lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<!--/8.lombok-->
<!--9.junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--/9.junit-->
</dependencies>
3.配置tomcat,WEB-INF里创建lib将maven jar包导入
4.编写配置文件(spring-context.xml、spring-mvc.xml、mybatis-config.xml、db.properties、log4j.properties、web.xml)
5.编写entity、mapper、service、controller、jsp
DTO、VO、Entity的区别
DO(Data Object):此对象与数据库表结构一一对应,通过 DAO层向上传输数据源对象。
DTO(Data Transfer Object):数据传输对象,Service 或Manager 向外传输的对象。
VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
- Entity就是一般和数据库对应的实体类,需要与数据库一一对应。
- DTO是数据传输对象,用来接收前端传过来的参数,一般会把前端传过来的参数封装进DTO,然后在Service中复制给新new的entity对象,然后进行持久化。
- VO就是返回给前端的视图对象