SpringMVC基础知识
一、SpringMVC了解
-
springmvc的底层是Servlet,以Servlet为核心,接收请求,处理请求,显示处理结果给用户。
-
DispatcherServlet 是框架一个Servlet对象,负责接收请求,响应处理结果。
-
DispatcherServlet 他的父类是HttpServlet
-
M:Model,模型层,指工程中的JavaBean,作用是处理数据
-
V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据
-
C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器
-
MVC的处理模式是:用户通过视图层(View)将数据发送给服务器的控制层(Controller),控制层通过调用业务层在调用数据层去获取数据, 然后再将请求处理的结果返回给View视图层,最后视图层渲染数据响应给浏览器。
二、SpringMVC入门
2.1 springmvc配置
- 在springmvc.xml中配置
<!-- 添加注解扫描器 -->
<context:component-scan base-package="com.meteor.controller"/>
<!-- 添加视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置前缀 -->
<property name="prefix" value="/admin/"/>
<!-- 配置后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
- 在web.xml中配置
<!-- 注册SpringMVC框架 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 填写springmvx.xml配置文件的名称,让它去读取 -->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--注册Spring框架,目的就是启动spring容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext_*.xml</param-value>
</context-param>
2.2 解决post请求中文乱码问题
<!--添加中文编码过滤器
private String encoding;
private boolean forceRequestEncoding;
private boolean forceResponseEncoding;
-->
<filter>
<filter-name>encode</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>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encode</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.3 @RequestMapping注解
-
可以放在类的上面,相当于多加了一层路径
-
可以放在方法上面,表示请求的路径
-
value可以默认不写,method默认是GET请求
-
参数最好使用包装类型,例如Integer,能接收空值情况,接收的是null
@RequestMapping(value = "/some.do", method= RequestMethod.GET)
public ModelAndView doSome() {
接收请求参数:
- 使用restful方式,在超链接或者地址栏上提交数据时,需要使用@PathVariable这个注解来拿值
@RequestMapping("/hello/{name}/{age}")
public String one(@PathVariable String name,@PathVariable Integer age) {
return "main";
}
- 如果我们前端的名称和后端的名称不一致,则需要使用RequestParam注解来设置相对应的值
@RequestMapping("/hello")
public String one(@RequestParam("name") String uname,@RequestParam("age") Integer uage) {
return "main";
}
- 还可以使用老样子,用request.getParameter()方法来获取值
@RequestMapping("/hello")
public String one(HttpServletRequest request) {
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
return "main";
}
- 当提交参数过多的时候,我们可以使用实体类来接收参数,但是在提交请求中,保证请求参数名称与实体类中成员变量名称一致,可以自动提交数据
@RequestMapping(value = "/test/receive-property.do")
public ModelAndView doPropertyParam(User user) {
2.4 方法的返回值
-
String:客户端资源的地址,自动拼装前缀和后缀,还可以屏蔽自动拼接字符串,可以指定返回路径
-
Object:返回json格式的对象,自动将对象或者集合转为json,使用jackson工具进行转换,必须添加jackson依赖,一般用于ajax
-
void:无返回值,一般用于ajax请求
-
基本数据类型,用于ajax请求
-
ModelAndView:返回数据和视图对象,用的较少
-
当我们采用ajax方式请求的时候,需要配置注解驱动
<mvc:annotation-driven/>
,并且在类上加入@ResponseBody
,也可以使用@RestController
,它是@Controller
+@ResponseBody
2.5 HttpMessageConverter 消息转换器
HttpMessageConverter接口:
- 可以将json数据转成java对象,同时也可以将java对象转成json字符串返回给前端
//把对象转为json
ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(student);
System.out.println("json=" + json);
- 需要在springmvc的配置文件中,加入注解驱动的标签,
mvc:annotation-driven
加入这个标签后,springmvc项目启动后,会创建HttpMessageConveter
接口的7个实现类对象。包括StringHttpMessageConveter
和Mappingjackson2HttpMessageConverter
三、请求转发和重定向
3.1 请求转发
-
请求转发的url地址栏是不变的
-
转发使用
forward
这个时候会清空我们的视图解析器配置,需要我们自己写明白具体的路径
@RequestMapping("/other")
public String other() {
System.out.println("访问了other");
return "main";
}
@RequestMapping("/two")
public String two() {
System.out.println("请求转发action跳转");
// forward:这组字符串可以屏蔽前缀和后缀的拼接
return "forward:/other.do";
}
3.2 重定向
-
重定向的url是改变的,并且变得是最终请求的地址url
-
重定向无法携带数据,并且需要使用
redirect
,也要写明路径名称
@RequestMapping("/three")
public String three() {
System.out.println("这是重定向页面");
return "redirect:/admin/main.jsp";
}
@RequestMapping("/four")
public String four() {
System.out.println("这是重定向action");
return "redirect:/other.do";
}
3.3 SpringMVC默认的参数类型
-
HttpServletRequest
-
HttpServletResponse
-
HttpSession
-
Model
-
Map
-
ModelMap
-
Model、Map、ModelMap和HttpServletRequest 一样,使用请求作用域进行数据传递,所以服务器跳转必须是请求转发。
- 这些参数我们都可以直接用,因为springmvc已经为我们准备好了。
四、SpringMVC资源处理问题
4.1 静态资源的处理方法
由于我们的中央调度器设置的是 "/":
使用 "/" 导致中央调度器是默认的 default servlet
需要处理静态资源和其他的为映射请求。 默认中央调度器没有处理静态资源的控制器对象,所以静态资源都是404.
some.do这个请求有MyController对象,所以能访问。
如果项目中,中央调度器设置了"/",动态资源能访问,静态资源不能访问,需要处理静态资源的访问工作。
注解式方法:
<!--声明注解驱动
default-servlet-handler和@RequestMapping使用有冲突
-->
<mvc:annotation-driven />
<!--声明静态资源的第一种处理方式
创建DefaultServletHttpRequestHandler处理静态资源。
DefaultServletHttpRequestHandler把接收的静态资源的地址,转发给tomcat的default
优点:解决方式简单
缺点:依赖tomcat服务器提供的能力
-->
<mvc:default-servlet-handler />
导入静态资源法:
-
在springmvc配置文件中加入一个 mvc:resources标签,框架会创建ResourceHttpRequestHandler控制器对象,使用这个对象处理静态资源的访问,不依赖tomcat服务器。推荐使用!
-
一句话设置静态资源
<mvc:resources mapping="/static/**" location="/static/" />
五、SpringMVC核心技术
5.1 拦截器
WEB-INF目录下的资源无法通过浏览器的url直接访问。都是通过controller的请求转发进行访问
但是这样也并不安全,因为我可以把它的请求路径记住,所以我们就需要用到了拦截器
拦截器的定义:
-
创建类实现拦截器接口 HandlerInterceptor,实现接口中的方法3个
-
preHandle():在请求被处理之前进行操作
-
postHandle():在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果
-
afterCompletion:所有的请求响应结束后执行善后工作,清理对象、关闭资源、最终处理
-
-
在springmvc的配置文件中,声明拦截器对象,并置顶拦截的url地址
<!-- 注册拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- 设置放行的请求 -->
<mvc:exclude-mapping path="/shouLogin"/>
<mvc:exclude-mapping path="/login"/>
<!-- 配置具体的拦截器实现功能类 -->
<bean class="com.meteor.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
//拦截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle先处理");
return true;
}
}
-
多个拦截器的时候也采用的是责任链设计模式,和我们JavaWeb部分的Filter过滤器一样,可以跳转到我的Tomcat深入浅出文章去了解一下
-
先执行过滤器、在执行中央调度器、最后才是拦截器。
-
一般拦截器都是用作登录拦截
5.2 异常处理机制
框架使用的是集中的异常处理。把各个Controller中抛出的异常集中到一个地方处理。处理异常的叫做异常处理器。
-
@ControllerAdvice:放在类的上面,表示这个类中有异常的处理方法。相当于aop中的@Aspect
-
@ExceptionHandler:放在方法的上面,表示此方法可以处理某个类型的异常。当异常发生时,执行这个方法。
@ControllerAdvice
public class GlobalExceptionHandler {
//定义处理异常的方法,当异常发生后,执行这个方法
/**
*处理NameException类型的异常
* 参数:
* @ExceptionHandler: 表示Controller抛出的异常对象
* 属性: value 异常的类型
*/
@ExceptionHandler(value = NameException.class)
public ModelAndView doNameException(Exception e) {
//给用户友好的提示
ModelAndView mv = new ModelAndView();
mv.addObject("tips","姓名只能是zs");
mv.setViewName("nameError");
return mv;
}
}
- 我们可以通过这种方式去设置一个全局异常处理,也可以给某个单个异常进行处理。
六、SSM整合
6.1 整合思路
-
我们需要把java对象放到容器里,我们现在有两个容器
-
Spring容器:管理service和dao等对象的,是业务层对象的容器。
-
SpringMVC容器:管理控制器controller对象的,是视图层对象。
6.2 容器创建
Spring容器创建: 在web.xml中声明了ContextLoaderListener
,这个功能是框架写好的,创建spring容器对象WebApplicationContext
。在创建WebApplicationContext
的时,就读取了spring的配置文件,当遇到bean
标签的时候就将service、dao等对象创建好放到容器中。
SpringMVC容器创建: SpringMVC是Spring的子容器,它是用于将pojo实体类的对象创建出来的,操作的是Controller层
6.3 三层架构配置文件
application_mapper.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 https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 读取属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置SqlSessionFactoryBean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!-- 配置SqlMapConfig.xml核心配置文件-->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
<!--注册实体类-->
<property name="typeAliasesPackage" value="com.meteor.pojo"/>
</bean>
<!-- 注册mapper.xml文件-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.meteor.mapper"/>
</bean>
</beans>
application_service.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" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--添加包扫描-->
<context:component-scan base-package="com.meteor.service.impl"></context:component-scan>
<!--添加事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--切记切记:配置数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务切面-->
<tx:advice id="myadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*select*" read-only="true"/>
<tx:method name="*find*" read-only="true"/>
<tx:method name="*serach*" read-only="true"/>
<tx:method name="*get*" read-only="true"/>
<tx:method name="*insert*" propagation="REQUIRED"/>
<tx:method name="*add*" propagation="REQUIRED"/>
<tx:method name="*save*" propagation="REQUIRED"/>
<tx:method name="*set*" propagation="REQUIRED"/>
<tx:method name="*update*" propagation="REQUIRED"/>
<tx:method name="*change*" propagation="REQUIRED"/>
<tx:method name="*modify*" propagation="REQUIRED"/>
<tx:method name="*delete*" propagation="REQUIRED"/>
<tx:method name="*drop*" propagation="REQUIRED"/>
<tx:method name="*remove*" propagation="REQUIRED"/>
<tx:method name="*clear*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!--配置切入点+绑定-->
<aop:config>
<aop:pointcut id="mycut" expression="execution(* com.meteor.service.impl.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="myadvice" pointcut-ref="mycut"></aop:advisor>
</aop:config>
</beans>
springmvc.xml
//添加包扫描
<context:component-scan base-package="com.meteor.controller"/>
//便于使用ajax
<mvc:annotation-driven/>
- 分页的基本公式:基础分页公式:limit (当前页面-1)*每页条数,每页条数
七、结尾
- 这些只是SpringMVC的基础入门知识,毕竟笔者也仅仅二刷,待笔者闭关修炼,后续会继续更新源码底层知识。
- 对于SpringMVC内容就总结这么多,若想深入学习等待后续更新。
- 我将会继续更新关于Java方向的学习知识,感兴趣的小伙伴可以关注一下。
- 文章写得比较走心,用了很长时间,绝对不是copy过来的!
- 尊重每一位学习知识的人,同时也尊重每一位分享知识的人。
- 你的点赞与关注,是我努力前行的无限动力。