学习 SSM框架 项目总结
原创 已于 2024-10-21 00:20:34 修改 · 粉丝可见 · 1.4k 阅读 · 12 · 11 GEO检测 · 编辑
文章链接:https://blog.csdn.net/hacker_51/article/details/141943989
目录
[TOC]
menus = menuMapper.queryAllMenu(menuVo);
通过指导老师发布的学习SSM框架项目,这次我深刻体会到了SSM整体项目之间的紧连关系。
以下是我自己学习过程中总结出来的经验。
SSM框架 配置
导入核心spring组件坐标
将spring相关组件坐标,导入到 pom 文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency>
|
SSM框架XML配置
随后,将SSM框架配置的XML文件放置在resource资源目录下,
其中配置过程,最好 分层 解耦 的 配置,对应软件设计原则:高内聚低耦合。

通过,我首次配置,无数次报错的经历,学习到了相关配置的标签语句含义,如下:
dao 层(Mapper所在层)的相关配置
1、引入 数据库连接 相关变量 XML
1 2 3 4
| <bean id="placeholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <property name="locations" value="classpath:jdbc.properties"/> </bean>
|
2、引入 数据源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> <property name="initialPoolSize" value="5"/> <property name="maxPoolSize" value="50"/> <property name="minPoolSize" value="10"/> </bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driverClass}"/> <property name="url" value="${jdbc.jdbcUrl}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> <property name="initialSize" value="5"/> <property name="maxActive" value="20"/> <property name="maxWait" value="5000"/> </bean>
|
3、声明 会话工厂 ,引用数据源, 并注入mybatis-config.xml 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations"> <array> <value>classpath:mapper/*/*Mapper.xml</value> </array> </property> </bean>
|
4、扫描 Mapper 接口 所在的包,同时注入 会话工厂
1 2 3 4 5 6 7
| <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.angindem.bus.mapper,com.angindem.sys.mapper,com.angindem.stat.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean>
|
Service层的相关配置
1、使用 <context:component-scan base-package=”path”/> 语句扫描并自动注册对应bean类
1 2 3 4
| <context:component-scan base-package="com.angindem.sys.service.impl"/> <context:component-scan base-package="com.angindem.bus.service.impl"/> <context:component-scan base-package="com.angindem.stat.service.impl"/>
|
2、声明 数据库的事务管理器 bean类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
<tx:advice id="advise"> <tx:attributes> <tx:method name="add*"/> <tx:method name="save*"/> <tx:method name="update*"/> <tx:method name="delete*"/> <tx:method name="change*"/> <tx:method name="reset*"/> <tx:method name="get*" read-only="true"/> <tx:method name="load*" read-only="true"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice>
|
3、编写 AOP 切面声明
1 2 3 4 5 6 7 8 9 10 11
| <aop:config> <aop:pointcut id="pc1" expression="execution(* com.angindem.sys.service.impl.*.*(..))"/> <aop:pointcut id="pc2" expression="execution(* com.angindem.bus.service.impl.*.*(..))"/> <aop:pointcut id="pc3" expression="execution(* com.angindem.stat.service.impl.*.*(..))"/> <aop:advisor advice-ref="advise" pointcut-ref="pc1"/> <aop:advisor advice-ref="advise" pointcut-ref="pc2"/> <aop:advisor advice-ref="advise" pointcut-ref="pc3"/> </aop:config>
|
Context (IOC容器)的配置
1、创建 Spring时进行包扫描并自动注册
1 2
| <context:component-scan base-package="com.angindem.sys,com.angindem.bus,com.angindem.stat"/>
|
2、加载 dao 和 service 的配置
1 2 3
| <import resource="classpath:application-dao.xml"/> <import resource="application-service.xml"/>
|
springmvc 的相关配置
1、扫描并自动注册 Controller
1 2 3 4
| <context:component-scan base-package="com.angindem.sys.controller"/> <context:component-scan base-package="com.angindem.bus.controller"/> <context:component-scan base-package="com.angindem.stat.controller"/>
|
2、配置 映射器和适配器(允许你使用 Spring MVC 的各种注解来简化你的控制器代码,它能够处理使用 @RequestMapping 或其他相关注解的方法)
1 2
| <mvc:annotation-driven />
|
3、配置springmvc中 解析 JSP 的视图解析器
1 2 3 4 5 6
| <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/view/" /> <property name="suffix" value=".jsp" /> </bean>
|
4、配置静态资源文件的放行,例如CSS等
1 2
| <mvc:default-servlet-handler/>
|
5、声明文件上传配置 的bean类
1 2 3 4 5 6 7
| <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8"/> <property name="maxUploadSize" value="20971520"/> </bean>
|
最后mybatis-config相关配置,结合自己的需求,从官网中自行配置即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?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="mapUnderscoreToCamelCase" value="true"/> </settings>
<typeAliases> <package name="com.angindem.domain"/> </typeAliases>
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"/> </plugins>
</configuration>
|
编写习惯风格
项目整体结构
通过不同的功能进行分包,对相同类别合并,做到 高内聚低耦合,各个功能模块内部的功能联系清晰不混乱。

