框架技术----SpringMVC【SSM整合】

springMVC

javaWeb—SSM中最后控制层MVC框架


SSM整合开发


昨天已经分享了返回值,还有@ResponstBody注解的数据可以直接输出到响应体;这里需要加上annotation-driven来避免和静态资源的resources、default-servlet-handler冲突;路径问题之前分析过,一般情况下,能用/就一定要用/;不加会变化

如果是jsp页面,为了可以使用/,这个时候可以使用EL表达式,{pageContext.request.cocntextPath}; 之前使用servlet来写html代码的时候也是使用的request.getContextPath

昨天提到过,为了更方便的使用MVC解析资源,一般建立一个静态的目录static,将所有的静态资源放在下面,但是这样子就出现问题了,这里如果不加/,参考路径就会变成……/static/html

为了避免这些问题,如果是jsp页面,就可以使用EL表达式,如果是html,就可以使用base标签

base标签

base是html中的标签,因为前端一般使用的是不加/的方式,这个时候会自动以项目根路径的或者其他的作为参考路径,【欢迎页面比较特殊,因为地址栏不会显示完整的static/html/index.html;而是直接显示8080/MVCtest/ ----> 因此这里的参考路径就是最后一个/之前的 带上根路径;所以这里只是静态资源访问出现问题,如果是其他的html界面则还需要注意参考路径会变成static/html —>这个时候就要注意使用base】base就是表示当前页面访问地址的基地址。==页面中所有的不加/的地址,都是base指定的地址为参考地址,使用base中的地址 + 所写的地址,构成绝对地址

<!DOCTYPE html>
<html>
<head>
    <!-- 为了能够正常访问动态资源,这里base设置到项目的根,和不加/的地址简单拼凑,所以要加上末尾加/ -->
    <base href="http://localhost:8080/MVCtest/"/>
    <meta charset="UTF-8">
    <title>cfengOA.助力</title>
    <script type="text/javascript" src="static/js/JQuery1.8.js"></script>

如果使用jsp还可以使用request内置对象动态得到地址

<% 
	String basePath = request.getScheme() + "://" + request.getServerName + ":" + request.getServerPort() + request.getContentPath + "/";
%>

<html>
    <head>
        <base href=<%= basePath %>/>
    </head>
</html>

SSM整合开发

SSM也就是springMVC + spring + mybatis; SSH是springMVC + spring + hiberna;都差不多,除了基础的SSM,还有封装更复杂的SpringBoot;之后会提及这个框架。其实SSM整合的本质只是将spring整合入spring就可,SpringMVC就是spring;就多了一个配置文件而已;并且就是普通的spring配置文件;SSM再三层架构中分管不同的角色,SpringMVC主要是做控制层管理,Spring则是负责创建对象,当然SpringMVC就是Spring;主要就是使用的Spring中的@Controller注解,而普通的对象使用的是@Component进行创建,Spring主要的作用就是IOC和AOP; 而Mybatis是做持久层的操作,连接数据库

用户发起请求给SpringMVC接收 ----> spring中的service对象------>Mybatis处理数据

整合中出现了两个容器,一个是SpringMVC的容器,代替之前Tomcat的容器的作用;第二个是Spring的容器,就是service等对象存储的容器,使用的是全局监听器创建;把使用的对象交给合适的容器管理;SpringMVC容器是spring容器的子容器,使用一个spring主配置文件可以将所有的子容器整合为一个大的容器

springmvc容器就是spring容器的子容器,类似java中的继承,子可以访问父的内容

SSM整合实例

还是用一个小的实例来查看这个SSM整合的过程;这里还是使用学生表,就是cfengbase中的表student

