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;
        }
    
    }

猜你喜欢

转载自www.cnblogs.com/wadmwz/p/9846330.html