SpringMVC框架

Spring Web MVC 介绍

SpringMVC 是 Spring 框架的一个模块,Spring 和 SpringMVC 是无需通过中间整合层进行整合。例如 Struts 与 Spring 整合的时候,会有一个 struts-spring 这样的 jar 包,这个包就是整合层。
SpringMVC 是一个基于 MVC 的一个 Web 框架。
MVC:是一个设计模式(设计模式:总结了我们日常开发当中一些很好的经验和编写代码方法,把他抽取一个模式,让我们软件工程师按照这种模式开发,可以少走弯路)。使用这种模式是为了刚好的让我们的系统能够更好的扩展,其在 B/S 和 C/S 下都有应用,

SpringMVC 框架

前端控制器:DispatcherServlet,这个 request 还是请求到了 Servlet 了,请求到 SpringMvc的前端控制器了,比如就是用户注册,他跟我们上面所说的请求是一样的,接受请求,然后响应,谁来处理呢?模型,我们写之前的项目的时候,需要些 service,dao,pojo。
在 SpringMVC 里面,最直接的模型是,是 Handler 处理器,平时我们开发的时候,交流问题的时 候,我们 称之为 controller,在 SpringMVC 里面 DispatcherServlet 不能直接调用Handler,我们的请求要发一个 url,请求链接 前端控制器要通过,处理器映射器处理器映射器:根据 URL 来找到对应的处理器,其实他是根据 XML 配置的方式来找。找到之后,就返回 Handler,返回的不是一个单纯的 Handler , 返回的是一个执行链,叫做 HandlerExecutionChain{ },在这个链当中,就有一个 Handler,在 Handler 之前还有
1.request前端控制器DispatcherServlet接受用户请求,响应
Handler 处理器平常我们称之为 controller处理器映射器HandlerMapping
2. 请求查找Handler
3.返回一个执行链
HandlerExceutionCh
ain{
HandlerIntercepter1
HandlerIntercepter2
Handler
}
处理器适配器HanderAdapter去执行 Handler
4. 请 求 执 行Handler
5.执行
6.返回 ModelAndView
7.返 回ModelAmdView、View 视图、Jsp、Freemark、Excel 、Pdf视图解析器View resolver
8.请求视图解
9. 返回View
10.视图渲染将模型数据填 充 到request 作用域中
11.Response很多的 HandlerIntercepter 拦截器,可以只有一个,也可以有多个。框架的设计,讲究的是框架的可扩展性,其实,在这里,有各种 Handler,我们不可 能 把Handler 写到 DispatcherServlet 里面,如果我们把这个逻辑写到 DispatcherServlet,我们的程序代码很难维护。这个时候,我们就需要一个组件,那就是处理器适配器,HandlerAdapter 去执行 Handler,
举例:手机充电器,接受的电压很小,然后通过充电器进行变压,剃须刀的适配器,也可以改变电压我们会写不同的 Handler,不同的 handler 由不同的的适配器去执行。此时:适配器就调用 Handler 处理器去执行请求,返回 ModelAndView 是模型和视图的结合体。
视图:框架讲究的是可扩展性,视图包括很多,jsp、freemark、excel、pdf 等SpringMVC:通过视图解析器(View resolver)来解析各种视图,解析完毕,返回给前端控制器(DispatcherServlet),返回一个真正的视图,请求的其实是一个逻辑视图,返回真正的视图 View。最后: 视图渲染将模型数据填充到 request 作用域中
总结:
1. 发起请求到前端控制器(DispatcherServlet)
2. 前端控制器请求 HandlerMapping 查找 Handler
- 可以根据 XML 配置
- 也可以根据注解来查找
3. 处理器映射器,向前端控制器返回 Handler
4. 前端控制器要执行 Handler,调用处理器适配器来执行 Handler
5. 处理器适配器去执行 Handler
6. Handler 执行完,给处理器适配器返回 ModelAndView,是 SpringMVC 的一个底层对象
7. 处理器适配器,向前端控制器返回一个 ModelAndView
8. 请求视图解析器,去进行视图解析,根据逻辑视图名,来解析出真正的视图
9. 将视图解析器解析的结果 View,返回给前端控制器
10. 前端控制器进行视图的渲染(就是讲模型数据【在 ModelAndView 中】填充到 request域中),最终返回给用户
11. 前端控制器,向用户响应。
组件:
1. 前端控制器(DispatcherServlet)[中央处理器](不需要程序员开发)
- 作用:接受请求和响应结果(相当于转发器)
- 有了 DispatcherServlet 就减少了其他组件之间的耦合性,
2. 处理器映射器 HandlerMapping(不需要程序员开发)
- 作用:根据请求的 URL 来查找 Handler
3. 处理器适配器 HandlerAdapter
- 作用:按照特定的规则(HandlerAdapter 要求的规则):执行 Handler
4. 处理器 Handler(需要程序员开发)
- 注意:开发 Hander 的时候,要按照 HandlerAdapter 的要求去做,这样适配器才可以去
正确执行 Handler
5. 视图解析器:(不需要程序员开发)
- 作用:进行视图解析,根据逻辑视图,来解析真正的视图(View)
6. 视图(需要程序员来开发 JSP)
- View 是一个接口,他的实现类就是来支持不同的 View 类型,(jsp,freemark,pdf……)