mysql> SELECT * FROM student;
+-------+---------+----------+
| stuno | stuname | stuclass |
+-------+---------+----------+
|     1 | 张三    | HC2001   |
|     2 | 李四    | HC2002   |
|     3 | Cfeng   | HC2002   |
|     4 | 王五    | HC2001   |
|     6 | Jning   | HC2001   |
|     7 | 里斯    | HC2003   |
|     8 | 卡夫卡  | HC2004   |
|    10 | 里仁    | HC2004   |
|    11 | 小欢    | HC2006   |
|    12 | 黄某    | HC2001   |
|    13 | 奥利    | HC2002   |
|    14 | 新亚    | HC2003   |
+-------+---------+----------+
12 rows in set (0.04 sec)

maven建立一个web项目,导入依赖

mvc: 导入springMVC的依赖【会自动导入spring-context和spring-web】,加入servlet和jsp依赖,jackson依赖—jackson-core,jackson-bind

spring : 加入javax-annotatation-api依赖,druid依赖【连接池,整合mybatis】,spring-sapects【aop】,spring-tx,spring-jdbc【事务】

mybatis : 加入mybatis依赖,mysql驱动,mybatis-spring【整合】,pagehelper【分页】

junit依赖

以后开发差不多就是这些依赖,这里就将依赖都导入

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- springMVC的依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.14</version>
    </dependency><!--jsp的依赖,不需要tomcat了 -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>
    <!--加入servlet依赖,(servlet的jar包) 不需要再配置tomcat了 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <!-- 加入jackson的依赖,数据转为json格式,包括core和datablind -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.13.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.1</version>
    </dependency>
    <!-- 添加mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.9</version>
    </dependency>
    <!--添加mysql依赖 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.27</version>
    </dependency>
    <!-- 加入pageHelper依赖-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.3.0</version>
    </dependency>
    <!-- 加入AspectJ依赖,方便实现AOP -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.3.13</version>
    </dependency>
    <!--spring transaction -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.3.14</version>
    </dependency>
    <!-- Spring jdbc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.14</version>
    </dependency>
    <!-- mybatis 和spring集成-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.6</version>
    </dependency>
    <!-- 德鲁伊druid连接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.8</version>
    </dependency>
  </dependencies>

可以看到要完整开发项目,需要使用的jar包非常多,并且这些jar包各自还依赖其他的jar包,programmer自己管理非常复杂,所以maven真的减少了很多的复杂的工作

还有为了保证mapper文件正常加载到target/classes下,需要加入资源插件

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
      <!-- 还要配置上原来编译资源的路径-->
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.*</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>

web.xml编写

  1. 注册DispatcherServlet : 创建springmvc容器对象,才能创建controller对象,创建的是servlet:才能接收用户的请求
  2. 注册spring容器的监听器,ContextLoaderListener, 创建Spring容器对象,才能创建service、dao等对象
  3. 注册字符过滤器CharacterEncodingFilter,【都是spring-web提供的】,解决post请求乱码的问题,创建放在mvc容器之前
<?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">

    <!-- 注册字符过滤器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 需要将参数设置: 编码方式,强制转换请求和响应 -->
        <init-param>
            <param-name>fileEncoding</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>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 注册中央调度器 -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:conf/dispatcherServlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 注册监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 指定监听器扫描的spring配置文件的位置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:conf/applicationContext.xml</param-value>
    </context-param>

    <welcome-file-list>
        <welcome-file>static/html/index.html</welcome-file>
    </welcome-file-list>
</web-app>

中央调度器中需要注意init-param标签需要再load-on-startup之前,不然会出现一些问题,因为load是表明创建对象的时机的,一般放在最后面

创建包 — controller、service、dao、entity等

项目架构最重要的就是各司其职,所以各个不同功能的包要创建好

这里就简单将包创建好就可以,需要注意的是最好不要和其他模块的包冲突,这里就修改一下artificial就可以

编写springmvc、spring、mybatis的配置文件

springmvc、spring中主要就是要保证注解开发的正常进行,还有spring的配置文件要保证事务的正常进行,也要注册事务管理器等

