项目是从网上找的,好像一个培训机构的视屏,一个旅游网站
1,项目依赖技术
myBatis------------------------------------------dao 持久层,操作数据库
Oracle--------------------------------------------数据库
spring--------------------------------------------service 业务层
springMVC-----------------------------------------web层
springSecurity------------------------------------权限控制
pageHelper----------------------------------------分页工具
SVN------------------------------------------版本控制(没怎么用,就我自己)
adminLTE------------------------------------------开源的前端模板主题工具(巨好用)
maven
idea
**mvc+xml和注解结合**
2,主要功能
- 商品的增删改查
- 订单的增删改查
- 用户的添加,查询
- 角色的添加,查询
- 权限的添加,查询
- 权限的添加,查询
- 用户关联角色
- 角色关联权限
- AOP日志记录
3,数据库设计
设计到的实体有商品,订单,旅客,会员,用户,角色,权限,日志记录
订单与商品n-1(这里是因为是旅游项目所以一个订单只能有一个旅游路线)
订单与旅客n-m
订单与会员1-n
用户n-角色m-权限q
每个表都用一个随机数作为id,无任何意义,不参数业务逻辑处理,后期有所变动也不会影响
4,搭建环境
(1)创建一个父工程,里面创建不同的子模块
(2)在父工程导入需要用到的依赖,可以根据自己需求添加,将一些核心的包锁定
数据库连接池,这里我用的是c3p0,
可以用阿里的Druid,DruidDataSource
或者spring(org.springframework.jdbc.datasource.DriverManagerDataSource)自带
或者BDCP( BasicDataSourceFactory)
这里我没研究过他们区别我平时用的c3p0和Druid比较多
myBatis相关依赖
spring相关依赖,参考一个博主总结的每个包的作用
https://www.cnblogs.com/zz-1q/p/10350265.html
springMVC依赖
测试依赖
EL表达式
lof4j
Oracle驱动
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.4.0</version>
</dependency>
jdk和Tomcat插件
5,配置文件
mybatis和spring的整合在一起了
applicationContex ======== mybatis主要配置
- 引入外部配置文jdbc的配置
- 扫描包,只扫描到dao层
- 数据源配置(驱动,URL,username,password)
- 配置sqlSession工厂(SqlSessionFactoryBean),在这里面可以
配置实体别名
,和插件,如果使用xml配置文件开发,映射文件和dao接口在同包路径下,不用配置扫描包,在扫描dao.class的时候会同时扫描其同名的xml文件,但是若xml文件和接口不在同路径下需要配置 - 扫描映射(MapperScannerConfigurer),生成代理对象放在容器中
applicationContex ======== spring主要配置
- 扫描包,只扫描service层
- 事务管理器
- 事务通知,在里面配置事务属性,不同类型方法的事务属性不同
- 配置切面,里面定义切入点,并将事务通知注入切入点,切入点一般为service.impl下面的所有方法
- 若使用注解配置事务这里不需要配置3,4,直接开启支持事务注解
<tx:annotation-driven/>
,在要用到事务的类或者方法上添加注解@Transactional
springMVC.xml
- 配置扫描包,只扫描controller
- 开启映射器和适配器的支持
<mvc:annotation-driven />
,之后若自己定义转换器要在这里面加上conversion-service="conversionService"
- 过滤静态资源
- 配置试图解析器
6,业务操作
查询的时候用到一个分页工具
1,导入相关依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
2,在mybatis配置的sqlSession工厂添加插件配置
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.zwp.domain"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<map>
<!--使用哪种数据库语言-->
<entry key="helperDialect" value="oracle"/>
<!--这里合理化配置,当页上当前页为第一页或者
最后一页,你再点击上一页或者下一页不会调转-->
<entry key="reasonable" value="true"/>
</map>
</property>
</bean>
</array>
</property>
</bean>
3,在你需要进行分页的 MyBatis 查询方法前调用PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。
4,PageHelper.提供了一个PageInfo对象,封装了当前页的相关信息,在controller将查询的list封装即可
2,用户关联角色,角色又关联权限,那在这里如何在查询用户的时候同时获取到角色和权限呢
配置在查找用户的同时,通过用户的id查找到相关的角色
在角色查询中配置,在查询角色同时通过id查找到相关权限
user操作
/**
* 根据用户id查找用户
* @param id
* @return
*/
@Select("select *from users where id=#{id}")
@Results(id="userInfoMap",value = {
@Result(id=true,property = "id",column = "id"),
@Result(property = "userName",column = "userName"),
@Result(property = "passWord",column = "passWord"),
@Result(property = "status",column = "status"),
@Result(property = "phoneNum",column = "phoneNum"),
@Result(property = "email",column = "email"),
@Result(property = "roles",column = "id",javaType = List.class,
many = @Many(select = "com.zwp.dao.IRoleDao.findByUserId",fetchType = FetchType.LAZY))
})
UserInfo findById(String id);
role操作
/**
* 根据用户的id查找角色
* @param userId
* @return
*/
@Select("select *from role where id in (select roleId from users_role where userId =#{id})")
@Results(
{
@Result(id=true,property = "id",column = "id"),
@Result(property = "roleName",column = "roleName"),
@Result(property = "roleDesc",column = "roleDesc"),
@Result(property = "permissions",column = "id",
many = @Many(select = "com.zwp.dao.IPermissionDao.findByRoleId",fetchType = FetchType.LAZY)
)
})
List<Role> findByUserId(String userId);
/**
* 根据角色id查找权限信息
* @return
*/
@Select("select *from permission where id in (select permissionId from role_permission where roleId=#{id})")
Permission findByRoleId() throws Exception;
还有一种方式,直接用sql语句查询用户关联的权限,在Oracle数据库中,字段表名等不区分大小写,默认全部为大小,要想区分大小写,加双引号
select permission.* from users
inner join users_role on users.id=users_role.userId
inner join role_permission on users_role.roleId=role_permission.roleId
inner join permission on role_permission.permissionId=permission.id
where users.id=#{id}
3,用户关联角色,角色关联权限,在页面实现给用户添加角色(给角色添加权限,原理相同)
1,首先点击添加添加角色按钮,去数据库查找当前用户不具有的角色,将其返回显示在添加页面,同时还要返回当前用户,要在添加页面放置当前用户的id,一个隐藏input
<button type="button" class="btn bg-olive btn-xs"
οnclick="location.href='${pageContext.request.contextPath}/user/findOtherRole.do?id=${user.id}'"> 添加角色
</button>
2,controller,
返回不具有角色的sql语句
select * from role where id not in
(select roleId from users_role where userId =#{id}
@RequestMapping("/findOtherRole.do")
public ModelAndView findOtherRole(@RequestParam("id") String id) throws Exception {
ModelAndView mv = new ModelAndView();
<!--返回当前用户-->
UserInfo user = userService.findById(id);
<!--返回当前用户不具有的角色-->
List<Role> roleList = userService.findOtherRole(id);
mv.addObject("user", user);
mv.addObject("roleList", roleList);
mv.setViewName("forward:/pages/user_add_role.jsp");
return mv;
}
3,再添加页面以添加复选框展示所有角色信息,同时在表单添加隐藏input,
用户的id提交添加的时候要携带用户的id,和一个角色id的数组,
SpringMVC会自动为我们封装表单里的数据,注意controller接收参数名称与表单对应即可
<form action="${pageContext.request.contextPath}/user/userAddRole.do" method="post">
<input type="hidden" name="userId" value="${user.id }">
<table id="dataList"
class="table table-bordered table-striped table-hover dataTable">
<thead>
<tr>
<th class="" style="padding-right: 0px;"><input
id="selall" type="checkbox" class="icheckbox_square-blue"
</th>
<th class="sorting">角色名称</th>
<th class="sorting">角色描述</th>
</tr>
</thead>
<tbody>
<c:forEach items="${roleList}" var="role">
<tr>
<td>
<input name="ids" type="checkbox" value="${role.id}">
</td>
<td>${role.roleName }</td>
<td>${role.roleDesc}</td>
</tr>
</c:forEach>
</tbody>
</table>
</form>
4,在controller接收用户id和一个角色id的数组
@RequestMapping("/userAddRole.do")
public String userAddRole(@RequestParam("userId") String userId, @RequestParam("ids") String[] ids) throws Exception {
userService.userAddRole(userId, ids);
return "redirect:/user/findAll.do";
}
service对角色id数组循环
@Override
public void userAddRole(String userId, String[] ids) throws Exception {
for (String roleId : ids) {
userDao.userAddRole(userId,roleId);
}
}
dao
/**
* 接收一个userid和一个角色id将角色添加给用户
* @param userId
* @param roleId
*/
@Insert("insert into users_role(userId,roleId) values(#{userId},#{roleId})")
void userAddRole(@Param("userId") String userId, @Param("roleId") String roleId);
这里涉及到给接口传入两个参数的问题,解决方式4种
https://mp.csdn.net/mdeditor/98732846#
4,springSecurity,核心为过滤器
官方文档 https://springcloud.cc/spring-security-zhcn.html
入门总结
https://blog.csdn.net/zwpppppp/article/details/99062289
5,AOP日志记录
https://mp.csdn.net/mdeditor/99062328#