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;
        }
    
    }
相關文章
相關標籤/搜索