配置文件直接全部放在resource下面会显得非常杂乱,所以这里就再建立一个conf目录,将资源放在conf目录下 < param-value>classpath:conf/dispatcherServlet.xml< /param-value>

  1. springMVC的配置文件编写是最简单的,【简单4个部分】需要一个组件扫描器识别@Controller —component-scan;再一个就是视图解析器用于解析处理器方法的视图 — 一个InternalResourceViewResolver对象bean创建;还有一个就是处理静态资源的,一般使用resources,因为不依赖Tomcat
<?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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="Jning.controller"/>

    <!-- 声明springmvc中的视图解析器,帮助开发人员设置视图文件的路径 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 和注解ResponseBodu配合使用,内部将对象转为json格式 -->
    <mvc:annotation-driven/>

    <!-- 解决静态资源覆盖问题,注册defaultServletHandler -->
<!--    <mvc:default-servlet-handler/>-->
    <!-- 这里是后台路径,所以加上/,会带上根路径 location表示的是目录位置; mapping代表的是访问的url地址 -->
    <mvc:resources mapping="/static/**" location="/static/"/>
</beans>

这里的组件扫描器的base-package就是controller即可,因为只是创建控制层的对象

视图解析器是为了方便书写视图路径,prefix和suffix分别制定视图的前缀和后缀,这样返回String的是时候只需要写逻辑名称

annotation-driven: 注解驱动,为了配合@ResourceBody;还有就是进行静态资源解析的时候避免冲突

还有就是静态资源解析的resources;或者使用default-servlet也可以,但是需要依赖tomcat服务器,是一个请求转发的过程

  1. 编写Mybatis主配置文件,这里将数据库剥离到druid中之后,mybatis的主配置文件的内容也就很少,必要的就3个部分,一个是设置环境,settings用来设置日志,第二个就是typaAilas设置别名,这样mapper文件中可以使用别名,别名就是类名;一般是实体类,最后一个最重要的就是mapper文件,和设置别名是类似的,也是使用package进行指定
<?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>
    <!-- 配置日志信息,设置环境 -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!-- 设置别名,下面直接用包,不用一个一个用mapper指定,一般都是视实体类所在的包 -->
    <typeAliases>
        <package name="Jning.entity"/>
    </typeAliases>

    <!-- 以后的环境都是用druid了 -->

    <!-- 设置映射文件的位置,这里和设置别名是类似的,这里直接指定包名就好了,一般就是dao包,因为mapper文件和接口放在一起,名称相同 -->
    <mappers>
        <!--        <mapper resource="cfeng\dao\StudentDao.xml"/>  直接按照包导入就可-->
        <package name="Jning\dao"/>
    </mappers>
</configuration>

注意:这里因为标签是用的/结尾,所以这里使用\; 这里的写法有两种,推荐使用上面的.的方式,下面的\必须要使用反斜杠

  1. 编写Spring配置文件,这里就有很多个部分,首先就是整合mybatis需要创建3个对象,datasource、sqlSessionFactory、dao
<?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">

    <!-- spring 整合mybatis : 声明数据源对象,sqlSessionFactory对象,Dao对象 -->
    <!-- 数据源对象,声明init和destroy的method代表的是创建和销毁连接池的方法,使用druid,其中要使用数据库的配置文件-->
    <context:property-placeholder location="classpath:conf/db.properties"/>

    <bean id="myDatasource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="password" value="${jdbc.password}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="maxActive" value="20"/>
    </bean>
    <!-- mybatis-spring为了整合提供的sqlSessionFactory对象,这里类型是加上Bean,创建sqlSession需要配置文件和datasource
         因为之前是所有的都在mybatis主配置文件中,但是现在将数据库的信息,也就是environment交给了druid;对象的属性注入
    -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="myDatasource"/>
        <property name="configLocation" value="classpath:conf/mybatis.xml"/>
    </bean>

    <!-- 整合mybatis还需要的就是dao对象,这里使用的是扫描器对象,扫描mapper文件的,所以名称就是mapperScanner,
          使用package为包扫描包下面所有的mapper文件,注意这是扫描配置文件,所以是configurer,不是bean
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="Jning.dao"/>
    </bean>

    <!-- 接下来就是声明组件扫描器,扫描service包下的对象注解,创建对象 -->
    <context:component-scan base-package="Jning.service"/>

    <!-- 完成spring的事务, 需要有事务的管理器,mybatis的是datasource,如果使用注解的方式,要用driven,如果使用aop的AspectJ也行 -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 某个特定数据库的事务 -->
        <property name="dataSource" ref="myDatasource"/>
    </bean>

    <!-- 如果使用注解就加入annotation-driven即可,指定扫描器;如果使用AspectJ,需要使用tx的advice指明通知method;可以通配
          同时配置aop中的config,用来引入通知并且配置切入点表达式;因为上面的通知只有方法名,没有具体指明位置,这样advice才有效
     -->