1.需要jar包

 2.配置前端控制器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- 配置前端控制器 -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- contextConfigLocaion配置SpringMVC加载的配置文件(配置处理器映射器,适配器等等) -->
        <!-- 如果不配置 contextConfigLocaion 系统会自动去
        /WEB-INF/servlet名称-servlet.xml (springmvc-servlet) -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <!-- 第一种:*.action,可以访问.action结尾的请求由DispatcherServlet进行解析 -->
        <!-- 第二种:/ 所有访问地址都由DispatcherServlet进行解析,对于静态的文件解析需要配置
         不让DispatcherServlet进行解析,但是使用这种方法可以实现RESTful风格的url -->
        <!-- 第三种:/* 这种配置方式不对,使用这种配置,当我们转发到一个jsp页面时
         仍然由DispatcherServlet进行解析JSP地址,不能根据JSP页面找到handler,会报错 -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>


    <!--<display-name>springmvcdoml</display-name>-->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

log4j.properties

# Global logging configuration 
# 在实际开发过程中,日志级别要设置成DEBUG,生产环境要设置成info或error
log4j.rootLogger=debug, stdout 
# MyBatis logging configuration... 
log4j.logger.org.mybatis.example.BlogMapper=TRACE 
# Console output... 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

 

3.配置处理器适配器 

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

    <!-- 配置handler -->
    <bean id="itemsController1" name="/queryItems1.action"
        class="com.hzxy.springmvcdoml.controller.ItemsController1" />
    <!-- 配置另外一个Handler -->
    <!-- 对于注解的Handler可以单个配置  -->
    <!-- 实际开发中,建议使用组件扫描 -->
    <!-- <bean class="cn.atwyl.ssm.controller.ItemsController3" /> -->
    <!-- 组件扫描的配置方法,可以扫描controller,service...... -->
    <!-- 这里我想让扫描controller,指定controller的包就可以了 -->
    <context:component-scan base-package="com.hzxy.springmvcdoml.controller" />
    
    <!-- 处理器映射器 -->
    <!-- BeanNameUrlHandlerMapping 将bean的name作为URL进行查询找handler -->
    <!-- 在配置handler的时候,要指定你的beanname(就是url) -->
    <bean
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

    <!-- 简单URL映射 -->
    <!--<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">-->
        <!--<property name="mappings">-->
            <!--<props>-->
                <!--<prop key="/queryItems1.action">itemsController1</prop>-->
            <!--</props>-->
        <!--</property>-->
    <!--</bean>-->

    <!-- 处理器适配器 所有的处理器适配器,都实现了一个接口 HandlerAdapter -->
    <!--<bean-->
        <!--class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />-->

    <!-- 还有一个适配器 所有的处理器适配器,都实现了一个接口 HandlerAdapter -->
    <!--<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />-->


    <!-- 试图解析器 -->
    <!-- 解析jsp,默认使用jstl,classpath下的有jstl的包 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--<property name="prefix" value="jsp/"/>-->
        <!--<property name="prefix" value="web/"/>-->
        <property name="suffix" value=".jsp"/>
    </bean>


    <!-- 注解的映射器 -->
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
    <!-- 注解的适配器 -->
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
    <!-- 使用代替上面的两个器,一个是注解映射器,一个是注解适配器 -->
    <!-- mvc:annotation-driven这个mvc的注解驱动,默认还加载了很多的参数的绑定方法 -->
    <!-- 比如json的转换,默认加载了json的转换器,如果使用了这个注解驱动, 上面两行的配置就不需要了 -->


    <!-- 实际开发过程中,我就使用这种注解驱动的配置方式 -->
    <mvc:annotation-driven></mvc:annotation-driven>

</beans>

如下配置 

此适配器能执行----实现了 Controller 接口的 Handler。通过查看源码,如下视图:

 

 

 

4.编写 Handler

Hanlder 需要实现 Controller 接口,才能由 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter 这个适配器来执行。
public class ItemsController1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons
e response) throws Exception {
//调用 Service 查询数据,先使用模拟数据
List<Items> list=new ArrayList<>();
Items items1=new Items();
items1.setId(1)
items1.setItemsCreatetime(new Date());
items1.setItemsDetail("IPhone7Plua Details");
items1.setItemsName("苹果手机 IPhone7s");
items1.setItemsPic("iphone7s.jpg");
items1.setItemsPrice(5888.66f);
Items items2=new Items();
items2.setId(2);
items2.setItemsCreatetime(new Date());
items2.setItemsDetail("IPhone8Plua Details");
items2.setItemsName("苹果手机 IPhone8s");
items2.setItemsPic("iphone8s.jpg");
items2.setItemsPrice(5888.66f);
list.add(items1);
list.add(items2);
//创建 ModelAndView 准备填充数据,设置试图
ModelAndView modelAndView=new ModelAndView();
//填充数据
modelAndView.addObject("itemList",list);
//视图
modelAndView.setViewName("jsp/items/");
return modelAndView;
} 
}

5.视图的编写

 

6. 配置 Handler 

7. 配置映射器处理器 

8.配置视图解析器 

 

非注解的处理器映射器和适配器

1.非注解的处理器映射器

处理器映射器org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping下面多个映射器并存

测试结果:看地址栏,三个地址都可以正常的访问。多个映射器可以并存,前端控制器判断 URL,能让哪些映射器映射,就让正确的映射器处理, 

2.非注解的处理器适配器

非注解的处理器适配器org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter该适配器要求处理器适配器 所有的处理器适配器,都实现了一个接口 Controller。 

编写的 Handler 实现了 HttpRequestHandler 接口。 

配置 springmvc.xml 

 

 

 

DispatcherServlet.properties 

注解的处理器映射器和适配器

在 Spring3.1 之前注解使用映射器:
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping 注解映
射器文器。 在 Spring3.1 之后,就使用映射器:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
注解映射文器。 在 3.1 之前注解使用的适配器是:
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
在 3.1 之后注解使用适配器是:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

3.配置注解的映射器和适配器

3.开发注解的 Handler

 

 

  

4.在 Spring 容器中,来加载 Handler 

5.测试

源码分析(了解)

 

 

 

 

SpringMVC 和 MyBatis 整合

1. 整合的思路 

第一步:整合 dao 层(持久层)
- MyBatis 和 Spring 整合,通过 Spring 管理 Mapper 接口,使用 Mapper 的扫描器,来自
动扫描 mapper 接口在 Spring 中进行注册。
第二步:整合 service 层
- 通过 Spring 管理 service 接口,使用配置的方式,将 Service 接口配置在 Spirng 配置文件。
表现层
业务层:service 接口
持久层:MyBatis
MySQL
Spring 在架构中的作用:
Spring 将各层进行整合
通过 Spring 的整合,可以管理持久层的
mapper,相当于我们写的 dao 的接口。
通过 Spring 管理业务层的 service,service 层
可以调用 Mapper 接口,另外还要进行事务
的控制。
通过 Spring 管理表现层的 Handler,Handler
里面可以调用 Service 里面的接口
Mapper,Service,Handler 都是 JavaBean- 实现事务的控制。
第三步:整合 SpirngMVC
- 由于 SpringMVC 是 Spring 的一个模块,所以这里面不需要整合。 

 

  

2.log4j.properties 

# Global logging configuration 
# 在实际开发过程中,日志级别要设置成DEBUG,生产环境要设置成info或error
log4j.rootLogger=debug, stdout 
# MyBatis logging configuration... 
log4j.logger.org.mybatis.example.BlogMapper=TRACE 
# Console output... 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3.db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis
jdbc.username=root
jdbc.password =971128
#jdbc.maxPoolSize=20
#jdbc.minPoolSize=2

4.SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--开启延迟加载放到properties 标签下-->
    <settings>
        <setting name="lazyLoadTriggerMethods" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>

        <!--开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <!-- SSM   SSH   Spring   MyBatis  Hibernate Struts -->
    <!-- 以后该配置将会配置到Spring内,此处被废弃 -->
    <typeAliases>
        <package name="com.hxzy.SSM.mapper"/>
    </typeAliases>
</configuration>

5.applicationContext-dao.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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
    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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<!--开启注解扫描-->
    <context:component-scan base-package="com.hxzy.SSM.controller"/>

    <!--1.加载db.properties的配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--开启AOP-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <!-- 配置事务管理器 -->
    <!--<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">-->
    <!--<property name="dataSource" ref="dataSource"/>-->
    <!--</bean>-->

    <!--开启事务注解-->
    <!--<tx:annotation-driven transaction-manager="transactionManager"/>-->
    <!--2.配置j3po的数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}"/>
   <!--<property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>-->
    <!--<property name="jdbc.minPoolSize" value="${jdbc.minPoolSize}"/>-->
</bean>
    <!--3.配置sqlSessionFactory-->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--加载mybatis的配置文件-->
        <property name="configLocation" value="mybatis/SqlMapConfig.xml"/>
        <!--配置dataSource的数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--批量扫描mapper.xml文件 严格首字母大写-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.hxzy.SSM.mapper"></property>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
</bean>
    <!--//将service注入-->
    <bean id="itemsService" class="com.hxzy.SSM.service.ItemsServiceImpl"/>
    
<!--声明事务控制-->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!--通知-->
    <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
        <!--转播行为-->
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="insert*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.hxzy.SSM.service.*Impl.*.*(..))"/>
    </aop:config>

</beans>

6. 整合 SpringMVC   springmvc.xml

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- contextConfigLocaion配置SpringMVC加载的配置文件(配置处理器映射器,适配器等等) -->
        <!-- 如果不配置 contextConfigLocaion 系统会自动去
        /WEB-INF/servlet名称-servlet.xml (springmvc-servlet) -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc/springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <!-- 第一种:*.action,可以访问.action结尾的请求由DispatcherServlet进行解析 -->
        <!-- 第二种:/ 所有访问地址都由DispatcherServlet进行解析,对于静态的文件解析需要配置
         不让DispatcherServlet进行解析,但是使用这种方法可以实现RESTful风格的url -->
        <!-- 第三种:/* 这种配置方式不对,使用这种配置,当我们转发到一个jsp页面时
         仍然由DispatcherServlet进行解析JSP地址,不能根据JSP页面找到handler,会报错 -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

</web-app>

springmvc.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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

    <!-- 配置handler -->
    <!--<bean id="itemsController1" name="/queryItems1.action"
        class="com.hzxy.springmvcdoml.controller.ItemsController1" />-->
    <!-- 配置另外一个Handler -->
    <!-- 对于注解的Handler可以单个配置  -->
    <!-- 实际开发中,建议使用组件扫描 -->
    <!-- <bean class="cn.atwyl.ssm.controller.ItemsController3" /> -->
    <!-- 组件扫描的配置方法,可以扫描controller,service...... -->
    <!-- 这里我想让扫描controller,指定controller的包就可以了 -->
    <context:component-scan base-package="com.hxzy.SSM.controller" />
    
    <!-- 处理器映射器 -->
    <!-- BeanNameUrlHandlerMapping 将bean的name作为URL进行查询找handler -->
    <!-- 在配置handler的时候,要指定你的beanname(就是url) -->
    <bean
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

    <!-- 简单URL映射 -->
    <!--<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">-->
        <!--<property name="mappings">-->
            <!--<props>-->
                <!--<prop key="/queryItems1.action">itemsController1</prop>-->
            <!--</props>-->
        <!--</property>-->
    <!--</bean>-->

    <!-- 处理器适配器 所有的处理器适配器,都实现了一个接口 HandlerAdapter -->
    <!--<bean-->
        <!--class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />-->

    <!-- 还有一个适配器 所有的处理器适配器,都实现了一个接口 HandlerAdapter -->
    <!--<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />-->


    <!-- 试图解析器 -->
    <!-- 解析jsp,默认使用jstl,classpath下的有jstl的包 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--<property name="prefix" value="jsp/"/>-->
        <!--<property name="prefix" value="web/"/>-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 注解的映射器 -->
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
    <!-- 注解的适配器 -->
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
    <!-- 使用代替上面的两个器,一个是注解映射器,一个是注解适配器 -->
    <!-- mvc:annotation-driven这个mvc的注解驱动,默认还加载了很多的参数的绑定方法 -->
    <!-- 比如json的转换,默认加载了json的转换器,如果使用了这个注解驱动, 上面两行的配置就不需要了 -->


    <!-- 实际开发过程中,我就使用这种注解驱动的配置方式 -->
    <mvc:annotation-driven></mvc:annotation-driven>

</beans>

注解

@RequestMapping 注解

1.URL 映射
定义 controller 方法对应的 url,进行处理器映射使用。
2.窄化请求映射
为了很好的分类管理我的这个 url 映射,我就在 controller 上面定义一个根。最终访问的路径,即使根路径+子路径比如说商品的列表:/items/queryItems.action,这种叫做窄化请求映射 
3.限制请求方法
可以限制 HTTP 的请求的方法:处于一些安全的考虑,对一些 HTTP 的链接进行限制,可以是 get 也可以是 post,也可以是即使 get 又是 post 

Cntroller 方法的返回值

1. 可以返回 ModelAndView

- 方法结束的时候,定义 ModelAndView,将 model 和 view 分别进行设置。

2. 还可以返回 Srring

- 如果 controller 返回的是 String,表示返回的是逻辑视图名
- 真正的视图(JSP 路径)=前缀+逻辑视图名+后缀
 

 -Redirect 重定向

- forward 页面转发

- 通过 forward 地址栏不变,request 可以共享。

 

3. 还可以返回 void

参数绑定 

@RequestParam

通过@RequestParam 对简单的类型的参数进行绑定,如果不使用这个注解@RequestParam,要求 request 传入的参数名称要和 controller 方法的形参名称一致,方可绑定成功。

SpringMVC 参数绑定的过程

从客户端请求 Key/Value 数据,经过参数绑定,将 Key/Value 的数据,绑定到 Controller 的形参上。在 SpringMVC 中,是通过方法的形参,来接受数据,而不是在 Controller 来定义成员变量。

默认支持的类型

直接在方法的形参上,定义下边类型的对象,就可以使用这些对象,就是在参数绑定的过程中,如果遇到下边的类型,就直接进行绑定。
1. HttpServletRequest
- 通过 request 获取信息
2. HttpServletResponse
- 通过 response 处理相应信息
3. HttpSession
- 通过 session 对象得到 session 中存放对象
4. Model/ModelMap
- Model 是一个接口
- ModelMap 是一个接口的实现,写 Model 和写 ModelMap 其实都一样。
- 作用:将模型数据,填充到 request 域

简单类型

POJO 绑定

页面中的 input 的 name 与 controller 的 pojo 形参的属性名一致。将页面中的数据,绑定到POJO。页面的定义如下:

形参 ItemsCustom 的属性名:

 

 

自定义参数绑定实现日期类型的绑定

对于 Controller 形参中的 pojo 对象,如果属性中有日期类型,需要自定义参数绑定。将请求的日期字符串转成日期类型,要转换的日期类型,和 pojo 中的属性的类型保持一致。所以说,自定义的参数绑定要
 
将日期转成 java.util.Date 类型。需要向处理器适配器中,注入我们自定义的参数绑定组件:

 

 

配置方式:

 

 

 

乱码

 

 

包装类参数绑定 

 

 

 

 

 

集合类型绑定

数组的绑定

 

 

 

 

 

 

List 绑定

通常情况下需要批量提交数据的时候,将提交的数据绑定到 List<pojo>中,比如说,成绩的录入,会产生批量提交的情况。本例子:批量商品的修改:在页面中输入多个商品的信息, 将多个商品的信息 , 提交到Controller 的方法中……
1. 进入批量修改的页面:(页面样式,可以参考我们的商品列表页面实现 )
2. 批量商品修改提交:
使用 List 接受页面提交的批量数据,通过包装 pojo 来接受,在包装 pojo 中,要定义 list 属性 

 

 

 

 

Map 的绑定

 

服务端校验

校验的理解 

项目中,通常使用的较多的是前端的校验,比如页面中的 js 校验, 对应安全性要求较高的属性字段,建议在服务器端校验。服务端校验:控制层:controller 校验页面请求参数的合法性。在服务端控制层 controller 校验,不区分客户端的类型(浏览器,手机客户端,远程接口的调用)。业务层:service 主要校验业务比较关键的一些参数,仅限于 service 接口中所使用的参数。
持久层 dao:一般不校验。用较多的是 service 层。你不能只知道 JS 校验,你也要知道服务端也可以校验。 

SpringMVC 的校验

SpringMVC 使用 Hibernate 的校验框架 validation(和 Hibernate 没有任何关系)。就是一个校验框架。
校验的思路:
页面提交的请求的参数,请求到 controller 方法中,使用我们上面所说的 validation 进行校验,如果校验通过,就往 service 里面走,如果校验失败,将错误信息展现在页面。
需求:
商品修改,我们要添加校验(校验商品的名称的长度 1-30 个字符,生产日期非空校验),如果出错,我们在修改商品的页面显示错误信息。

准备环境

Hibernate 的校验框架 validation 所需 jar 包 

配置校验器 

<!-- 配置校验器 --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<!-- hibernate 校验器 --> <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
<!-- 指定校验使用的资源文件,如果不指定则默认使用 classpath 下的 ValidationMessage.properties --> <property name="validationMessageSource" ref="messageSource"></property>
</bean>
<!-- 验证错误信息配置文件 --> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMe
ssageSource">
<!-- 资源文件名 --> <property name="basenames"> <list><value>classpath:CustomValidationMessage</value>
</list>
</property>
<!-- 资源文件编码方式 --> <property name="fileEncodings" value="UTF-8"></property>
<!-- 对资源文件内容缓存时间,单位秒 --> <property name="cacheSeconds" value="120"></property>
</bean>

校验器注入到处理器适配器 

校验的错误信息   CustomValidationMessage.properties

###配置验证的错误消息
items.name.length.error=请输入长度为1-30个字符以内的商品名称
items.createtime.notnull.error=商品的生产日期不能为空

在 pojo 中添加校验的规则

 

 

Controler 里面的校验写法 

 

在页面中显示错误信息:

Validation 校验-分组校验

在 pojo 中,定义校验规则,而 pojo 中是被多个 controller 所共用,当需要不同的 controller方法对同一个 pojo 进行校验,每个 Controller 对同一个的 pojo 属性,需要不同的校验方法,该怎么解决?
解决方法:定义多个校验分组(其实就是一个 Java 接口);分组中定义有哪些规则。每个 Controller 方法使用不同的校验组

在校验规则中,添加分组

在 Controller 方法中,使用分组 

数据回显

提交后,如果出现错误,将刚才提交的数据回显到提交页面。
1. SpringMVC 默认对 pojo 数据进行回显,
- Pojo 数据传入 controller 中以后,springmvc 自动的将 pojo 的数据存入 request 作用域中,key 等于 pojo 类型的首字母小写。
2. 我们使用@ModelAttribute 指定 pojo 回显到页面在 request 中的 key。 

 

 

4. @ModelAttribute 还可以将方法的返回值传到页面:
- 需求:
- 在商品的查询的列表页面,通过商品的类型来查询商品的信息:
- 在 controller 中来定义商品查询的方法,最终将商品的类型传到页面。

 

 

最简单的数据回显的方法其实就是使用 model 

简单数据类型的回显只能使用 model

使用简单的方法 model:model.addAttribute("id", id);

异常处理的思路

系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发,测试通过手段减少运行时异常的发生。系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常的处理,如下图:

 

自定义的异常类

对不同的异常类型定义异常类,有多少种异常的类型,你就定义多少种异常的类就行了。异常类,要继承 Exception; 

全局异常处理器

当我们系统遇到异常,在程序中,手动抛出,Dao 抛给 Service,Service 抛给 Controller,最后 Controller 抛给前端控制器,前端控制器调用全局的异常处理器:全局异常处理器的思路;首先要解析出当前的异常类型。如果该异常是系统自定义的异常,就直接取出异常的错误信息,在错误页面显示如果不是系统自定义的异常,那基本上都是系统的运行时异常,那么我们就构造一个自定义异常,构造出一个自定义异常类型(信息为“未知错误”)

 

 

 

错误页面

在 SpringMVC 中,来配置全局异常处理器

异常测试:

在 Controller、service、dao 中任意一处需要手动抛出异常。如果在程序中手动抛出异常,在错误页面中显示自定义异常信息,如果不是手动抛出的异常,说明是一个运行时异常,在错误页面显示“未知错误”。我们在商品修改的 Controller 方法中抛出异常: 

 

上传图片

加入上传图片的 jar 包 

 

SpringMVC 中对多部件类型的解析

jsp 的页面的 form 中提交 enctype=multipart/form-data 的数据的时候,需要 SpringMVC在 SpringMVC 的配置文件中,springmvc.xml 中配置 multipart 类型的解析器。

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.Common
sMultipartResolver">
<!-- 设置上传文件的最大的尺寸为 5M -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>

配置上传图片的解析器:

创建一个图片的虚拟目录来存放图片

也可以直接修改 Tomcat 的配置文件 Tomcat-----conf------server.xml添加虚拟目录:

 

//绑定参数修改
    @RequestMapping(value = "/editItemsSubmit",method = {RequestMethod.POST,RequestMethod.GET})
    //在修改时进行校验
    //需要添加@Validated注解
    //提示信息添加
    //分组校验添加value = ValidationGroupOne.class
    //进行回显
    public  String editItemsSubmit(Model model, @ModelAttribute("itemsCustom") @Validated(value = ValidationGroupTow.class)
            ItemsCustom itemsCustom , BindingResult bindingResult, MultipartFile items_pic,
                                   @RequestParam(value = "id",required = true) Integer id)  throws Exception {
        System.out.println(itemsCustom);
        System.out.println("______________________________进来哦了_________________________________________");

        System.out.println("______________________________进来哦了_________________________________________");
        //获得校验信息
        if (bindingResult.hasErrors()) {
            //输出校验信息
            List<ObjectError> allError = bindingResult.getAllErrors();
            //输出遍历校验信息
            System.out.println("*********输出遍历校验信息***********"+allError.toString());
            for (ObjectError objectError : allError) {
                System.out.println(objectError.getDefaultMessage());
            }
            model.addAttribute("allErrors", allError);
            //利用 model.addAttribute也可以进行回显
            //model.addAttribute("itemsCustom",itemsCustom);
            return "items/editItems";//输入错误返回当前页面
        } else {
           //上传文件
            //判断得到的文件是否是否空,文件的名称的长度>0
            if (items_pic!=null&&items_pic.getOriginalFilename().length()>0){
                //保存文件的物理路径
                String pic_th="F:\\upload\\";
                //拿到图片的原始名称
                String originalFilename=items_pic.getOriginalFilename();
                //获得原始图片的后缀名
                String lastName=originalFilename.substring(originalFilename.lastIndexOf("."));
                //新图片的名称,使用UUID的随机数获得
                String newFileName= UUID.randomUUID()+lastName;
                //新的图片
                File newFile=new File(pic_th+newFileName);
                //将内存中的图片写入磁盘
                items_pic.transferTo(newFile);
                //将新的文件写入数据库
                itemsCustom.setPic(newFileName);

            }
                itemsService.updateByPrimaryKeyWithBLOBs(itemsCustom, id);
            return "redirect:queryItems.action";//成功转到展示页面
        }

    }

Json 的数据交互

@RequestBody 

SpringMVC 默认用 MappingJacksonHttpMessageConverter 对 json 数据进行转换,需要加入客户端请求 K/V 串请求的是 JSON 串不是默认的类型,需要指定:contentType=”application/json”@RequestBody 将 JSON 串转换成Java 对@ResponseBody 将 Java 对象转换成Json 对象输出请求的是 key/value默认的类型,不需要指定:contentType=”application/x-www-form-urlencoded”不需要@RequestBody 将 JSON 串转换成 Java 对象@ResponseBody 将 Java 对象转换成 Json 对象输出最终:都输出 Json 数据,为了在前端方便对请求的结果进行解析11jar 包:在 SpirngMVC 中,用以下三个 jar包进行 Json 转换。(@RequestBody 和 @ResponseBody 使用下边这两个包进行 Json 转换。) 

配置 Json 转换器

 

拦截器

 定义:Spring Web MVC 的处理器拦截器类似于 Servlet 开发中的过滤器,用于对处理器进行预处理和后处理。 

拦截器的定义:定义拦截器,它实现了 HandlerInterceptor 
public class HandlerInterceptor1 implements HandlerInterceptor {
    @Override
    //进入Handler 方法之前执行
    //可以用于身份证和身份授权
    //比如 身份证不通过,就表明认证不通过,没有登录,就用此方法来拦截,不在往下执行
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        //获得访问路径
         String url=httpServletRequest.getRequestURI();
         if (url.indexOf("userLagin.action")>=0){
             return  true;
         }
        HttpSession session=httpServletRequest.getSession();
         //获得session作用域的用户名
        String username= (String) session.getAttribute("username");
         if (username!=null&&username!=""){
             return  true;
         }
         httpServletRequest.getRequestDispatcher("/loginUser.jsp").forward(httpServletRequest,httpServletResponse);
        return false ;
    }
//进入Handler后,返回ModelAndView之前,执行
    //应用场景从ModelAndView出发,可以将公共的模型(列如:面包屑导航)传统到视图
    //可以在此方法中,统一指定视图
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    //Handler执行完成,执行该方法
    //应用:可以统一异常处理
    //统一的日志处理
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

拦截器的配置

Spring Web MVC 的拦截器,是针对 HandlerMapping 进行拦截设置。第一种配置方式:(这种方式我们一般不推荐使用,麻烦)如果在某个 HandlerMapping 中配置拦截器,经过 HandlerMapping 映射成功的 Handler 才能使用拦截器。 

第二种配置方法:

Spring Web MVC 配置类似全局的拦截器,SpringMVC 框架,会将配置的拦截器,自动的注入到每一个 HandlerMapping 中。

拦截器的测试测试

需求

1:测试多个拦截器各个方法的执行时机。 

HandlerInterceptor1......preHandle
HandlerInterceptor2......preHandle
HandlerInterceptor2......postHandle
HandlerInterceptor1......postHandle
HandlerInterceptor2......afterCompletion
HandlerInterceptor1......afterCompletion 
posted @ 2020-05-02 13:35  苏先生139  阅读(1365)  评论(0编辑  收藏  举报