SSM整合配置案例

news2024/12/23 9:16:03

一、什么是SSM整合

SSM整合用到两个容器,web容器是root容器的子容器,父子容器关系。

为了方便编写,我们可以三层架构每层对应一个配置类,分别指定两个容器加载

 Ioc如何初始化?

二、简单实现整合SSM

(一)service层实现

    1.数据库准备

    2.pojo包下准备实体类

     3.until包下准备R类,用于接收返回状态码&状态&具体数据

    4.service包下创建ScheduleService

    5.config包下配置service

    6.mapper包下创建ScheduleMapper类

(二)mapper配置实现

    1.准备dataSource

        1.1 resource文件夹下创建jdbc.properties

        1.2  config包下实现DataSourceJavaConfig配置

    2.mapper包下创建ScheduleMapper类

    3. resource文件夹下创建com/example/mapper包存放ScheduleMapper.xml文件

(三) controller层实现

    1.untils包下准备PageBean数据结构用于实现分页功能

    2.service/impl包下创建ScheduleServiceImpl实现ScheduleService的增/删/改/分页查询功能

    3.controller包下ScheduleController实现响应结果

    4.config包下实现WebMvcJavaConfig

(四) 配置IOC

测试


所有代码在gitee可自行下载

SSM整合学习icon-default.png?t=N7T8https://gitee.com/cx293824/ssm-learning.git

一、什么是SSM整合

  • SSM整合用到两个容器,web容器是root容器的子容器,父子容器关系。

容器名盛放组件
web容器web相关组件(controller,springmvc,web等组件)
root容器业务和持久层相关组件(service,aop,tx,dataSource,mybatis,mapper等)
  • 为了方便编写,我们可以三层架构每层对应一个配置类,分别指定两个容器加载

配置名对应内容对应容器
WebJavaConfigcontroller,springmvc相关web容器
ServiceJavaConfigservice,aop,tx相关root容器
MapperJavaConfigmapper,datasource,mybatis相关root容器

  •  Ioc如何初始化?

对于web项目,可以选择web.xml和配置类方式进行ioc配置,相较于xml配置,配置类更简介方便

public class SpringIoCInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    //rootioc容器的配置类
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{DataSourceJavaConfig.class, MapperJavaConfigNew.class,ServiceJavaConfig.class};
    }

    //webioc容器的配置类指定
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebMvcJavaConfig.class};
    }

    //dispatcherServlet的拦截路径
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

二、简单实现整合SSM

(一)service层实现

    1.数据库准备

CREATE TABLE schedule (
  id INT NOT NULL AUTO_INCREMENT,
  title VARCHAR(255) NOT NULL,
  completed BOOLEAN NOT NULL,
  PRIMARY KEY (id)
);

INSERT INTO schedule (title, completed)
VALUES
    ('学习java', true),
    ('学习Python', false),
    ('学习C++', true),
    ('学习JavaScript', false),
    ('学习HTML5', true),
    ('学习CSS3', false),
    ('学习Vue.js', true),
    ('学习React', false),
    ('学习Angular', true),
    ('学习Node.js', false),
    ('学习Express', true),
    ('学习Koa', false),
    ('学习MongoDB', true),
    ('学习MySQL', false),
    ('学习Redis', true),
    ('学习Git', false),
    ('学习Docker', true),
    ('学习Kubernetes', false),
    ('学习AWS', true),
    ('学习Azure', false);

    2.pojo包下准备实体类

@Data
public class Schedule implements Serializable {

    private Integer id;
    @NotBlank
    private String title;
    @NotNull
    private Boolean completed;

    private static final long serialVersionUID = 1L;
}

     3.until包下准备R类,用于接收返回状态码&状态&具体数据

@Data
public class R {

    private int code = 200; //200成功状态码

    private boolean flag = true; //返回状态

    private Object data;  //返回具体数据

    public  static R ok(Object data){
        R r = new R();
        r.data = data;
        return r;
    }

    public static R  fail(Object data){
        R r = new R();
        r.code = 500; //错误码
        r.flag = false; //错误状态
        r.data = data;
        return r;
    }
}

    4.service包下创建ScheduleService

@Service
public interface ScheduleService {

