持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情 完整项目会在末尾附上gitee链接
SSM 项目基础环境搭建
本实验将完成 SSM 整合的第一部分即完成 SSM 项目的基础环境搭建工作。本次实验项目采用三层架构 + MVC 设计模式进行搭建。实验中采用如下技术栈:
- Spring
- SpringMVC
- MyBatis Plus 第三方插件
- Druid 数据源
- Apache IO 组件
- Log4j 日志框架
- JSR-303 验证框架
- MySQL 数据库
- JSP
- jQuery
知识点
- 基本环境搭建流程
- 配置文件关联关系
第一步:新建·文件
第二步:导入依赖
按技术栈要求在 pom.xml 导入完整 SSM 的依赖,包括 mybatis plus,springmvc,jackson ,commons-io,hibernate-validator。
编写空白 applicationContext.xml
。。
<!--引入其它配置文件到spring框架 由spring框架统一管理-->
<import resource="spring-mybatis.xml"/>
<import resource="spring-mvc.xml"/>
<!--<import resource="spring-shiro.xml"/>-->
<!--整合事务-->
<bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
</bean>
<!--事务配置增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManger">
<tx:attributes>
<!--propagation事务的传播特性,required没有事务就创建一个 有就加入-->
<!--<tx:method name="select*" read-only="true"></tx:method>-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--aop配置-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* org.yamiya.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
编写 springmvc.xml,配置项目所需的基本配置,并在其中通过 import 引用 applicationContext.xml
。。
<context:component-scan base-package="org.yamiya.controller"/>
<!-- 适配器和映射器 -->
<mvc:annotation-driven conversion-service="myconverter"/>
<!-- 日期转换器 -->
<bean id="myconverter" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="org.yamiya.util.MyDateConverter"/>
</set>
</property>
</bean>
<mvc:resources mapping="/static/**" location="/static/"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
第六步 编写日志和数据库连接信息的 properties 配置文件
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
username = 你的用户名
password = 你的密码
第七步 编写测试类并测试(Spring 整合持久层)
这里为了方便,我们先完成全查功能。书写对应的数据库,并且照数据库字段,书写pojo里面的实体类,Book.Java,在Java下mapper里面的BookMapper书写接口方法,并且在resource同名路径的BookMapper.Xml下进行《select》配置,书写service,此处我们同样一个接口,一个类(需要使用到BookMapper。Java对象,使用对象调用方法),书写controller new一个ModeAndView对象,配置一个service对象,把service调用方法返回值传入modeandview对象。最后通过modeandview的setViewName(“路径“)跳转到我们的查询界面。书写查询界面: 通过${}获取传入的值;此处需要循环,即我们var代表循环体内对象 items谁被循环 varstaus 变量状态,主要是编号
<c:forEach var="b" items="${blist}" varStatus="vs">
<tr>
<td>${vs.count}</td>
,,,,
注意:这里我们获取时间会出现问题,需要使用类型转换才能变成我们熟悉的
<td>
<fmt:formatDate value="${b.chubantime}" pattern="yyyy-MM-dd HH:mm:ss"/>
</td>
到这里,项目环境搭建完成
前端代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--<%@taglib prefix="c"% uri="http://java.sun.com/jstl/core_rt"%>--%>
<%@taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
<html>
<head>
<title>Title</title>
</head>
<%--工程名 webapp--%>
<link rel="stylesheet" href="${pageContext.request.contextPath}/static/bootstrap3.3.7/css/bootstrap.css">
<body>
<table class="table table-bordered table-hover">
<tr>
<%-- 无法访问情况 (全路径也是) web-inf受保护,不能直接访问 <a class="checkbox" href="add.jsp">添加 </a>--%>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/add">添加 </a>
<%-- </td>--%>
</tr>
<tr>
<td>编号: </td>
<td>书名: </td>>
<td>作者: </td>
<td>出版社:</td>
<td>时间: </td>
<td>操作: </td>
</tr>
<%-- var代表循环体内对象 items谁被循环 varstaus 变量状态,主要是编号--%>
<c:forEach var="b" items="${p.list}" varStatus="vs">
<tr>
<td>${vs.count}</td>
<td>${b.uname}</td>>
<td>${b.auther}</td>
<td>${b.chubanshe}</td>
<%-- <td>${b.chubantime}</td>--%>
<td>
<fmt:formatDate value="${b.chubantime}" pattern="yyyy-MM-dd HH:mm:ss"/>
</td>
<td>
<a class="btn btn-success" href="bookbyid?id=${b.id}"> 修改</a>
<a class="btn btn-info" href="deleteBook?id=${b.id}"> 删除</a>
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
可以发现,这里我有一些样式。
关于怎么有样式:
这里我们使用 bootstrap,具体百度改关键词,然后在前端界面通过link引入样式,之后就能在元素里面通过一些关键语句添加样式。
怎么添加数据
整合的基础上,我们对mapper进行方法添加,和insert标签书写,然后在service里面通过mapper对象调用方法返回值,最后在controlle获取值,通过ifelse完成跳转。
然后书写我们add界面
在query跳转到add不能直接写
在web编程规范中,WEB-INF文件夹下面的内容不能直接通过文件的全路径进行访问,是受保护的。所以一般我们也会把我们的页面为了安全起见,放在我们的WEB-INF文件夹中。需要借助control,页面通用跳转
// 页面通用
@RequestMapping("{page}")
public String toPage(@PathVariable()String page){
return page;
}
注意:add这个时候我们不能跳转,会报错400
出现400的错误码
原因:我们从前端页面上获取的参数实质上都是String类型
我们数据库中的使用类型叫做datatime类型 我在java中封装的数据模型的时间类型是java.util.Date类型。Mybatis在做数据转换的时候,是先把数据库中的datatime类型转为java.sql.Date类型,由于java.sql.Date是java.util.Date的子类,所以可以无风险的向上转型,所以我们查询的时候,不会有异常。但是添加的时候,从前端获取的数据都是字符串,没法转换成java.util.Date的类型,所以会出现400的错误码。
删除数据
删除最简单
不过分逻辑删除和物理删除。物理删除是真实删除,但是在生活里面很少使用,逻辑删除就比如我进行了一个购物订单,那么数据库里面订单字段有,订单编号,商品编号,用户编号,用户姓名,收货人信息(很多不列举),状态码。
其中对于逻辑删除来说,状态码最重要:
比如:我们可以约定
状态码-1:表示下单了,没有付款
2:下单了付款了,没有发货
3:已经发货
4:退款订单
5:删除订单
我们在前端看到的页面就是数据库操作当状态码等于xx的时候的值,具体在mapperxml里面完成
搜先在bookmapper。Java里面写一个
然后去mapperxml写
然后在service里面书写接口和实现类,实现了所有mapper对象调用删除方法
然后去controller写相关方法!
最后在query。Jsp页面的删除按钮那边加上地址。
修改
修改分两步,第一步点击修改,回显当前id的内容,第二步进行修改回到全查界面
第一步:
点击某一个然后修改,类似查询全部,不过把全部改成一个,具体如截图 bookmapper.java
bookmapper.xml
bookservice
bookSeviceimpl
bookController
update.jsp
第二步:修改 按照同样的bookmapper,bookservice,bookconteoller方法进行修改的填写
修改之前:
修改之后:
登录
只有账号密码在数据库类名,才能登录,登录成功才能进行book操作。
分析:登录如何验证?其实相当于在前端页面输入,然后去数据库类名查询有没有对应当前账号密码的行,如果有,表示可以登录,如果没有,表示账号密码没找到。 所以先书写查询一个的例子。具体步骤参考book。 mapper。xml
<mapper namespace="org.yamiya.mapper.UserMappre">
<select id="loginUser" resultType="userinfo">
select * from userinfo where uname=#{uname} and upwd=#{upwd}
</select>
</mapper>
controller如下:
先自动注入我们需要的的service接口对象
@Autowired
private UserService userService;
然后在登录逻辑类中通过该对象调用方法赋值,并且把值传入ModelANdView对象然后通过对象跳转网页。 到这里简单的通过登录,去到book全查页面完成。
那么开始第二个问题,只有登录才能查询到book,并且进行操作。
就需要我们引入一个过滤器
Servlet、listenner、Filter被称为web的三大核心组件。
拦截器其实就是filter,主要的功能是过滤url。
在ssm框架中,我们会使用Filter的子接口。功能更为强大。
首先,在spring-mvc下:
按照路径建立相关文件。
如何过滤?
首先实现 HandlerInterceptor接口,重写接口里面的preHandle方法
通过获取页面url,uri得到我们的路径,然后通过查询路径是否包含我们目的界面,如果包括,就返回true即不拦截,如果吧包括,就进行拦截
web系统的4个作用域
Application:全局作用域,作用范围在整个项目,项目一旦看是运行,该作用域就存在,项目停止运行后,该作用域消失。
Request:请求作用域,作为范围是在发生请求后,请求结束后,该作用域消失。
Session:会话作用域,作用范围是产生会话后,会话结束后,该作用域消失。或者session失效了,该作用域也会消失。
Page:当前页面作用域,只针对当前页面有效。
如何判定用户是否为登录状态?
我们会根据session里面的用户信息进行判断,如果为null,则证明是非登录状态,进行相关跳转
到这里基本的登录后才能查看完成了。
我们知道数据库一般很多数据,如何实现分页操作?
为什么分页:分页的好处缓解了数据库的压力以及网络传输的压力
如果数据量比较大的情况,我们全查所有信息,需要等的时间就比较久。
用户体验不好,另外如果数据量较大,你的网络传输时间比较长,一旦出现网络波动或者数据丢包的情况,数据就不能完整显示
即:在mybatis-config加入分页插件
修改bookservice类名的全查 PageInfo<Book> selectAll(int pageNum,int pageSize);
并且对应写出全查的实现
并且在jquery里面书写分页器
结果如下
完整代码如下:gitee.com/dingxianliu…