• 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;
            }
        
        }
  • 相关阅读:
    Linux用户态程序计时方式详解
    我的代码重构经验
    基于链表的C语言堆内存检测
    C语言内存使用的常见问题及解决之道
    1151 LCA in a Binary Tree (30 分)
    1150 Travelling Salesman Problem (25 分)
    1149 Dangerous Goods Packaging (25 分)
    1148 Werewolf
    1155 Heap Paths (30 分)
    1154 Vertex Coloring (25 分)
  • 原文地址:https://www.cnblogs.com/wadmwz/p/9846330.html
Copyright © 2020-2023  润新知