    R page(int pageSize, int currentPage);

    R remove(Integer id);

    R save(Schedule schedule);

    R update(Schedule schedule);
}

    5.config包下配置service

/**
 * description: 业务层配置类: service , aop , tx
 * @author UserName
 *
 * 1.service
 * 2.开启aop注解的支持 aspect : @Before @After @AfterReturning @AfterThrowing @Around  @Aspect @Order
 * 3.tx声明式事务管理: 1.对应的事务管理器实现 [TransactionManager DataSource。。 Hibernate。。 Jpa。。]
 *                   2.开启事务注解支持  @Transactional
 */
@Configuration
@EnableAspectJAutoProxy
@EnableTransactionManagement
@ComponentScan("com.example.service") //advice
public class ServiceJavaConfig {

    @Bean
    public TransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        System.out.println("dataSource = " + dataSource.toString());
        return dataSourceTransactionManager;
    }
}

    6.mapper包下创建ScheduleMapper类

public interface ScheduleMapper{
    List<Schedule> queryList();

    int deleteById(Integer id);

    int insert(Schedule schedule);

    int update(Schedule schedule);
}

(二)mapper配置实现

    1.准备dataSource

        1.1 resource文件夹下创建jdbc.properties
jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/studb
jdbc.driver=com.mysql.cj.jdbc.Driver
        1.2  config包下实现DataSourceJavaConfig配置
@Configuration
@PropertySource("classpath:jdbc.properties")
public class DataSourceJavaConfig {

    @Value("${jdbc.user}")
    private String user;

    @Value("${jdbc.password}")
    private String password;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.driver}")
    private String driver;

    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        return dataSource;
    }
}

    2.mapper包下创建ScheduleMapper类

public interface ScheduleMapper{
    List<Schedule> queryList();

    int deleteById(Integer id);

    int insert(Schedule schedule);

    int update(Schedule schedule);
}

    3. resource文件夹下创建com/example/mapper包存放ScheduleMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 全限定符 -->
<mapper namespace="com.example.mapper.ScheduleMapper">
    <select id="queryList" resultType="schedule">
        select * from schedule
    </select>

    <!--    int deleteById(Integer id);-->
    <delete id="deleteById">
        delete from schedule where id = #{id}
    </delete>

    <insert id="insert" >
        insert into schedule (title,completed) value (#{title},#{completed});
    </insert>

    <update id="update" >
        update schedule set title = #{title} ,completed = #{completed}
        where id = #{id}
    </update>
</mapper>

    4.使用配置类代替xml配置,config包下创建MapperJavaConfig配置mybatis

@Configuration
public class MapperJavaConfigNew {

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){

        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        //指定配置文件等信息
        //指定数据库连接池对象
        sqlSessionFactoryBean.setDataSource(dataSource);

        //指定mybatis配置文件的功能,使用代码的形式
        org.apache.ibatis.session.Configuration configuration
                = new org.apache.ibatis.session.Configuration();
        // <setting name="mapUnderscoreToCamelCase" value="true"/>
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setLogImpl(Slf4jImpl.class);
        configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);

        //org.apache.ibatis.session.Configuration // 存储setting的配置文件
        sqlSessionFactoryBean.setConfiguration(configuration);

        //别名设置
        sqlSessionFactoryBean.setTypeAliasesPackage("com.example.pojo");

        //分页插件
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect","mysql");
        pageInterceptor.setProperties(properties);
        sqlSessionFactoryBean.addPlugins(pageInterceptor);

        return sqlSessionFactoryBean;
    }

    //mapper代理对象加入到ioc
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        // Mapper代理兑现的factoryBean -> 指定一个包 -> mapper接口 -》sqlSessionFactory -> sqlSession -> getMapper -> mapper代理对象 -》 ioc
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.example.mapper"); //mapper接口和mapperxml所在的共同包
        return  mapperScannerConfigurer;
    }

}

(三) controller层实现

    1.untils包下准备PageBean数据结构用于实现分页功能

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean<T> {
    private int currentPage;   // 当前页码
    private int pageSize;      // 每页显示的数据量
    private long total;    // 总数据条数
    private List<T> data;      // 当前页的数据集合
}

    2.service/impl包下创建ScheduleServiceImpl实现ScheduleService的增/删/改/分页查询功能

