SSM整合

一、跨域访问

概述

根据浏览器的同源策略,不同服务器之间是不能访问的,否则服务器不安全

只有加了相互信任的域才能狗进行访问。

应用

被访问的目标资源需要加入访问我的链接的信任域;例如,A访问B;在B处设置A可以访问我

@CrossOrigin("http://localhost:8080") //允许此域发请求访问
public class UserController {
	//...
}

Ajax访问时,需要进行配置:

 $("#btn").click(function () {
     $.ajax({
         type: "POST",
         url: "http://localhost:8081/hello1",
         xhrFields: {
             // 跨域携带cookie
             withCredentials: true
         }
     });
 })

注意事项

1.需要两个工程,一个设置8081; 另一个设置8080端口;都配置SpringMVC

2.两个工程测试springMVC目标handler成功

3.必须处理静态资源的访问:<mvc:default-servlet-handler />

二、SSM整合

DAO的SSM

先进行DAO测试,先结合DAO与mybatis进行处理。

Spring核心库的配置:

<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 产生数据源的bean,将加载的数据库驱动注入 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
<!-- sqlSessionFactory工厂bean的产生;里面配置了数据源,注册mapper,别名,分页插件-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="mapperLocations">
        <list>
            <value>classpath:mapper/*.xml</value>
        </list>
    </property>
    <property name="typeAliasesPackage" value="com.qf.entity"></property>

    <!-- spring容器配置  类似于ref属性引入bean对象 -->
    <property name="plugins">
        <bean class="com.github.pagehelper.PageInterceptor"></bean>
    </property>
</bean>
<!-- 通过扫描器方式创建接口目录中的bean -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 产生dao的bean对象,id为接口首字母小写 -->
    <property name="basePackage" value="com.qf.dao"></property>
</bean>
<!-- 注解扫描 -->
<context:component-scan base-package="com.qf"></context:component-scan>

使用spring单元测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:bean/bean-*.xml")
public class SpringTest { //产生当前类的bean
    @Resource
    private UserDao userDao;
    @Test
    public void daoTest(){
        List<User> list = userDao.selectUsers();
        System.out.println(list);
    }
}

SSM测试

完成springMVC配置:

配置web.xml:

<servlet>
    <servlet-name>mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param><!-- 初始化springMVC的配置 -->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:mvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>mvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- 通过监听器用于加载spring的工厂 -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 加载spring容器 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:bean/bean-*.xml</param-value>
</context-param>

mvc.xml的配置:

<!-- 扫描控制层注解 -->
<context:component-scan base-package="com.qf.controller"></context:component-scan>
<!-- 开启springMVC的注解驱动 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 静态访问处理 -->
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
</bean>

控制层测试:

@Controller
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;
    @RequestMapping("/users")
    public String users(HttpServletRequest request){
        System.out.println("展示数据...");
        List<User> list = userService.selectUsers();
        request.setAttribute("list",list);
        return "show";
    }
}

事务配置

分离spring容器用于配置事务。bean-tx.xml

<!-- 事务管理器bean -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 事务的增强,管理事务管理器 -->
<tx:advice id="tx" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="select*" propagation="SUPPORTS"/>
        <tx:method name="add*" rollback-for="Exception" />
        <tx:method name="delete*" rollback-for="Exception" />
        <tx:method name="update*" rollback-for="Exception" />
    </tx:attributes>
</tx:advice>

<!-- 切点与增强绑定,形成切面 -->
<aop:config>
    <aop:pointcut id="po" expression="execution(* com.qf.service.*.*(..))"/>
    <aop:advisor advice-ref="tx" pointcut-ref="po"></aop:advisor>
</aop:config>

三、功能与优化

细节

  1. 扫描冲突问题

mvc容器与spring容器的注解扫描有重合的地方,容易出现接口污染;所以需要调整成如下情况:

mvc容器只负责com.qf.controller的扫描,其它的不扫

spring容器负责扫描com.qf中除了controller以为的其它注解

<context:component-scan base-package="com.qf">
    <!-- spring容器中, 除了controller包,其它的都扫描 -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  1. 容器调用

    DispatcherServlet 启动springMVC容器,负责产生控制层的组件

    ContextLoaderListener启动spring容器,负责产生除控制层以外的组件

  2. 父子关系

    springMVC是spring的子容器,所以springMVC是spring的扩展与延申

分页

导入分页插件,及配置分页插件bean,在业务层封装分页实体

@Override
public PageInfo<User> selectPage(String pageNum, String pageSize) {
    int pnum = 1;
    int psize = 4;
    if(pageNum!=null){
        pnum = Integer.parseInt(pageNum);
    }
    if(pageSize!=null){
        psize = Integer.parseInt(pageSize);
    }
    PageHelper.startPage(pnum,psize); //分页设置
    List<User> list = userDao.selectUsers();
    return new PageInfo<>(list); //返回封装的Page实体
}

控制层获取分页参数

@RequestMapping("/pages")
public String pages(HttpServletRequest request){
    System.out.println("展示分页...");
    String pageNum = request.getParameter("pageNum");
    String pageSize = request.getParameter("pageSize");
    PageInfo<User> pageInfo = userService.selectPage(pageNum,pageSize);
    System.out.println("分页:"+pageInfo);
    request.setAttribute("p",pageInfo);
    return "show";
}

前端显示分页数据

<table border="1">
    <tr>
        <td>ID号</td>
        <td>姓名</td>
        <td>密码</td>
        <td>性别</td>
        <td>操作</td>
    </tr>
    <c:forEach items="${p.list}" var="u">
        <tr>
            <td>${u.id}</td>
            <td>${u.name}</td>
            <td>${u.password}</td>
            <td>${u.sex}</td>
            <td><a href="#">删除</a> |
                <a href="#">修改</a>
            </td>
        </tr>
    </c:forEach>
</table>

<a href="/user/pages?pageNum=1&pageSize=4">首页</a>
<c:if test="${p.hasPreviousPage}">
    <a href="/user/pages?pageNum=${p.pageNum-1}&pageSize=4">上一页</a>
</c:if>
<c:if test="${p.hasNextPage}">
    <a href="/user/pages?pageNum=${p.pageNum+1}&pageSize=4">下一页</a>
</c:if>
<a href="/user/pages?pageNum=${p.pages}&pageSize=4">尾页</a>
共${p.pageNum}/${p.pages}页

删除

DML的功能的事务操作,在SSM整合中,都通过AOP方式注入了,所以使用非常方便,只关注核心删除功能.

<a href="/user/delete/${u.id}">删除</a>
//控制层进行删除功能操作
@RequestMapping("/delete/{id}")
public String delete(@PathVariable Integer id){
    int res = userService.deleteById(id); //根据id删除
    System.out.println("删除:"+res);
    return "redirect:/user/pages";
}

四、总结与作业

总结

1.跨域访问
如何跨域,怎么设置的,环境搭建过程
2.SSM整合(重点)
DAO的SSM、SSM整合测试,事务应用
3.功能的优化
优化细节、分页功能-分页插件、删除

作业

1.完成SSM修改功能