</beans>

这里的配置就要复杂一些了,事务可以简单使用注解,也可以使用AdpectJ,只是aspectJ需要tx的advice和aop的config来完成一个具体的通知

编写code、dao的结构和mapper文件等

这里就是要完成业务代码需要做的最主要的部分;前面就类似于就是一个项目的完整的结构,写代码这部分才是完成业务操作,就编写dao接口和mapper文件,同时编写service接口和实现类就可以了

这里是单表的查询非常简单

  • dao接口
package Jning.dao;

import Jning.entity.Student;

import java.util.List;

public interface StudentDao {

    public List<Student> selectAllStudents();

    public int insertStudent(Student student);
}
  • dao的mapper文件
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="Jning.dao.StudentDao">
    <select id="selectAllStudents" resultType="student">
        SELECT stuno,stuname,stuclass FROM student ORDER BY stuno DESC
    </select>

    <insert id="insertStudent">
        INSERT INTO student (stuname,stuclass) VALUES (#{stuname},#{stuclass})
    </insert>
</mapper>
  • 编写业务类的接口,命名就是之前业务的说明的类型
package Jning.service;

import Jning.entity.Student;

import java.util.List;

public interface StudentService {

    public List<Student> queryStudents();

    public int addStudent(Student student);
}
  • 编写业务接口的实现类
package Jning.service.impl;

import Jning.dao.StudentDao;
import Jning.entity.Student;
import Jning.service.StudentService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 这里需要创建业务类的对象,所以就直接使用@Service,不使用Component了
 * 使用Resource进行自动注入
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Resource  //这里首先byName,寻找同名
    private StudentDao studentDao;

    @Override
    public List<Student> queryStudents() {
        return studentDao.selectAllStudents();
    }

    @Override
    public int addStudent(Student student) {
        return studentDao.insertStudent(student);
    }
}
  • 编写控制器类型,这里只用一个就可以了
package Jning.controller;

import Jning.entity.Student;
import Jning.service.StudentService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.List;

@Controller
@RequestMapping(value = "/student")
public class StudentAction {

    @Resource //自动byName注入
    private StudentService studentService;

    @RequestMapping(value = "/addStudent",method = RequestMethod.POST)
    public ModelAndView addStudent(Student student){
        //定义处理结果返回对象
        ModelAndView mv = new ModelAndView();
       //调用service处理业务
        String msg = "注册失败";
        int num = studentService.addStudent(student);
        if(num > 0){
            msg = "学生【" + student.getStuname() + "】注册成功";
        }
        mv.addObject("msg",msg);
        mv.setViewName("result");
        return mv;
    }

    //使用ajax展示学生列表
    @RequestMapping(value = "/queryStudent",method = RequestMethod.GET)
    @ResponseBody
    public List<Student> listStudent() {
        //调用业务方法获取返回值
        List<Student> list = studentService.queryStudents();
        //annotation-driven直接自动调用jackson转为json
        //注解过的对象直接返回给响应体
        return list;
    }
}

编写jsp等view界面