/**
* @author UserName
* @description 针对表【schedule】的数据库操作Service实现
* @createDate 2024-04-10 22:49:02
*/
@Service
public class ScheduleServiceImpl implements ScheduleService{

    private ScheduleMapper scheduleMapper;

    @Autowired(required = false)
    public ScheduleServiceImpl(ScheduleMapper scheduleMapper) {
        this.scheduleMapper = scheduleMapper;
    }

    @Override
    public R page(int pageSize, int currentPage) {
        //分页
        PageHelper.startPage(currentPage,pageSize); // sql limit x,y;
        //查询
        List<Schedule> scheduleList = scheduleMapper.queryList();
        //把查询到的List放入PageInfo进行分页数据装配
        PageInfo<Schedule> info = new PageInfo<>(scheduleList);

        //再装配入我们设定好的PageBean结构中
        PageBean<Schedule> pageBean = new PageBean<>(currentPage,pageSize,info.getTotal(),info.getList());

        return R.ok(pageBean);
    }

    @Override
    public R remove(Integer id) {

        int rows = scheduleMapper.deleteById(id);

        if (rows > 0){
            return R.ok(null);
        }

        return R.fail(null);
    }

    @Override
    public R save(Schedule schedule) {

        int rows = scheduleMapper.insert(schedule);

        if (rows > 0){
            return R.ok(null);
        }
        return R.fail(null);
    }

    @Override
    public R update(Schedule schedule) {
        //判断id不能为null
        if (schedule.getId() == null) {
            return R.fail("核心参数为null,无法修改!");
        }

        int rows = scheduleMapper.update(schedule);

        if (rows > 0){
            return R.ok(null);
        }

        return R.fail(null);
    }

}

    3.controller包下ScheduleController实现响应结果

@CrossOrigin //解决跨域问题,允许其他源访问我们的controller 浏览器大哥就不拦截了!
@RestController
@RequestMapping(value = "schedule")
@Slf4j
public class ScheduleController {
    private ScheduleService  scheduleService;

    @Autowired
    public ScheduleController(ScheduleService scheduleService) {
        this.scheduleService = scheduleService;
    }

    //接收参数
    //响应结果 springmvc
    @GetMapping("{pageSize}/{currentPage}")
    public R page(@PathVariable int pageSize,
                  @PathVariable int currentPage){

        R r = scheduleService.page(pageSize,currentPage);
        //sl4fj
        log.info("查询的数据为:{}",r);
        return r;
    }


    @DeleteMapping("{id}")
    public R remove(@PathVariable Integer id){
        return scheduleService.remove(id);
    }

    @PostMapping
    public R save(@Validated @RequestBody Schedule schedule, BindingResult result){
        if (result.hasErrors()){
            return R.fail("参数为null,不能保存!");
        }
        return scheduleService.save(schedule);
    }

    @PutMapping
    public R update(@Validated @RequestBody Schedule schedule, BindingResult result){
        if (result.hasErrors()){
            return R.fail("参数为null,不能修改!");
        }
        return scheduleService.update(schedule);
    }
}

    4.config包下实现WebMvcJavaConfig

@EnableWebMvc
@Configuration
@ComponentScan("com.example.controller")
public class WebMvcJavaConfig implements WebMvcConfigurer {
//通过重写这个方法,启用默认Servlet处理器,使得对静态资源的请求能够被容器处理。
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
//配置视图解析器,将逻辑视图名称解析为具体的视图。
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/","jsp");
    }
//添加拦截器,通过这个方法可以配置自定义的拦截器,对请求进行预处理或后处理。
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       // registry.addInterceptor(new xx()).addPathPatterns().excludePathPatterns()
    }
}

(四) 配置IOC

@EnableWebMvc
@Configuration
@ComponentScan("com.example.controller")
public class WebMvcJavaConfig implements WebMvcConfigurer {
//通过重写这个方法,启用默认Servlet处理器,使得对静态资源的请求能够被容器处理。
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
//配置视图解析器,将逻辑视图名称解析为具体的视图。
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/","jsp");
    }
