您现在的位置是:首页 >学无止境 >做SSM项目的步骤和优化网站首页学无止境

做SSM项目的步骤和优化

鲨鱼辣椒_TUT 2023-06-07 20:00:03
简介做SSM项目的步骤和优化

SSM框架整合

这里说的SSM整合,主要说的是Spring和mybatis之间的整合。因为spring和springMVC都是spring生态系统中的框架,所以spring和springMVC之间的整合是无缝的整合,即,我们在不知不觉中,其实spring和springMVC已经整合好了,不用你做什么额外的事情了。但是mybatis是第三方的框架,所以我们要手动把spring和mybatis进行整合。

原始整合,即,我们每一层之前怎么学的(mybatis管理dao层,springMVC管理view层),这里就怎么直接用。但是原始整合,你会发现这种整合中,spring和mybatis的整合度不是很高。所以我们之后会解决这些问题,这些问题解决了,SSM框架的整合就已经OK了。这里,我们先学原始的整合方式,然后我们解决原始整合方式存在的问题,解决完了,我们本节“SSM框架整合”的学习就结束了。

原始整合方式

原始整合方式,就是我们直接用SSM框架来做web项目,所以整合的步骤:无。即,你想怎么写这个项目,就怎么写,该用框架的时候就直接用框架来写代码就行了。

没有整合的步骤,那我们来看看我们平常写项目的步骤就行了,平常写项目的步骤做完了,原始整合就结束了。

下面用一个例子来做演示:

