首页 / 资讯中心 / 文章详情

IDEA2021搭建SSM源码:从报错到跑通登录的完整指南

IDEA2021搭建SSM源码:从报错到跑通登录的完整指南 ★ FEATURED ARTICLE
简介这份源码资源面向Java Web初学者与需要从零搭建SSM框架的开发者基于IDEA2021环境整合Spring、SpringMVC与MyBatis三大框架配套Tomcat9.0与MySQL8.0.25帮助读者理解传统SSM项目的分层结构与配置流程。压缩包共105个文件约22.34MB其中52个jar包提供框架与数据库驱动依赖28个xml文件承载Spring、MyBatis及Web配置另有java源码、class编译文件、jsp页面与properties配置完整呈现Controller、Service、Dao到实体类的调用链路。目前已有3136人学习下载说明该搭建方案具备一定参考价值。读者可据此获得一套可直接导入运行的工程模板对照配置文件理解依赖注入、事务管理与映射关系并借助Book模块的增删改查示例掌握SSM整合要点适合作为课程设计或入门练手的起步项目。1. 从一堆报错到跑通登录这套 IDEA2021 搭建 SSM 源码到底能帮你省多少事如果你正在搜「ssm框架搭建 idea ssm javaweb java」大概率不是想听 Spring 和 MyBatis 的概念而是手里已经有一个 IDEA 2021 的窗口pom.xml 飘红、Tomcat 起不来、页面 404想找一份能直接对照的完整源码。这套资源就是干这个的它把 Spring SpringMVC MyBatis 从零搭起来包含 Maven 依赖、web.xml、spring 配置文件、MyBatis 映射、Controller 到 JSP 的完整链路最后落到一个能登录、能增删改查的 JavaWeb 工程。适合两类人刚学完 Servlet 想过渡到框架的在校生以及工作里要接手老 SSM 项目、需要快速把环境跑起来的开发者。下面我按「先跑通、再拆结构、最后改功能」的顺序把这份源码拆开讲。2. 环境与工程骨架IDEA2021 下 Maven 目录怎么摆才不飘红2.1 版本组合与依赖坐标SSM 搭建翻车八成不是代码写错而是版本对不上。这套源码用的是 JDK 8 Maven 3.6 Tomcat 9 的组合Spring 5.x 全家桶。为什么不用 JDK 11 或 17因为 Spring 5 的某些反射逻辑在高版本 JDK 上会报InaccessibleObjectException新手排查这个会怀疑人生。常见做法是IDEA 里File → Project Structure把 SDK 锁死 8Maven → Runner的 JRE 也设成 8两处不一致照样出玄学问题。pom.xml 里核心就三块依赖我按源码里的写法拆开!-- Spring 核心IOC 容器 事务 -- dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version5.3.20/version /dependency !-- SpringMVC处理 web 层请求映射 -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.20/version /dependency !-- MyBatis 与 Spring 的粘合包少了它 SqlSessionFactory 注入不进来 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.7/version /dependency参数说明spring-context管 Bean 和事务spring-webmvc管 DispatcherServlet 和注解驱动mybatis-spring是把 MyBatis 的SqlSession交给 Spring 管理的桥。三个版本要跟 Spring 主版本对齐mybatis-spring2.x 对应 Spring 5用 1.x 会报NoClassDefFoundError。数据库驱动按你本地 MySQL 版本选源码里是mysql-connector-java 8.0.29连 5.7 的库也能用只是 URL 要加时区参数。2.2 目录结构与打包方式这份源码是标准 Maven webapp 结构packaging必须是war不是jar否则 Tomcat 找不到入口。目录长这样src/main/java → 按 controller / service / mapper / entity 分包 src/main/resources → spring-dao.xml、spring-service.xml、spring-mvc.xml、mybatis-config.xml src/main/webapp → WEB-INF/web.xml、jsp 页面、static 静态资源webapp/WEB-INF下的web.xml是整个 web 层的入口它负责注册DispatcherServlet和ContextLoaderListener。很多人把spring-mvc.xml和applicationContext.xml混成一个文件结果事务不生效——因为 SpringMVC 容器和 Spring 根容器是父子关系Controller 里注入的 Service 如果没被正确扫描事务注解就是摆设。源码里拆成两个配置文件就是为了避开这个坑。2.3 在 IDEA2021 里跑起来的最小步骤先File → Open选源码根目录等 Maven 索引完。然后配 TomcatRun → Edit Configurations → → Tomcat Server → LocalDeployment里加war explodedApplication context填/ssm。启动前确认web.xml里的contextConfigLocation路径和实际文件名一致差一个字母就是FileNotFoundException。启动后访问http://localhost:8080/ssm/login能出登录页说明 web 层通了登录报 500 再去看控制台的 SQL 日志那是 DAO 层的事。这一步跑通后面拆代码才有意义。3. 核心链路拆解一个登录请求从 Controller 到 MyBatis 的完整走向3.1 web.xml 与两个容器的分工web.xml里最关键的两段配置决定了整个请求的入口和 Bean 的加载顺序!-- 根容器加载 service、dao事务在这里生效 -- context-param param-namecontextConfigLocation/param-name param-valueclasspath:spring-dao.xml,classpath:spring-service.xml/param-value /context-param listener listener-classorg.springframework.web.context.ContextLoaderListener/listener-class /listener !-- MVC 容器只加载 controller负责请求映射 -- servlet servlet-namedispatcher/servlet-name servlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class init-param param-namecontextConfigLocation/param-name param-valueclasspath:spring-mvc.xml/param-value /init-param load-on-startup1/load-on-startup /servlet逻辑说明ContextLoaderListener先启动创建根容器把 Service 和 Mapper 装进去DispatcherServlet后启动创建子容器只扫 Controller。子容器能拿到父容器的 Bean反过来不行。所以spring-mvc.xml里的context:component-scan一定要排除Service和Repository否则事务代理会被重复创建出现「同一个 Service 有两个实例」的怪现象。参数上load-on-startup设 1 是让 DispatcherServlet 随容器启动不设的话第一次请求才初始化调试时容易误判。3.2 Controller 到 Service 的注解链路登录接口的 Controller 写法很典型源码里是这样Controller RequestMapping(/user) public class UserController { Autowired private UserService userService; // 注入的是根容器里的代理对象 RequestMapping(/login) public String login(String username, String password, Model model) { User user userService.login(username, password); if (user null) { model.addAttribute(msg, 账号或密码错误); return login; // 回到登录页 } return redirect:/user/list; // 登录成功跳列表 } }逻辑说明Controller让这个类被 MVC 容器扫描RequestMapping把/user/login映射到方法。参数username、password由 SpringMVC 自动从请求参数绑定不用手动request.getParameter。返回login时走视图解析器拼成/WEB-INF/jsp/login.jsp返回redirect:前缀则走重定向。这里有个细节UserService注入的是接口Spring 默认用 JDK 动态代理生成事务代理类所以 Service 必须写成接口 实现类直接写类会报BeanCreationException。3.3 MyBatis 映射与 SqlSessionFactory 注入DAO 层没有手写SqlSession全靠mybatis-spring的MapperScannerConfigurer自动生成代理!-- spring-dao.xml 片段 -- bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ property namemapperLocations valueclasspath:mapper/*.xml/ property nameconfigLocation valueclasspath:mybatis-config.xml/ /bean !-- 扫描 mapper 接口自动生成实现类 -- bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.ssm.mapper/ /bean逻辑说明SqlSessionFactoryBean把数据源、映射文件、全局配置组装成SqlSessionFactoryMapperScannerConfigurer扫描指定包下的接口运行时用动态代理生成实现接口里只写方法签名SQL 全在mapper/*.xml里。参数mapperLocations的路径要和实际目录一致放在resources/mapper下最省事。mybatis-config.xml里通常只开mapUnderscoreToCamelCase让user_name自动映射到userName不开的话每个字段都要写resultMap改起来很痛苦。3.4 事务配置为什么必须放在 service 层spring-service.xml里的事务配置是整条链路能不能回滚的关键bean idtxManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource/ /bean tx:annotation-driven transaction-managertxManager/逻辑说明DataSourceTransactionManager基于 JDBC 连接做事务管理tx:annotation-driven开启Transactional注解支持。事务要生效切面必须能代理到目标方法而 Controller 在子容器、Service 在根容器所以Transactional只能加在 Service 实现类的方法上。加在 Controller 上不报错但不回滚这是最常见的「事务失效」原因。参数上transaction-manager的名字要和 Bean id 对上写错就是NoSuchBeanDefinitionException。4. 避坑与排查SSM 搭建最容易翻车的 5 个现场4.1 启动报 ClassNotFoundException: ContextLoaderListener现象Tomcat 一启动就抛这个异常工程直接起不来。原因spring-web的 jar 没进WEB-INF/lib多半是 Maven 依赖 scope 写成了provided或者 IDEA 的 Artifact 里没把依赖打进去。解决检查 pom 里spring-web是不是默认 compile 作用域再到Project Structure → Artifacts确认WEB-INF/lib下有这个 jar。用war exploded部署时IDEA 有时不会自动同步依赖手动删掉 Artifact 重新加一次最稳。4.2 页面 404控制台没有任何报错现象Tomcat 起来了访问接口返回 404日志干净得像没事发生。原因spring-mvc.xml的组件扫描包路径写错或者DispatcherServlet的url-pattern配成了/但静态资源被拦截。解决先看spring-mvc.xml里context:component-scan base-package...是否覆盖到 Controller 所在包再确认web.xml里url-pattern是/而不是/*/*会连 JSP 一起拦掉。静态资源要在 MVC 配置里加mvc:default-servlet-handler/否则 css、js 全 404。4.3 登录查询报 Invalid bound statement (not found)现象Service 调用 Mapper 方法时抛这个异常提示找不到映射语句。原因Mapper 接口的方法名和 XML 里的id不一致或者mapperLocations没扫到 XML 文件。解决先核对接口方法名和select id...是否完全一致大小写敏感再看spring-dao.xml里mapperLocations的路径classpath:mapper/*.xml要求 XML 在resources/mapper下。如果 XML 放在java目录里Maven 默认不打包要在 pom 的build里加resources配置把**/*.xml包含进去。4.4 中文参数传到后台变成乱码现象登录时用户名是中文后台收到的是????。原因GET 请求的编码由 Tomcat 的URIEncoding决定POST 请求要靠CharacterEncodingFilter。解决在web.xml里加编码过滤器forceEncoding设 true同时 Tomcat 的server.xml里Connector加URIEncodingUTF-8。源码里过滤器配在 DispatcherServlet 之前顺序错了不生效。数据库连接 URL 也要带useUnicodetruecharacterEncodingutf8三层都对齐才不出乱码。4.5 修改代码后重启才生效现象改了 JSP 或 Java 代码刷新页面没变化必须重启 Tomcat。原因JSP 默认有编译缓存Java 类被 Tomcat 加载后不会自动重载。解决IDEA 的 Tomcat 配置里On Update action选Update classes and resourcesOn frame deactivation也选同一项。JSP 改动一般热生效Java 方法体改动可以热替换但改了方法签名或注解就必须重启。这是开发期的效率问题不是代码 bug别在这上面浪费时间排查。5. 二次开发改造把登录 Demo 扩成带分页和拦截器的业务模块5.1 加一个分页查询的完整改法登录跑通后最自然的下一步是把用户列表改成分页。源码里list是全量查询改造要动四个地方。先在UserMapper接口加方法ListUser selectByPage(Param(offset) int offset, Param(limit) int limit); int countAll();Param注解让 XML 里能用#{offset}直接引用不加的话 MyBatis 按参数顺序找多参数场景容易错位。然后 XML 里写两条 SQLLIMIT #{offset}, #{limit}做物理分页countAll查总数。Service 层算offset (pageNum - 1) * pageSize把pageNum、pageSize、total一起塞进PageResult返回。Controller 接收pageNum参数默认值设 1防止前端不传时报空指针。这套改法不引入 PageHelper 插件依赖最少适合理解分页本质要省事也可以引 PageHelper但版本要和 MyBatis 对齐否则Interceptor注册不上。5.2 用拦截器做登录校验现在任何人不登录直接访问/user/list也能进得加拦截器。新建一个类实现HandlerInterceptorpublic class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user request.getSession().getAttribute(loginUser); if (user null) { response.sendRedirect(request.getContextPath() /user/login); return false; // 中断请求不再走 Controller } return true; // 放行 } }逻辑说明preHandle在 Controller 方法执行前调用返回 false 就中断。登录成功时要把User放进Sessionkey 和拦截器里取的一致。然后在spring-mvc.xml里注册mvc:interceptors mvc:interceptor mvc:mapping path/**/ mvc:exclude-mapping path/user/login/ !-- 登录页放行 -- bean classcom.ssm.interceptor.LoginInterceptor/ /mvc:interceptor /mvc:interceptors参数上exclude-mapping必须放行登录接口和静态资源否则登录页自己都被拦形成死循环。拦截器只拦 Controller不拦 JSP 直接访问所以 JSP 要放在WEB-INF下从物理路径上禁止浏览器直接打开。5.3 改造时怎么验证没改坏每改一层就单独验证一层别等全改完再启动。改完 Mapper 接口和 XML先写个main方法或用单元测试调SqlSession直接跑 SQL确认映射没问题改完 Service在 Controller 里打日志看返回值改完拦截器用无痕窗口访问受保护路径看是否跳登录。我一般会在spring-mvc.xml里临时把mvc:interceptors注释掉对比加与不加的行为差异确认拦截器真的生效而不是碰巧。数据库改动前先mysqldump备份分页 SQL 的LIMIT参数在 MySQL 和 Oracle 上写法不同换库时这里是重灾区。从那以后我每次拿到一份 SSM 源码都强制先只跑登录、再动一行代码确认基线是通的才往下改。这套 IDEA2021 的 SSM 搭建源码价值不在代码多复杂而在于它把「配置怎么串、请求怎么走、事务怎么生效」这条线完整摆出来了照着改一遍比看十篇原理文都管用。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站