编写实体类
通过编写自身的实体类,其中创建 VO 对象并继承实体类,在 VO对象中创建分页视图所需的变量。


分页组件的使用
通过分页组件,获得分页查询效果。
这行代码使用 PageHelper 类来启动分页查询。 PageHelper 是 MyBatis 分页插件的一个工具类,它通过拦截 SQL 语句来实现物理分页。这里调用 startPage 方法来设置分页参数,其中 menuVo.getPage() 是当前页码, menuVo.getLimit() 是每页显示的记录数。
这行代码调用 menuMapper 的 queryAllMenu 方法来查询所有的菜单数据。 menuMapper 是一个 MyBatis 的 Mapper 接口,用于数据库操作。 queryAllMenu 方法根据传入的 MenuVo 对象进行查询,返回一个 Menu 类型的列表。
这行代码创建了一个新的 DataGridView 对象,并将其返回。 DataGridView 是一个自定义的响应类,用于封装分页数据。构造函数接收两个参数: page.getTotal() (总记录数)和 menus (当前页的数据列表)。

实用编写经验
人机图片验证码
引用Hutool工具坐标
1 2 3 4 5 6
| <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.6.8</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12
| @RequestMapping("getCode") public void getCode(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(116, 36, 4, 5);
session.setAttribute("code",lineCaptcha.getCode());
ServletOutputStream outputStream = response.getOutputStream();
ImageIO.write(lineCaptcha.getImage(),"JPEG",outputStream); }
|
由于将生成的验证码答案放到了 Session 中,所以也要有个对于Web的会话管理工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.angindem.sys.utils;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes;
public class WebUtils { public static ServletRequestAttributes getServletRequestAttributes() { return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); }
public static HttpServletRequest getHttpServletRequest() { return getServletRequestAttributes().getRequest(); }
public static HttpServletResponse getHttpServletResponse() { return getServletRequestAttributes().getResponse(); }
public static HttpSession getHttpSession() { return getHttpServletRequest().getSession(); }
public static String getServletContext() { return getHttpServletRequest().getServletPath(); } }
|
最后访问登录功能的时候,获取验证码进行比较
1 2 3 4 5 6 7 8 9
| @RequestMapping("login") public String login(UserVo userVo, Model model,HttpServletRequest request){
String code = WebUtils.getHttpSession().getAttribute("code").toString();
if(userVo.getCode().equals(code)){ .... } }
|
登录日志文件中的获取 IP
通过用户登录的时候,我们通过在提交的请求中,访问IP存在的数据进行获取,下面是这个工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package com.angindem.sys.utils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import javax.servlet.http.HttpServletRequest;
public class IpUtil { public static String getIpAddress(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } if (StringUtils.isNotEmpty(ip) && ip.contains(",")) { String[] ipArray = ip.split(","); if (ArrayUtils.isNotEmpty(ipArray)) { ip = ipArray[0]; } } return ip; } }
|
最后,直接调用即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| User user = userService.login(userVo); if(user != null){ WebUtils.getHttpSession().setAttribute("user",user); LogInfoVo logInfoVo = new LogInfoVo(); String loginip = IpUtil.getIpAddress(request); String loginname = user.getLoginname(); Date logintime = new Date(); logInfoVo.setLoginip(loginip); logInfoVo.setLoginname(loginname); logInfoVo.setLogintime(logintime); logInfoService.addLogInfo(logInfoVo); return "system/main/index"; }else{ model.addAttribute("error", SysConstant.USER_LOGIN_ERROR_MSG); return "system/main/login"; }
|