步骤:

  1. 编写数据库和表

    建库如下:

    在这里插入图片描述

    建表如下:

    在这里插入图片描述

  2. 创建maven项目,并且创建maven工程可能需要的包。反正就是把项目的结构搭好。

    在这里插入图片描述

  3. 导入项目可能需要用到的架包

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>org.itcast</groupId>
      <artifactId>ssm</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <dependencies>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.7</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>5.0.5.RELEASE</version>
        </dependency>
    
        <!--servlet和jsp-->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.0</version>
        </dependency>
    
        <!--mybatis相关的架包-->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.4.5</version>
        </dependency>
        <!--这个mybatis-spring是我们之后优化整合的时候会用,原始整合不用。-->
    <!--    <dependency>-->
    <!--      <groupId>org.mybatis</groupId>-->
    <!--      <artifactId>mybatis-spring</artifactId>-->
    <!--      <version>1.3.1</version>-->
    <!--    </dependency>-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.6</version>
        </dependency>
        <dependency>
          <groupId>c3p0</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.1.2</version>
        </dependency>
    
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>jstl</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
              <!--source 和 target根据个人需要自己修改-->
              <source>11</source>
              <target>11</target>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    
  4. 编写实体类

    实体类如下:

    package com.itcast.domain;
    
    public class Account {
        //建议写Integer,而不是写int
        private Integer id;
        private String name;
        private Double money;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Double getMoney() {
            return money;
        }
    
        public void setMoney(Double money) {
            this.money = money;
        }
    }
    

    注意点:

    实体类用定义属性的时候,建议包装类型来定义。理由如下:

    在这里插入图片描述

  5. 编写Mapper接口和可能会用到的方法

    package com.itcast.mapper;
    
    import com.itcast.domain.Account;
    import java.util.List;
    
    public interface AccountMapper {
        public void save(Account account);
        public List<Account> findAll();
    }
    
    
  6. 编写Service层的接口和可能会用到的方法

    package com.itcast.service;
    
    import com.itcast.domain.Account;
    import java.util.List;
    
    public interface AccountService {
        public void save(Account account);
        public List<Account> findAll();
    }
    
  7. 编写Service层的接口实现类和实现方法

    package com.itcast.service.impl;
    
    import com.itcast.domain.Account;
    import com.itcast.service.AccountService;
    import java.util.List;
    
    public class AccountServiceImpl implements AccountService {
        @Override
        public void save(Account account) {
    
        }
    
        @Override
        public List<Account> findAll() {
            return null;
        }
    }
    

    service实现类的具体实现,我们先空着,之后写。

    在这里插入图片描述

  8. 编写Controller

    这里我们具体实现也先空着。先把框架搭好。

    在这里插入图片描述

  9. 编写前端的页面

    在这里插入图片描述

    在这里插入图片描述

    注意:

    因为WEB-INF下的资源是受保护的,所以我们不能直接访问到。我们放在WEB-INF文件夹外的资源,我们可以浏览器输入地址直接访问。但是在WEB-INF文件夹内的资源,我们只能通过controller的转发机制访问。

  10. 编写配置文件(这些配置文件的结构先搭好,里面具体写什么得用得时候才知道,所以我们先空着)

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  11. 补齐配置文件中的配置:

    AccountMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.itcast.mapper.AccountMapper">
        <insert id="save" parameterType="account">
            insert into account value(#{id},#{name},#{money})
        </insert>
        <select id="findAll" resultType="Account">
            select * from account
        </select>
    </mapper>
    

    applicationContext.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:tx="http://www.springframework.org/schema/tx"
           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 http://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 http://www.springframework.org/schema/aop/spring-aop.xsd
    ">
        <!--组件扫描 -->
        <context:component-scan base-package="com.itcast">
            <!--我们扫这个com.itcast包,那么com.itcast包下的@Controller注解也会被扫描到,但是这个@Controller注解的类一般是表示层的类,所以我们到时候应该让他被springmvc来管理的,所以我们这里spring就不去控制它了,我们就需要这个@Controller注解给排除掉去,到时候让springmvc的配置文件来扫描-->
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    </beans>
    

    jdbc.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/ssm
    jdbc.username=root
    jdbc.password=815924
    

    log4j.properties

    ### direct log messages to stdout ###
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target=System.out
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
    
    ### direct messages to file mylog.log ###
    #log4j.appender.file=org.apache.log4j.FileAppender
    #log4j.appender.file.File=hibernate.log
    #log4j.appender.file.layout=org.apache.log4j.PatternLayout
    #log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
    
    ### set log levels - for more verbose logging change 'info' to 'debug' ###
    
    log4j.rootLogger=all, stdout
    

    spring-mvc.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: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 http://www.springframework.org/schema/context/spring-context.xsd
                                http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!--组件扫描,主要扫描@Controller注解-->
        <context:component-scan base-package="com.itcast.controller" use-default-filters="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    
        <!--配置mvc注解驱动-->
        <mvc:annotation-driven/>
    
        <!--配置内部资源视图解析器-->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    
        <!--开放静态资源访问-->
        <mvc:default-servlet-handler/>
    </beans>
    

    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文件-->
        <properties resource="jdbc.properties"></properties>
    
        <!--定义别名-->
        <typeAliases>
            <!--<typeAlias type="com.itcast.domain.Account" alias="account"></typeAlias>-->
            <!--上面这种定义别名的方式是,把这个com.itcast.domain.Account定义一个别名,别名叫account-->
            <!--下面我们介绍另一种定义别名的方式,扫描包的方式。比如下面这样写的话,我们这个com.itcast.domain包下所有的类都将会被设置别名。设置什么别名,看例子:比如,我们这个com.itcast.domain包下有一个Account类和User类,那么,你用了下面这个扫描包的这个方式,就相当于给这个com.itcast.domain包下的Account类设置了account和Account两个别名。给com.itcast.domain包下的User类设置了User和user两个别名-->
            <package name="com.itcast.domain"></package>
        </typeAliases>
    
        <!--数据源环境-->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"></transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
    
        <!--加载映射文件-->
        <mappers>
            <!--<mapper resource="comitcastmapperAccountMapper.xml"/>-->
            <!--上面这个加载映射文件的方式是一个个加载的,所以,要想加载多个映射文件,你得写多个mapper标签。下面,我们来介绍另一种写法,包引入方式,我们在“mybatis-day1.md”中的mappers标签里面讲过,但是使用这种方式有一些注意点,你看之前“mybatis-day1.md”中的mappers标签的笔记就行. -->
            <package name="com.itcast.mapper"/>
        </mappers>
    </configuration>
    
  12. 完成逻辑代码的编写

    package com.itcast.controller;
    
    import com.itcast.domain.Account;
    import com.itcast.service.AccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;
    
    import java.util.List;
    
    @Controller
    @RequestMapping("/account")
    public class AccountController {
        @Autowired
        private AccountService accountService;
        //保存(实际中,我们保存成功应该会跳转到一个列表页面的,这里我们简单点,就直接在页面打印一个字符串意思一下。)
        @RequestMapping("/save")
        @ResponseBody
        public String save(Account account){
            accountService.save(account);
            return "保存成功!";
        }
    
        //查询。查询结束我们返回一个数据,并且返回一个视图。
        public ModelAndView findAll(){
            List<Account> accountList=accountService.findAll();
            ModelAndView modelAndView=new ModelAndView();
            modelAndView.addObject("accountList",accountList);
            modelAndView.setViewName("accountList");
            return modelAndView;
        }
    }
    
    
    package com.itcast.service.impl;
    
    
    import com.itcast.domain.Account;
    import com.itcast.mapper.AccountMapper;
    import com.itcast.service.AccountService;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.springframework.stereotype.Service;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    @Service("accountService")
    public class AccountServiceImpl implements AccountService {
        @Override
        public void save(Account account) {
            try {
                InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
                SqlSession sqlSession = sqlSessionFactory.openSession();
                AccountMapper mapper = sqlSession.getMapper(AccountMapper.class);
                mapper.save(account);
                sqlSession.commit();
                sqlSession.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public List<Account> findAll() {
            try {
                InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
                SqlSession sqlSession = sqlSessionFactory.openSession();
                AccountMapper mapper = sqlSession.getMapper(AccountMapper.class);
                List<Account> accountList = mapper.findAll();
                sqlSession.close();
                return accountList;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
  13. 测试

    在这里插入图片描述

    结果:

    在这里插入图片描述

    数据库:

    在这里插入图片描述

    发现,页面显示的时候出现了乱码,但是数据库里面存数据的时候是正确的。

    分析:

    数据库能正确存数据的原因是:我们在web.xml中设置了乱码过滤器,所以服务器获取前端代码的数据的乱码问题解决了,即,我们前端输入了中文的数据,后端正确获取到了中文数据,没有出现乱码,然后存到数据库里面,所以数据库里面存的是正确的。

    那么前端出现乱码的原因是什么呢?你看我们之前没用ssm的时候,我们都直接在servlet的代码块的后半段设置response.setContentType(“text/html;charset=utf-8”)。这样前端页面就不会出现乱码了,这里我们ssm要达到这个效果,我们也得设置一下响应的编码。

    解决方法如下:

    在这里插入图片描述

    测试:

    在这里插入图片描述

    点击"保存"后:

    在这里插入图片描述

    数据库数据如下:

    在这里插入图片描述

  14. 下面我们来完成保存的方法。之前1~13步中,没有把save()方法和他跳转的页面完成,下面我们来把他们完成。

    在这里插入图片描述

    在这里插入图片描述

  15. 测试:

    在这里插入图片描述

原始整合方式的弊端

弊端:

你看上面这里service层中,每次执行某个方法的时候都会执行下面这些语句,即,都会加载配置文件、创建工厂对象、创建Session对象、事务提交、关闭sql会话等。

在这里插入图片描述

解决:

把创建Session工厂的工作、创建AccountMapper对象的工作都交给spring容器来做。并且把事务控制也交给spring来做。

在这里插入图片描述

即,我们要做到让spring创建这个AccountMapper,并且注入到这个AccountServiceImpl的某个AccountMapper类型的成员变量里面,然后这个AccountServiceImpl类里面的所有方法都可以用那个成员变量了,这个类里面也不用创建对象,因为创建对象和绑定到AccountServiceImpl的成员变量的工作都交给spring容器了。

然后我们在spring核心配置文件里面给这个AccountServiceImpl类里面的方法配置上事务控制,这样,那些被设置了事务控制的方法会在执行成功的时候自动提交,执行失败的时候自动回滚了,就取代了我们上面的sqlSessioni.commit()和sqlSessioni.close()了。其实上面这个例子里面,出现异常回滚的代码都没有写,我们通过spring核心配置文件给AccountServiceImpl类里面的方法配置上事务控制,那些方法执行出现异常,就会自动回滚了,也相当于补齐了上面例子中没有写的回滚的功能。

具体怎么整合看下面。

优化后的整合

我们先在spring核心配置文件中加一些配置做到让spring来创建工厂和AccountMapper对象。

在这里插入图片描述

注意:上面这个工厂类是mybatis-spring包下的,所以我们要把之前注释掉的mybatis和spring整合需要用到的架包给解开。

在这里插入图片描述

然后我们就可以把mybatis核心配置文件中那些被移到spring核心配置文件中来配置的东西给删了

删除前:

在这里插入图片描述

删除后:

在这里插入图片描述

修改AccountServiceImpl。

在这里插入图片描述

上面是完成了让spring帮我们创建AccountMapper对象。下面我们来把声明式事务控制做了,这样优化后的SSM整合就ok了。

添加事务控制如下:

在这里插入图片描述

测试:

数据库之前数据:

在这里插入图片描述

输入:

在这里插入图片描述

点击保存后:

在这里插入图片描述

数据库数据:

在这里插入图片描述

输入http://localhost:8080/ssm_war_exploded/account/findAll,显示的结果如下

在这里插入图片描述

OK,整合完成,并且测试通过。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。