这里就简单编写一个jsp结果页面,需要注意的是,可能因为IDEA的不稳定问题,这里的过滤器有的时候会感觉不起作用,还有的时候将界面给乱码了,这个时候可以删除之后再次建立就可以成功进行了,并没有声明什么特殊的问题

//首先是一个index.html界面,ajax直接定义就可

<!DOCTYPE html>
<html>
<head>
    <!-- 为了能够正常访问动态资源,这里base设置到项目的根,和不加/的地址简单拼凑,所以要加上末尾加/ -->
    <base href="http://localhost:8080/MVCtest/"/>
    <meta charset="UTF-8">
    <title>cfengOA.助力</title>
    <script type="text/javascript" src="static/js/JQuery1.8.js"></script>
    <script type="text/javascript">
        $(function() {
            //点击按钮,按钮绑定一个ajax请求
            $("#mybtn").click(function() {
                $.ajax({
                    dataType: 'json',
                    url: 'student/queryStudent',
                    success: function (resp) {
                        var list = "<table><tr><th>学生学号</th><th>学生姓名</th><th>学生班级</th></tr>"
                        for(var i = 0; i < resp.length; i++) {
                            var student = resp[i];
                            list += "<tr><td>" + student.stuno + "</d>";
                            list += "<td>" + student.stuname + "</d>";
                            list += "<td>" +student.stuclass + "</d></tr>";
                        }
                        $("#mydiv")[0].innerHTML = list;
                    }
                })
            });
        })
    </script>
</head>
<body>
<h1 align="center">OA学生信息系统</h1>
<hr color="pink"/>
    <a href="static/html/addStudent.html">添加学生</a><br/><br/><br/>
    <input type="button" id="mybtn" value="查看学生列表"/><br/><br/><br/>
    <div id="mydiv" style="font-size: large;color: aquamarine">学生列表信息……</div>
</body>
</html>

这里是简单使用js来进行的动态操作,其实这可以换成表的形式然后使用JQuery动态操作

$.ajax({
          dataType: 'json',
          url: 'student/queryStudent',
          success: function (resp) {
              $("#mytable").empty(); //删除所有的子对象
              $("#mytable").append("<table><tr><th>学生学号</th><th>学生姓名</th><th>学生班级</th></tr>");
              $.each(resp,function(index,student){
              $("#mytable").append("<tr>").append("<td>").append(student.stuno).append("</td>")
              .append("<td>").append(student.stuname).append("</td>")
              .append("<td>").append(student.stuclass).append("</td>").append("</tr>")
           }); //添加子标签
         }
     })
 });

<table id="mytable" bgcolor="aquamarine" bordercolor="pink"></table>

这样一个简单的SSM流程就开发完成了,简单来说,框架真的简化了很多东西,特别是数据库的连接部分,还有service和controller的DI和AOP等都很方便

这里要加入业务也很简单,使用AspectJ框架即可,使用annotation-driven和一个aop的config就可以完成操作

 <!-- 完成spring的事务, 需要有事务的管理器,mybatis的是datasource,如果使用注解的方式,要用driven,如果使用aop的AspectJ也行 -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 某个特定数据库的事务 -->
        <property name="dataSource" ref="myDatasource"/>
    </bean>

    <!-- 如果使用注解就加入annotation-driven即可,指定扫描器;如果使用AspectJ,需要使用tx的advice指明通知method;可以通配
          同时配置aop中的config,用来引入通知并且配置切入点表达式;因为上面的通知只有方法名,没有具体指明位置,这样advice才有效
     -->
    <!-- id自定义,表示配置内容-->
    <tx:advice id="myadvise"  transaction-manager="dataSourceTransactionManager">
        <tx:attributes> <!--表示要配置的事务的属性 method是作用的方法,切入点 -->
            <tx:method name="add*"  propagation="REQUIRED" isolation="DEFAULT"
                       rollback-for="java.lang.NullPointerException"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置aop -->
    <aop:config>
        <!-- 配置切入点表达式,指出哪些类需要应用事务  id 切入点表达式的名称   切入点表达式:指出切入点表达式-->
        <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>

        <!-- 配置增强器: 关联pointcut和上面的advisce -->
        <aop:advisor advice-ref="myadvise" pointcut-ref="servicePt"/>
    </aop:config>