//添加拦截器,通过这个方法可以配置自定义的拦截器,对请求进行预处理或后处理。
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       // registry.addInterceptor(new xx()).addPathPatterns().excludePathPatterns()
    }
}

测试

每页五个数据,第一页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1592399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

是的,本科毕业八年,我考研了

今天&#xff0c;是一篇纯分享文。 是的&#xff0c;本科毕业八年&#xff0c;我考研了。 停更10个月&#xff0c;历时296天&#xff0c;我考研上岸了。 小伙伴们&#xff0c;好久不见。 一 发今年第一篇文章的时候刚处理完后续事宜&#xff0c;就简单说了句&#xff0c;后台…

QThread的学习

锁住该线程直到下面的情况之一出现&#xff1a; (1)和该线程连接的对象已经执行完成&#xff08;例如&#xff1a;当它从run()中返回时&#xff09; 如果该线程已经结束&#xff0c;该函数将返回true。 如果该线程还没有开始&#xff0c;它也返回true。 (2)time毫秒已经过去。如…

Linux 内核学习(2) --- regulator 框架

目录 Regulator 介绍Regulator provider 注册struct regulator_descstruct regualtor_configDTS 配置和解析On BoardConfig 配置regulator_ops总结 Regulator Consumer 使用struct regulator 获取regulator 操作使用Multi Regulator 参考博客 Regulator 介绍 Regulator 指的是…

电子烟特效音语音方案选型-WTN6020-8S-E

随着科技的迅猛进步&#xff0c;电子烟行业亦在持续创新与突破&#xff0c;引领着全新的潮流。其中&#xff0c;电子烟产品所特有的吸烟声音特效播报功能&#xff0c;无疑成为了技术革新的璀璨亮点。这一设计巧妙地将吸烟的声效融入使用体验中&#xff0c;使得用户在吸电子烟时…

Javascript 斐波那契搜索-迭代与递归(Fibonacci Search)

给定一个大小为 n 的排序数组 arr[] 和要在其中搜索的元素 x。如果 x 存在于数组中&#xff0c;则返回 x 的索引&#xff0c;否则返回 -1。 例子&#xff1a; 输入&#xff1a; arr[] {2, 3, 4, 10, 40}, x 10输出&#xff1a; 3 元素 x 出现在索引 3 处。 输入&#xff1…

HarmonyOS开发实例:【app帐号管理】

应用帐号管理 介绍 本示例选择应用进行注册/登录&#xff0c;并设置帐号相关信息&#xff0c;简要说明应用帐号管理相关功能。效果图如下&#xff1a; 效果预览 使用说明参考鸿蒙文档&#xff1a;qr23.cn/AKFP8k点击或者转到。 1.首页面选择想要进入的应用&#xff0c;首次进…

【Redis】持久化

文章目录 一、RDB1.1、RDB的自动备份与手动备份1.1.1、自动备份1.1.2、手动备份 1.2、RDB优点1.3、RDB缺点1.4、RDB快照1.5、RDB优化配置项 二、AOF2.1、AOF工作流程2.2、AOF写回策略2.3、MP-AOF实现2.4、AOF优缺点2.5、AOF重写机制 三、RDBAOF混合持久化3.1、数据恢复顺序和加…

生产环境中秒杀接口并发量剧增与负载优化策略探讨

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 1. 实施限流措施 1.1 令牌桶算法&#xff1a; 1.2 漏…

如何申请阿里云服务器学生优惠,入口在这呢!

阿里云学生服务器免费申请&#xff0c;之前是云翼计划学生服务器9元/月&#xff0c;现在是高校计划&#xff0c;学生服务器可以免费申请&#xff0c;先完成学生认证即可免费领取一台云服务器ECS&#xff0c;配置为2核2G、1M带宽、40G系统盘&#xff0c;在云服务器ECS实例过期之…

什么是队头阻塞以及如何解决

前言 通常我们提到队头阻塞&#xff0c;指的可能是TCP协议中的队头阻塞&#xff0c;但是HTTP1.1中也有一个类似TCP队头阻塞的问题&#xff0c;下面各自介绍一下。 TCP队头阻塞 队头阻塞&#xff08;head-of-line blocking&#xff09;发生在一个TCP分节丢失&#xff0c;导致…

