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个实现类对象。包括StringHttpMessageConveterMappingjackson2HttpMessageConverter

三、请求转发和重定向

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="//www.springframework.org/schema/beans"
       xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
       xmlns:context="//www.springframework.org/schema/context"
       xsi:schemaLocation="//www.springframework.org/schema/beans //www.springframework.org/schema/beans/spring-beans.xsd //www.springframework.org/schema/context //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="//www.springframework.org/schema/beans"
       xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
       xmlns:context="//www.springframework.org/schema/context" xmlns:tx="//www.springframework.org/schema/tx"
       xmlns:aop="//www.springframework.org/schema/aop"
       xsi:schemaLocation="//www.springframework.org/schema/beans //www.springframework.org/schema/beans/spring-beans.xsd //www.springframework.org/schema/context //www.springframework.org/schema/context/spring-context.xsd //www.springframework.org/schema/tx //www.springframework.org/schema/tx/spring-tx.xsd //www.springframework.org/schema/aop //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过来的!
  • 尊重每一位学习知识的人,同时也尊重每一位分享知识的人。
  • 你的点赞与关注,是我努力前行的无限动力。
Tags: