SSM 小demo的盲点总结
日期Date和String之间的转换:
1. 全局转换器(推荐使用)
1. 创建类实现Converter接口,实现Convert方法
public class StringToDateConvert implements Converter<String, Date> {
@Override
public Date convert(String resource) {
if(resource == null){
throw new RuntimeException("请输入值");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
try {
Date parse = df.parse(resource);
return parse;
} catch (ParseException e) {
throw new RuntimeException("数据格式转换异常");
}
}
}
2. 在SpringMVC的配置文件中进行配置转换器
<!--配置自定义日期转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.wzlove.utils.StringToDateConvert"/>
</set>
</property>
</bean>
<!--开启MVC注解驱动(加载处理器映射器和处理器适配器)-->
<mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>
2. 属性转换器
使用注解进行转换:
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private Date departureTime;
对于日期在页面的展示(get方法需要注意)
对于日期在页面上的展示考虑使用字符串,多创建一个String属性,在前台展示的时候使用这个字符串属性,记得转换类型就好.
实体类:
private Date departureTime;
private String departureTimeStr;
public String getDepartureTimeStr() {
if(departureTime != null){
departureTimeStr = DateFromatUtils.date2String(departureTime,"yyyy-MM-dd HH:mm");
}
return departureTimeStr;
}
DateFromatUtils:
public class DateFromatUtils {
/**
* 日期转时间
* @param date
* @param patt
* @return
*/
public static String date2String(Date date, String patt){
SimpleDateFormat sdf = new SimpleDateFormat(patt);
String format = sdf.format(date);
return format;
}
/**
* 字符串转日期
* @param time
* @param patt
* @return
*/
public static Date string2Date(String time, String patt){
SimpleDateFormat sdf = new SimpleDateFormat(patt);
try {
Date date = sdf.parse(time);
return date;
} catch (ParseException e) {
e.printStackTrace();
throw new RuntimeException("日期转换异常");
}
}
}
对于特殊的标记属性在页面的展示(get方法需要注意)
与日期类似,创建额外表示的字段
/**
* 状态 0 关闭 1 开启
*/
private Integer productStatus;
/**
* 对状态的字符串描述
*/
private String productStatusStr;
public String getProductStatusStr() {
if(null != productStatus){
if(productStatus == 0){
productStatusStr = "关闭";
} else if(productStatus == 1){
productStatusStr = "开启";
}
}
return productStatusStr;
}
Mybatis的一对一和多对多的回顾:
一对一:
@Select("select * from orders")
@Results({
@Result(id = true,property = "id", column = "ID"),
@Result(property = "orderNum",column = "ORDERNUM"),
@Result(property = "orderTime",column = "ORDERTIME"),
@Result(property = "orderStatus",column = "ORDERSTATUS"),
@Result(property = "peopleCount",column = "PEOPLECOUNT"),
@Result(property = "payType",column = "PAYTYPE"),
@Result(property = "orderDesc",column = "ORDERDESC"),
@Result(property = "product",column = "PRODUCTID",javaType = Product.class,
one = @One(select = "cn.wzlove.mapper.ProductMapper.findProductById"))
})
多对多:
@Select("select * from orders where id = #{ordersId}")
@Results({
@Result(id = true,property = "id", column = "ID"),
@Result(property = "orderNum",column = "ORDERNUM"),
@Result(property = "orderTime",column = "ORDERTIME"),
@Result(property = "orderStatus",column = "ORDERSTATUS"),
@Result(property = "peopleCount",column = "PEOPLECOUNT"),
@Result(property = "payType",column = "PAYTYPE"),
@Result(property = "orderDesc",column = "ORDERDESC"),
@Result(property = "product",column = "PRODUCTID",javaType = Product.class,
one = @One(select = "cn.wzlove.mapper.ProductMapper.findProductById")),
@Result(property = "member",column = "MEMBERID",javaType = Member.class,
one = @One(select = "cn.wzlove.mapper.MemberMapper.findMemberById")),
@Result(property = "travellers",column = "id",javaType = java.util.List.class,
many = @Many(select = "cn.wzlove.mapper.TravellerMapper.findTravelByOrderId"))
})
PageHelper的使用:
1. 导入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
2. 进行配置
<!--配置sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="cn.wzlove.domain"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">oracle</prop>
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
3. 进行使用
@RequestMapping("findAll.do")
public ModelAndView findOrdersAll(@RequestParam(name = "page",required = true,defaultValue = "1") Integer page,
@RequestParam(name = "size",required = true,defaultValue = "4") Integer size){
ModelAndView mv = new ModelAndView();
PageHelper.startPage(page,size);
List<Orders> allOrders = ordersService.findAllOrders();
PageInfo<Orders> pageInfo = new PageInfo<>(allOrders);
mv.addObject("pageInfo",pageInfo);
mv.setViewName("orders-list");
return mv;
}
4. 对于PageInfo考虑查看源码看看封装的分页信息,列出常用的
//当前页
private int pageNum;
//每页的数量
private int pageSize;
//当前页的数量
private int size;
//由于startRow和endRow不常用,这里说个具体的用法
//可以在页面中"显示startRow到endRow 共size条数据"
//当前页面第一个元素在数据库中的行号
private int startRow;
//当前页面最后一个元素在数据库中的行号
private int endRow;
//总记录数
private long total;
//总页数
private int pages;
//结果集
private List<T> list;
//前一页
private int prePage;
//下一页
private int nextPage;
权限的管理(Srping security的使用)
1. Srping security的使用: 安全框架(认证和授权)
1. 导入依赖
spring-security-web
spring-security-config
2. web.xml配置过滤器
ContextLoaderListener----------> 加载spring-Security.xml的配置文件
DelegatingFilterProxt----------> 委托过滤器代理类-----> springSecurityFilterChain(名字不能变)
3. spring-security核心配置文件的配置
1. 哪些资源不登录也能访问,也就是过滤
<security:http pattern="" security="none" >
2. 认证管理器
<security:authentication-manager>
3. 配置拦截规则
<security:http auto-config="true" use-expressions="false">
代码如下:
2. web.xml的配置:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<!--
classpath和classpath*的区别
前者表示当前工程的类路径下加载配置文件
后者表示从当前工程的类路径及jar包的类路径下加载
-->
<param-value>
classpath*:applicationContext.xml,
classpath*:spring-security.xml
</param-value>
</context-param>
3. spring-security.xml的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 配置不拦截的资源 -->
<security:http pattern="/login.jsp" security="none"/>
<security:http pattern="/failer.jsp" security="none"/>
<security:http pattern="/css/**" security="none"/>
<security:http pattern="/img/**" security="none"/>
<security:http pattern="/plugins/**" security="none"/>
<!--
配置具体的规则
auto-config="true" 不用自己编写登录的页面,框架提供默认登录页面
use-expressions="false" 是否使用SPEL表达式(没学习过)
-->
<!-- 配置具体的拦截的规则 pattern="请求路径的规则" access="访问系统的人,必须有ROLE_USER的角色" -->
<security:http auto-config="true" use-expressions="false">
<security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>
<!-- 定义跳转的具体的页面 -->
<security:form-login
login-page="/login.jsp"
login-processing-url="/login"
default-target-url="/index.jsp"
authentication-failure-url="/failer.jsp"
authentication-success-forward-url="/pages/main.jsp"
/>
<!-- 关闭跨域请求 -->
<security:csrf disabled="true"/>
<!-- 退出 -->
<security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp" />
</security:http>
<!-- 切换成数据库中的用户名和密码 -->
<security:authentication-manager>
<security:authentication-provider user-service-ref="userService">
<!-- 配置加密的方式(开始的时候由于密码没有加密,所以将这个应该先注释掉,等到密码加密了再放开) -->
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<!-- 配置加密类 -->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!-- 提供了入门的方式,在内存中存入用户名和密码
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
-->
<!--如果密码没有加密,则密码前需要添加{noop}-->
</beans>
Spring Security的权限控制
服务器的权限控制
1. JSR250注解配置
1. 在pom.xml中引入依赖
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
2. 在spring-security.xml的配置文件中开启注解开关
<security:global-method-security jsr250-annotations="enabled"></security:global-method-security>
3. 在方法上使用注解(一般在Controller注解上)
@RolesAllowed({"ADMIN","USER"}) ====> 必须有ADMIN或者USER角色才可以访问此方法
@PermitAll ====> 允许所有的角色都可以访问
@DenyAll ====> 所有的角色都不可以访问
2. 使用@Secured注解
1. 在spring-security.xml的配置文件中开启注解开关
<security:global-method-security secured-annotations="enabled"></security:global-method-security>
2. 使用注解
@Secured("ROLE_ADMIN") ====> 拥有ADMIN角色的用户可以访问,必须要有ROLE_
3. 基于表达式的
1. 在配置文件中开启注解开关
<security:global-method-security pre-post-annotations="enabled" ></security:global-method-security>
2. @PreAuthorize("hasRole('ROLE_ADMIN')") ====> 如果表达式返回true,可以访问该方法,由于使用了spel表达式,所以配置文件需要更改(在原来的基础上,修改use-expressions和access):
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>
@PreAuthorize("authentication.principal.username == 'wzlove'")表示只有wzlove用户可以访问
前端的权限控制
1. 在pom.xml中引入依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
2. 在jsp页面引入标签库:
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
3. 标签的使用:
1. 获取当前登录的用户名
<security:authentication property="principal.username"/>
2. 根据权限隐藏标签(拥有ADMIN角色才可以显示该标签)
<security:authorize access="hasRole('ADMIN')">
<li id="system-setting"><a
href="${pageContext.request.contextPath}/user/findAll"> <i
class="fa fa-circle-o"></i> 用户管理
</a></li>
</security:authorize>
SpringAOP的日志记录控制(把数据存放在数据库中)
1. 创建数据库的表结构:
CREATE TABLE sysLog(
id VARCHAR2(32) default SYS_GUID() PRIMARY KEY,
visitTime timestamp,
username VARCHAR2(50),
ip VARCHAR2(30),
url VARCHAR2(50),
executionTime int,
method VARCHAR2(200)
)
2. 创建日志实体:
public class SysLog {
/**
* 主键uuid
*/
private String id;
/**
* 访问时间
*/
private Date visitTime;
/**
* 访问时间前台展示
*/
private String visitTimeStr;
/**
* 操作者
*/
private String username;
/**
* 操作者ip
*/
private String ip;
/**
* 操作的URL
*/
private String url;
/**
* 执行的时长
*/
private Long executionTime;
/**
* 访问方法
*/
private String method;
setter和getter
}
4. 创建mapper:
@Mapper
public interface SysLogMapper {
@Insert("insert into syslog(visitTime,username,ip,url,executionTime,method) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
void saveSysLog(SysLog sysLog);
@Select("select * from syslog")
List<SysLog> findAll();
}
5. AOP控制:
@Component
@Aspect
public class LogAop {
@Autowired
private HttpServletRequest request;
@Autowired
private SysLogService sysLogService;
@Around("execution(* cn.wzlove.controller.*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object proceed = null;
// 访问方法(分别获取类和方法,然后进行拼接)
String className = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
// 忽略日志本身的Controller
if("cn.wzlove.controller.SysLogController".equals(className)){
// 获取参数
Object[] args = pjp.getArgs();
// 执行原始方法(放行)
proceed = pjp.proceed(args);
} else{
// 封装SysLog,获取SysLog的属性
// 访问时间
Date visitDate = new Date();
// 操作者
String loginName = SecurityContextHolder.getContext().getAuthentication().getName();
// 操作者ip
String remoteAddr = request.getRemoteAddr();
// 操作的URL
String requestURI = request.getRequestURI();
// 执行时长
Long startTime = System.currentTimeMillis();
// 获取参数
Object[] args = pjp.getArgs();
// 执行原始方法(放行)
proceed = pjp.proceed(args);
// 结束时间
Long endTime = System.currentTimeMillis();
Long executeTime = endTime - startTime;
// 封装SysLog
SysLog sysLog = new SysLog();
sysLog.setIp(remoteAddr);
sysLog.setExecutionTime(executeTime);
sysLog.setMethod(className+"."+methodName);
sysLog.setUsername(loginName);
sysLog.setVisitTime(visitDate);
sysLog.setUrl(requestURI);
// 进行插入操作
sysLogService.saveSysLog(sysLog);
}
return proceed;
}
}
6. 日志的Controller
@Controller
@RequestMapping("sysLog")
public class SysLogController {
@Autowired
private SysLogService sysLogService;
@RequestMapping("findAll")
public ModelAndView findAll(){
ModelAndView mv = new ModelAndView();
List<SysLog> all = sysLogService.findAll();
mv.addObject("sysLogs",all);
mv.setViewName("syslog-list");
return mv;
}
}
SSM 小demo的盲点总结的更多相关文章
- SpringMVC小demo解析
第一次实际接触SpringMVC,之前在教程网站上看得是概念性的. SpringMVC是属于Java框架SSM中的一环 在做了一个小demo后发现原来编程如此简单. 首先建立动态网页项目(Dynami ...
- 快速搭建一个SSM框架demo
我之所以写一个快速搭建的demo,主要想做一些容器的demo,所以为了方便大家,所以一切从简,简单的3层架构 先用mysql的ddl,后期不上oracle的ddl ; -- ------------- ...
- 新手 gulp+ seajs 小demo
首先,不说废话,它的介绍和作者就不在多说了,网上一百度一大堆: 我在这里只是来写写我这2天抽空对seajs的了解并爬过的坑,和实现的一个小demo(纯属为了实现,高手请绕道); 一.环境工具及安装 1 ...
- Nancy之基于Nancy.Hosting.Self的小Demo
继昨天的Nancy之基于Nancy.Hosting.Aspnet的小Demo后, 今天来做个基于Nancy.Hosting.Self的小Demo. 关于Self Hosting Nancy,官方文档的 ...
- Nancy之基于Nancy.Owin的小Demo
前面做了基于Nancy.Hosting.Aspnet和Nancy.Hosting.Self的小Demo 今天我们来做个基于Nancy.Owin的小Demo 开始之前我们来说说什么是Owin和Katan ...
- Nancy之基于Self Hosting的补充小Demo
前面把Hosting Nancy with ASP.NET.Self Hosting Nancy和Hosting Nancy with OWIN 以demo的形式简单描述了一下. 这篇是为Self H ...
- [Unity3D]做个小Demo学习Input.touches
[Unity3D]做个小Demo学习Input.touches 学不如做,下面用一个简单的Demo展示的Input.touches各项字段,有图有真相. 本项目已发布到Github,地址在(https ...
- Android -- 自定义View小Demo,动态画圆(一)
1,转载:(http://blog.csdn.NET/lmj623565791/article/details/24500107),现在如下图的效果: 由上面的效果图可以看到其实是一个在一个圆上换不同 ...
- Win10 FaceAPI小demo开发问题汇总
Win10 FaceAPI小demo开发问题汇总 最近使用微软牛津计划做一个小demo,使用FaceAPI做一个小应用,实现刷脸的功能.开发的过程中用到几个问题,具体如下: Stream 与IRand ...
随机推荐
- Linux系统中时间区域和API
1.问题 在开发云平台程序的时候,经常会碰到时间区域转换的问题.比如,任何网络存储的文档的metadata都自己记录了编辑时间.但是,云平台记录时需要把这个时间转成标准时间,便于管理.但是用户使用的时 ...
- 高可用Kubernetes集群-16. ansible快速部署
说明 本文档指导采用二进制包的方式快速部署高可用kubernetes集群. 脚本托管:k8s-ansible(持续更新) 参考:高可用kubernetes集群 组件版本 组件 版本 备注 centos ...
- docker usage
docker ps -a 查看物理机上面所有容器信息列表 docker exec -it $docker_id /bin/bash 进入容器以默认帐号 docker exec -it -u root ...
- Vue03
5.组件化开发 组件[component] 在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个功能相关的[HTML ...
- JavaWeb-Servlet-Tomcat
Servlet就是运行在服务器上的Java类.Servlet容器为javaweb应用提供运行时环境,负责管理Servlet和JSP的生命周期,以及管理它们的共享数据. Servlet容器软件——Tom ...
- vi/vim命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/mondol/p/vi-examples.html 进入vi vi filename # 打开或新建文件,并将光标置于第 ...
- 导出excel失败,提示提示加载类型库/DDL出错
首先,这里提供的解决办法仅适用于出现如下异常的情况:无法将类型为“Microsoft.Office.Interop.Excel.ApplicationClass”的 COM 对象强制转换为接口类型“M ...
- 奔跑吧DKY——团队Scrum冲刺阶段博客汇总
第一周:团队展示 团队选题 需求规格说明书 第二周:完善需求规格说明书.制定团队编码规范.通过团队项目数据库设计 奔跑吧DKY--团队Scrum冲刺阶段-Day 1-领航 奔跑吧DKY--团队Scru ...
- Scala入门系列(三):数组
Array 与Java的Array类似,也是长度不可变的数组,此外,由于Scala与Java都是运行在JVM中,双方可以互相调用,因此Scala数组的底层实际上是Java数组. 注意:访问数组中元素使 ...
- VS团队资源管理器(VS自带git)使用说明_使用VS自带git推送到远程存储库
使用git存储库是相当好的习惯,每次码完代码就推送到远程存储库,万一不小心把本地代码搞废了,或者硬盘坏了,或者中了勒索病毒,本地代码丢失了还能从服务器上下载.我曾经就中了一次勒索病毒,本地电脑上的所有 ...