ip地址切换器安卓版,保护隐私,自由上网

在移动互联网时代&#xff0c;随着智能手机和平板电脑的普及&#xff0c;移动设备的网络连接变得愈发重要。为了满足用户在不同网络环境下的需求&#xff0c;IP地址切换器安卓版应运而生。本文将以虎观代理为例&#xff0c;为您详细解析IP地址切换器安卓版的功能、应用以及其所…

26、链表-环形链表II

思路&#xff1a; 这道题就是判断链表中是否有环&#xff0c;首先使用集合肯定可以快速地解决&#xff0c;比如通过一个set集合遍历&#xff0c;如果遍历过程中有节点在set中已经存在那么说明存在环。返回这个节点即可 第二种方式就是通过快慢指针方式寻找环。如何做呢&#xf…

震惊!借助Coze白嫖GPT4-128k解决方案

震惊!某大佬借助Coze白嫖GPT4-128k解决方案 前言 此文章介绍如何免费使用GPT-4高级模型并拓展API功能 最近的 Coze 在国内开放了&#xff0c;可以免费使用大模型。但是和国外的有点区别&#xff0c;国外版本使用的chatgpt4&#xff0c;国内版本使用的是语雀大模型。 Coze是一…

《前端防坑》- JS基础 - 你觉得typeof nullValue === null 么?

问题 JS原始类型有6种Undefined, Null, Number, String, Boolean, Symbol共6种。 在对原始类型使用typeof进行判断时, typeof stringValue string typeof numberValue number 如果一个变量(nullValue)的值为null&#xff0c;那么typeof nullValue "?" const u …

图书推荐:用ChatGPT获取在线被动收入的8个方法

Universe S. The ChatGPT Money Mastery. Unlocking Online Income..for Dummies 2023 想要彻底革新您的收入模式吗&#xff1f;《用ChatGPT获取在线被动收入的8个方法》一书是您不可错过的指南。 在这个数字化飞速发展的时代&#xff0c;人工智能成为了开启成功之门的钥匙。…

2024年广东省网络系统管理样题第1套网络搭建部分

2024年广东省职业院校技能大赛样题1 信息安全管理与评估 网络系统管理 网络搭建与应用 云计算 软件测试 移动应用开发 任务书&#xff0c;赛题&#xff0c;解析等资料&#xff0c;知识点培训服务 添加博主wx&#xff1a;liuliu5488233 网络系统管理赛项 模块A&#xff1a;网络…

操作系统(第四周 第二堂)

目录 回顾 进程运行 进程的创建 进程的工作 举例 进程的删除 举例1&#xff08;走到return 0结束&#xff09; 举例2&#xff08;利用exit&#xff08;1&#xff09;结束&#xff09; 进程通信 共享内存 生产者算法 消费者算法 消息传递 定义 算法实现 总结 回顾…

数据结构--链式队列

一.链式队列的设计思想: 首先一定要理解设计的初衷,就是队头队尾的位置要满足怎么快怎么设计.那么分析如下: 最终我们敲定了入队,出队的时间复杂度都为O(1)的一种设计,也就是第四种设计;当然,头节点的数据域不使用,所以我们设计链式队列的头节点的时候删除数据域即可,链式队列…

了解虚拟路由器冗余协议(VRRP)

虚拟路由器冗余协议&#xff08;VRRP&#xff09;是一种被广泛使用的网络协议&#xff0c;旨在增强网络的可靠性和可用性。对于网络管理员和工程师来说&#xff0c;了解VRRP是确保网络能够实现无缝故障转移和保持不间断连接的关键。本文将深入探讨VRRP的基础知识&#xff0c;包…

ZooKeeper分布式服务与Kafka消息队列+ELKF整合方案

前言 ZooKeeper 是一个分布式的、开放源码的分布式应用程序协调服务&#xff0c;提供配置维护、命名服务、分布式同步、组服务等功能&#xff1b; Kafka 是一个开源的分布式流处理平台&#xff0c;它被设计用来处理实时数据流&#xff0c;包括发布和订阅消息系统、日志收集以…