这里就是为添加操作给加入了事务,这样添加学生的时候查看控制台的日志

Transaction synchronization committing SqlSession  ---> 成功添加学生,提交事务

SpringMVC将之前的servlet的请i去转发和重定向的操作都进行了封装,可以使用更加简单的方式实现重定向和请求转发。 forward表示转发,实现执行的forword;redirect表示重定向,实现之前的response.sendRedirect();

需要注意的是: 对于请求转发的页面,可以是WEB-INF的页面,因为是浏览器来进行调用,而重定向的页面是不能使WEB-INF下面的,因为重定向可以看作是用户再次发了一次请求; 但是两者的共同点就是都是不和视图解析器一起工作

MVC请求转发和重定向【避免视图解析】

请求转发

处理器方法返回ModelAndView的时候,需要在setViewName中指定视图前面添加forward,这个时候的视图不再会使用视图解析器,这样就可以指定不同的视图,不再遵循视图解析器的规则;视图页面里是后台路径,也就是相对于项目的根路径,forward操作不需要视图解析器

这里来实现这个测试请求转发,首先前端页面简单编写一个表单

方法返回值为modelAndView的时候实现请求转发 
<br><br>
    方法返回值为modelAndView的时候实现请求转发
    <form action="/test/some.do" method="post">
        用户名<input type="text" name="user"/><br>
        年龄<input type="text" name="age"/><br>
        <input type="submit" value="注册"/>
    </form>

这里返回值是ModelAndView的时候才能使用请求转发,因为ModelAndView的底层就是进行请求转发,但是只是没有指明而已,要使用请求转发,只用在setViewName里加上forward和视图完整路径就可以 【不管资源在哪里都行,WEB-INF】

//格式
mv.setViewName("forward:视图完整路径")

不和视图解析器一同工作,就相当于项目中没有视图解析器

package Jning.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value ="/test")
public class RedirctTest {

    @RequestMapping(value ="/some.do",method = RequestMethod.POST)
    public ModelAndView doSome(String user,int age) {
        System.out.println(user + ": " + age);
        ModelAndView mv = new ModelAndView();
        mv.setViewName("forward:/test.html");
        return mv;
    }
}

视图解析器解析的都是WEB-INF/view下面的jsp文件,这里想要访问不再这里的文件,就只能使用forward: 这是一种显式转发,可以帮助转发到任意的位置【但是和之前的servlet的相同,浏览器的地址还是最开始访问的地址就是some.do,并且不能跨项目重定向】

重定向

重定向也和请求转发相同处理视图的路径的,也是可以让视图解析失效,这里使用的格式和上面的相同显式表达就可以了

mv.setViewName("redirect:XXX")

重定向的问题和之前的servlet的问题都是相同的:

  1. 注意重定向相当于时用户发了多次请求,重定向的地址栏路径就是最终访问的路径,需要注意的是因为HTTP协议是无状态的,所以之前的请求域中的数据是不能正常传递的,这个时候要继续传递数据,只能能够拼URL的规则,将数据通过类似GET的形式传递参数
  2. 重定向是不能访问WEB-INF下面的数据的,因为这不是服务器内部转发,而是在浏览器外面进行转发,所以不能访问服务器内部资源
package Jning.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value ="/test")
public class RedirctTest {

    @RequestMapping(value ="/some.do")
    public ModelAndView doSome(String user,int age) {
        System.out.println(user + ": " + age);
        ModelAndView mv = new ModelAndView();
        mv.setViewName("redirect:/test.html");
        return mv;
    }
}

这里和上面的结果是相同的,需要注意的是,这里相当于是两个请求,所以不能使用请求域中的数据🎄

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值