水上太陽能火災 消防車要用特別款──千葉・山倉風災事件啟示錄

文:宋瑞文(加州能源特約撰述)

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

2015台灣國際電動車展 充電樁與電池技術備受矚目

隨著電動車普及,充電設備、車體以及電池等相關領域也成了相關業者爭相投入的目標。今年共有75家展商參與2015年台灣國際電動車展,許多台廠用充電樁與電動車電池等技術做為「電力」展示主軸。

2015年台北國際汽車零配件展&車用電子展於四月8日至11日在台北世貿、南港展覽館同時展出。其中,在世貿展覽的台北國際電動車展有來自台灣、中國大陸、日本、香港、紐西蘭等廠商參加。除了電動車外,其他主要展出內容包括:電池材料、模組與控制系統,馬達與驅控系統、充電樁相關設備與服務、檢測設備。電力是電動車之本,充電樁、電池或自動充電系統等取得電力的管道是本次展覽中十分重要的部分。

台灣的電動車展出

台灣地狹人稠,對電動載具的需求主要是電動機車和小貨卡、高球車、觀光區小車等工具車,且以電動機車最有發展潛力。受限於電池容量以及載重限制,電動機車體積仍較小,但在造型、避震、輪胎、車燈與置物空間等其他部分則已有多樣化發展,整體功能更接近傳統機車。

電動車的功能考量主要有幾個面向:

  • 充電方便性,如充電樁分布、快充功能、電池交換系統
  • 續航力(每次充電至少需可行駛40~50km)
  • 載重力
  • 爬坡力
  • 行駛速度

哈哈世代主要展出的電動車自動回充發電系統為針對電動車之充電需求所研發,小從電動機車,大到電動卡車、輪船或高鐵列車等皆可應用,車輛行駛一小時左右即可充飽電池,最低每公里耗電成本約為新台幣0.2~0.3元。

大同電子在本次展覽中未展出車輛,而是以電動車馬達為主要展示內容。大同所展示的馬達分成感應馬達、磁阻馬達以及內藏式永磁馬達,額定功率與電壓分別從1.8kW到30kW,以及24V到360V,可根據車輛需求的差別選擇不同功率與電壓的馬達。

晶片解決方案提供者Renesas展出了一種專為HEV/EV驅動馬達設計的變頻器套件解決方案,能縮小變頻器尺寸並提升其效率,且可適用各種馬達,也有助提升電動車馬達的效能。

 

電動車電池與充電樁

在本次展覽中,電動車電池的技術仍是最主要的內容。包括電池的蓄電力、充電後的續航力、充放電技術(快充功能)、防爆與安全性之檢測等,都有展示。

長泓能源科技展示氧化鋰鐵動力電池,這種電池的電性穩定、循環壽命長且能量密度高,加上它十分安全、重量又輕,很適合搭配電動車或其他儲設備使用。

充電樁與電池交換站是電動車的電力來源,密集分布的充電樁有助推廣民眾使用電動車。展場中常見的充電設備包括:壁掛式充電站、立柱式充電樁、電池交換器;而非家用充電設備的使用方法分成兩種,一種是經由卡片認證(可設計特殊RFID卡片或與悠遊卡等電子商務整合),另一種則是投幣式。據了解,台灣設置充電樁依縣市政策之別,可獲得約50%的補助;桃園市補助較高,可接近100%。

EValue 展出單槍、雙槍式充電樁,亦有裝設了液晶螢幕的多媒體充電站,可做為廣告看板。Phihong EV Charger 展出多種充電設備,立柱式充電樁的電容有40kW、70kW以及140kW等類型,也有簡易的小型充電站以及電池充電系統。

台灣喜洋洋公司展出的投幣式電動機車充電站可為裝設戶帶來一定的收益,每投幣10元可充100分鐘。目前有大學、社區等裝設與維護合作。

其他相關展示

汽車電控系統也是本次電動車展覽中可見的項目,例如Chroma就展示一體化的智慧電動車方案,可有效掌控電動車電力系統。EV Equipment  則展示更加環保的電動概念車Preeve。

台灣車輛研發聯盟主題館展示多種電動車相關技術,其中汰役電池的應用為未來將大量產生的廢電池找到了第二春。汰役電池的電容、續航力雖低,但可用於供應較低需求電力,或改作UPS系統。目前在金門烈嶼鄉東坑社區已有汰役電池應用測試,搭配太陽能與風能供應30戶住宅用電,也能支援當地的電動車用電。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

重學 Java 設計模式:實戰中介者模式「按照Mybatis原理手寫ORM框架,給JDBC方式操作數據庫增加中介者場景」

作者:小傅哥
博客:https://bugstack.cn – 原創系列專題文章

沉澱、分享、成長,讓自己和他人都能有所收穫!

一、前言

同齡人的差距是從什麼時候拉開的

同樣的幼兒園、同樣的小學、一樣的書本、一樣的課堂,有人學習好、有人學習差。不只是上學,幾乎人生處處都是賽道,發令槍響起的時刻,也就把人生的差距拉開。編程開發這條路也是很長很寬,有人跑得快有人跑得慢。那麼你是否想起過,這一點點的差距到遙不可及的距離,是從哪一天開始的。摸摸肚子的肉,看看遠處的路,別人講的是故事,你想起的都是事故

思想沒有產品高才寫出一片的ifelse

當你承接一個需求的時候,比如;交易、訂單、營銷、保險等各類場景。如果你不熟悉這個場景下的業務模式,以及將來的拓展方向,那麼很難設計出良好可擴展的系統。再加上產品功能初建,說老闆要的急,儘快上線。作為程序員的你更沒有時間思考,整體一看現在的需求也不難,直接上手開干(一個方法兩個if語句),這樣確實滿足了當前需求。但老闆的想法多呀,產品也跟着變化快,到你這就是改改改,加加加。當然你也不客氣,回首掏就是1024個if語句!

日積月累的技術沉澱是為了厚積薄發

粗略的估算過,如果從上大學開始每天寫200行,一個月是6000行,一年算10個月話,就是6萬行,第三年出去實習的是時候就有20萬行的代碼量。如果你能做到這一點,找工作難?有時候很多事情就是靠時間積累出來的,想走捷徑有時候真的沒有。你的技術水平、你的業務能力、你身上的肉,都是一點點積累下來的,不要浪費看似很短的時間,一年年堅持下來,留下印刻青春的痕迹,多給自己武裝上一些能力。

二、開發環境

  1. JDK 1.8
  2. Idea + Maven
  3. mysql 5.1.20
  4. 涉及工程一個,可以通過關注公眾號bugstack蟲洞棧,回復源碼下載獲取(打開獲取的鏈接,找到序號18)
工程 描述
itstack-demo-design-16-01 使用JDBC方式連接數據庫
itstack-demo-design-16-02 手寫ORM框架操作數據庫

三、中介者模式介紹

中介者模式要解決的就是複雜功能應用之間的重複調用,在這中間添加一層中介者包裝服務,對外提供簡單、通用、易擴展的服務能力。

這樣的設計模式幾乎在我們日常生活和實際業務開發中都會見到,例如;飛機降落有小姐姐在塔台喊話、無論哪個方向來的候車都從站台上下、公司的系統中有一个中台專門為你包裝所有接口和提供統一的服務等等,這些都運用了中介者模式。除此之外,你用到的一些中間件,他們包裝了底層多種數據庫的差異化,提供非常簡單的方式進行使用。

四、案例場景模擬

在本案例中我們通過模仿Mybatis手寫ORM框架,通過這樣操作數據庫學習中介者運用場景

除了這樣的中間件層使用場景外,對於一些外部接口,例如N種獎品服務,可以由中台系統進行統一包裝對外提供服務能力。也是中介者模式的一種思想體現。

在本案例中我們會把jdbc層進行包裝,讓用戶在使用數據庫服務的時候,可以和使用mybatis一樣簡單方便,通過這樣的源碼方式學習中介者模式,也方便對源碼知識的拓展學習,增強知識棧。

五、用一坨坨代碼實現

這是一種關於數據庫操作最初的方式

基本上每一個學習開發的人都學習過直接使用jdbc方式連接數據庫,進行CRUD操作。以下的例子可以當做回憶。

1. 工程結構

itstack-demo-design-16-01
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                └── JDBCUtil.java
  • 這裏的類比較簡單隻包括了一個數據庫操作類。

2. 代碼實現

public class JDBCUtil {

    private static Logger logger = LoggerFactory.getLogger(JDBCUtil.class);

    public static final String URL = "jdbc:mysql://127.0.0.1:3306/itstack-demo-design";
    public static final String USER = "root";
    public static final String PASSWORD = "123456";

    public static void main(String[] args) throws Exception {
        //1. 加載驅動程序
        Class.forName("com.mysql.jdbc.Driver");
        //2. 獲得數據庫連接
        Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
        //3. 操作數據庫
        Statement stmt = conn.createStatement();
        ResultSet resultSet = stmt.executeQuery("SELECT id, name, age, createTime, updateTime FROM user");
        //4. 如果有數據 resultSet.next() 返回true
        while (resultSet.next()) {
            logger.info("測試結果 姓名:{} 年齡:{}", resultSet.getString("name"),resultSet.getInt("age"));
        }
    }

}
  • 以上是使用JDBC的方式進行直接操作數據庫,幾乎大家都使用過這樣的方式。

3. 測試結果

15:38:10.919 [main] INFO  org.itstack.demo.design.JDBCUtil - 測試結果 姓名:水水 年齡:18
15:38:10.922 [main] INFO  org.itstack.demo.design.JDBCUtil - 測試結果 姓名:豆豆 年齡:18
15:38:10.922 [main] INFO  org.itstack.demo.design.JDBCUtil - 測試結果 姓名:花花 年齡:19

Process finished with exit code 0
  • 從測試結果可以看到這裏已經查詢到了數據庫中的數據。只不過如果在全部的業務開發中都這樣實現,會非常的麻煩。

六、中介模式開發ORM框架

`接下來就使用中介模式的思想完成模仿Mybatis的ORM框架開發~

1. 工程結構

itstack-demo-design-16-02
└── src
    ├── main
    │   ├── java
    │   │   └── org.itstack.demo.design
    │   │       ├── dao
    │   │       │	├── ISchool.java
    │   │       │	└── IUserDao.java
    │   │       ├── mediator
    │   │       │	├── Configuration.java
    │   │       │	├── DefaultSqlSession.java
    │   │       │	├── DefaultSqlSessionFactory.java
    │   │       │	├── Resources.java
    │   │       │	├── SqlSession.java
    │   │       │	├── SqlSessionFactory.java
    │   │       │	├── SqlSessionFactoryBuilder.java
    │   │       │	└── SqlSessionFactoryBuilder.java
    │   │       └── po
    │   │         	├── School.java
    │   │         	└── User.java
    │   └── resources
    │       ├── mapper
    │       │   ├── School_Mapper.xml
    │       │   └── User_Mapper.xml
    │       └── mybatis-config-datasource.xml
    └── test
         └── java
             └── org.itstack.demo.design.test
                 └── ApiTest.java

中介者模式模型結構

  • 以上是對ORM框架實現的核心類,包括了;加載配置文件、對xml解析、獲取數據庫session、操作數據庫以及結果返回。
  • 左上是對數據庫的定義和處理,基本包括我們常用的方法;<T> T selectOne<T> List<T> selectList等。
  • 右側藍色部分是對數據庫配置的開啟session的工廠處理類,這裏的工廠會操作DefaultSqlSession
  • 之後是紅色地方的SqlSessionFactoryBuilder,這個類是對數據庫操作的核心類;處理工廠、解析文件、拿到session等。

接下來我們就分別介紹各個類的功能實現過程。

2. 代碼實現

2.1 定義SqlSession接口

public interface SqlSession {

    <T> T selectOne(String statement);

    <T> T selectOne(String statement, Object parameter);

    <T> List<T> selectList(String statement);

    <T> List<T> selectList(String statement, Object parameter);

    void close();
}
  • 這裏定義了對數據庫操作的查詢接口,分為查詢一個結果和查詢多個結果,同時包括有參數和沒有參數的方法。

2.2 SqlSession具體實現類

public class DefaultSqlSession implements SqlSession {

    private Connection connection;
    private Map<String, XNode> mapperElement;

    public DefaultSqlSession(Connection connection, Map<String, XNode> mapperElement) {
        this.connection = connection;
        this.mapperElement = mapperElement;
    }

    @Override
    public <T> T selectOne(String statement) {
        try {
            XNode xNode = mapperElement.get(statement);
            PreparedStatement preparedStatement = connection.prepareStatement(xNode.getSql());
            ResultSet resultSet = preparedStatement.executeQuery();
            List<T> objects = resultSet2Obj(resultSet, Class.forName(xNode.getResultType()));
            return objects.get(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public <T> List<T> selectList(String statement) {
        XNode xNode = mapperElement.get(statement);
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(xNode.getSql());
            ResultSet resultSet = preparedStatement.executeQuery();
            return resultSet2Obj(resultSet, Class.forName(xNode.getResultType()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // ...

    private <T> List<T> resultSet2Obj(ResultSet resultSet, Class<?> clazz) {
        List<T> list = new ArrayList<>();
        try {
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            // 每次遍歷行值
            while (resultSet.next()) {
                T obj = (T) clazz.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    Object value = resultSet.getObject(i);
                    String columnName = metaData.getColumnName(i);
                    String setMethod = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);
                    Method method;
                    if (value instanceof Timestamp) {
                        method = clazz.getMethod(setMethod, Date.class);
                    } else {
                        method = clazz.getMethod(setMethod, value.getClass());
                    }
                    method.invoke(obj, value);
                }
                list.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    @Override
    public void close() {
        if (null == connection) return;
        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • 這裏包括了接口定義的方法實現,也就是包裝了jdbc層。
  • 通過這樣的包裝可以讓對數據庫的jdbc操作隱藏起來,外部調用的時候對入參、出參都有內部進行處理。

2.3 定義SqlSessionFactory接口

public interface SqlSessionFactory {

    SqlSession openSession();

}
  • 開啟一個SqlSession, 這幾乎是大家在平時的使用中都需要進行操作的內容。雖然你看不見,但是當你有數據庫操作的時候都會獲取每一次執行的SqlSession

2.4 SqlSessionFactory具體實現類

public class DefaultSqlSessionFactory implements SqlSessionFactory {

    private final Configuration configuration;

    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public SqlSession openSession() {
        return new DefaultSqlSession(configuration.connection, configuration.mapperElement);
    }

}
  • DefaultSqlSessionFactory,是使用mybatis最常用的類,這裏我們簡單的實現了一個版本。
  • 雖然是簡單的版本,但是包括了最基本的核心思路。當開啟SqlSession時會進行返回一個DefaultSqlSession
  • 這個構造函數中向下傳遞了Configuration配置文件,在這個配置文件中包括;Connection connectionMap<String, String> dataSourceMap<String, XNode> mapperElement。如果有你閱讀過Mybatis源碼,對這個就不會陌生。

2.5 SqlSessionFactoryBuilder實現

public class SqlSessionFactoryBuilder {

    public DefaultSqlSessionFactory build(Reader reader) {
        SAXReader saxReader = new SAXReader();
        try {
            saxReader.setEntityResolver(new XMLMapperEntityResolver());
            Document document = saxReader.read(new InputSource(reader));
            Configuration configuration = parseConfiguration(document.getRootElement());
            return new DefaultSqlSessionFactory(configuration);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Configuration parseConfiguration(Element root) {
        Configuration configuration = new Configuration();
        configuration.setDataSource(dataSource(root.selectNodes("//dataSource")));
        configuration.setConnection(connection(configuration.dataSource));
        configuration.setMapperElement(mapperElement(root.selectNodes("mappers")));
        return configuration;
    }

    // 獲取數據源配置信息
    private Map<String, String> dataSource(List<Element> list) {
        Map<String, String> dataSource = new HashMap<>(4);
        Element element = list.get(0);
        List content = element.content();
        for (Object o : content) {
            Element e = (Element) o;
            String name = e.attributeValue("name");
            String value = e.attributeValue("value");
            dataSource.put(name, value);
        }
        return dataSource;
    }

    private Connection connection(Map<String, String> dataSource) {
        try {
            Class.forName(dataSource.get("driver"));
            return DriverManager.getConnection(dataSource.get("url"), dataSource.get("username"), dataSource.get("password"));
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 獲取SQL語句信息
    private Map<String, XNode> mapperElement(List<Element> list) {
        Map<String, XNode> map = new HashMap<>();

        Element element = list.get(0);
        List content = element.content();
        for (Object o : content) {
            Element e = (Element) o;
            String resource = e.attributeValue("resource");

            try {
                Reader reader = Resources.getResourceAsReader(resource);
                SAXReader saxReader = new SAXReader();
                Document document = saxReader.read(new InputSource(reader));
                Element root = document.getRootElement();
                //命名空間
                String namespace = root.attributeValue("namespace");

                // SELECT
                List<Element> selectNodes = root.selectNodes("select");
                for (Element node : selectNodes) {
                    String id = node.attributeValue("id");
                    String parameterType = node.attributeValue("parameterType");
                    String resultType = node.attributeValue("resultType");
                    String sql = node.getText();

                    // ? 匹配
                    Map<Integer, String> parameter = new HashMap<>();
                    Pattern pattern = Pattern.compile("(#\\{(.*?)})");
                    Matcher matcher = pattern.matcher(sql);
                    for (int i = 1; matcher.find(); i++) {
                        String g1 = matcher.group(1);
                        String g2 = matcher.group(2);
                        parameter.put(i, g2);
                        sql = sql.replace(g1, "?");
                    }

                    XNode xNode = new XNode();
                    xNode.setNamespace(namespace);
                    xNode.setId(id);
                    xNode.setParameterType(parameterType);
                    xNode.setResultType(resultType);
                    xNode.setSql(sql);
                    xNode.setParameter(parameter);

                    map.put(namespace + "." + id, xNode);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }

        }
        return map;
    }

}
  • 在這個類中包括的核心方法有;build(構建實例化元素)parseConfiguration(解析配置)dataSource(獲取數據庫配置)connection(Map<String, String> dataSource) (鏈接數據庫)mapperElement (解析sql語句)
  • 接下來我們分別介紹這樣的幾個核心方法。

build(構建實例化元素)

這個類主要用於創建解析xml文件的類,以及初始化SqlSession工廠類DefaultSqlSessionFactory。另外需要注意這段代碼saxReader.setEntityResolver(new XMLMapperEntityResolver());,是為了保證在不聯網的時候一樣可以解析xml,否則會需要從互聯網獲取dtd文件。

parseConfiguration(解析配置)

是對xml中的元素進行獲取,這裏主要獲取了;dataSourcemappers,而這兩個配置一個是我們數據庫的鏈接信息,另外一個是對數據庫操作語句的解析。

connection(Map<String, String> dataSource) (鏈接數據庫)

鏈接數據庫的地方和我們常見的方式是一樣的;Class.forName(dataSource.get("driver"));,但是這樣包裝以後外部是不需要知道具體的操作。同時當我們需要鏈接多套數據庫的時候,也是可以在這裏擴展。

mapperElement (解析sql語句)

這部分代碼塊內容相對來說比較長,但是核心的點就是為了解析xml中的sql語句配置。在我們平常的使用中基本都會配置一些sql語句,也有一些入參的佔位符。在這裏我們使用正則表達式的方式進行解析操作。

解析完成的sql語句就有了一個名稱和sql的映射關係,當我們進行數據庫操作的時候,這個組件就可以通過映射關係獲取到對應sql語句進行操作。

3. 測試驗證

在測試之前需要導入sql語句到數據庫中;

  • 庫名:itstack-demo-design
  • 表名:userschool
CREATE TABLE school ( id bigint NOT NULL AUTO_INCREMENT, name varchar(64), address varchar(256), createTime datetime, updateTime datetime, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into school (id, name, address, createTime, updateTime) values (1, '北京大學', '北京市海淀區頤和園路5號', '2019-10-18 13:35:57', '2019-10-18 13:35:57');
insert into school (id, name, address, createTime, updateTime) values (2, '南開大學', '中國天津市南開區衛津路94號', '2019-10-18 13:35:57', '2019-10-18 13:35:57');
insert into school (id, name, address, createTime, updateTime) values (3, '同濟大學', '上海市彰武路1號同濟大廈A樓7樓7區', '2019-10-18 13:35:57', '2019-10-18 13:35:57');
CREATE TABLE user ( id bigint(11) NOT NULL AUTO_INCREMENT, name varchar(32), age int(4), address varchar(128), entryTime datetime, remark varchar(64), createTime datetime, updateTime datetime, status int(4) DEFAULT '0', dateTime varchar(64), PRIMARY KEY (id), INDEX idx_name (name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into user (id, name, age, address, entryTime, remark, createTime, updateTime, status, dateTime) values (1, '水水', 18, '吉林省榆樹市黑林鎮尹家村5組', '2019-12-22 00:00:00', '無', '2019-12-22 00:00:00', '2019-12-22 00:00:00', 0, '20200309');
insert into user (id, name, age, address, entryTime, remark, createTime, updateTime, status, dateTime) values (2, '豆豆', 18, '遼寧省大連市清河灣司馬道407路', '2019-12-22 00:00:00', '無', '2019-12-22 00:00:00', '2019-12-22 00:00:00', 1, null);
insert into user (id, name, age, address, entryTime, remark, createTime, updateTime, status, dateTime) values (3, '花花', 19, '遼寧省大連市清河灣司馬道407路', '2019-12-22 00:00:00', '無', '2019-12-22 00:00:00', '2019-12-22 00:00:00', 0, '20200310');

3.1 創建數據庫對象類

用戶類

public class User {

    private Long id;
    private String name;
    private Integer age;
    private Date createTime;
    private Date updateTime;
    
    // ... get/set
}

學校類

public class School {

    private Long id;
    private String name;
    private String address;
    private Date createTime;
    private Date updateTime;  
  
    // ... get/set
}
  • 這兩個類都非常簡單,就是基本的數據庫信息。

3.2 創建DAO包

用戶Dao

public interface IUserDao {

     User queryUserInfoById(Long id);

}

學校Dao

public interface ISchoolDao {

    School querySchoolInfoById(Long treeId);

}

3.3 ORM配置文件

鏈接配置

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/itstack_demo_design?useUnicode=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/User_Mapper.xml"/>
        <mapper resource="mapper/School_Mapper.xml"/>
    </mappers>

</configuration>
  • 這個配置與我們平常使用的mybatis基本是一樣的,包括了數據庫的連接池信息以及需要引入的mapper映射文件。

操作配置(用戶)

<mapper namespace="org.itstack.demo.design.dao.IUserDao">

    <select id="queryUserInfoById" parameterType="java.lang.Long" resultType="org.itstack.demo.design.po.User">
        SELECT id, name, age, createTime, updateTime
        FROM user
        where id = #{id}
    </select>

    <select id="queryUserList" parameterType="org.itstack.demo.design.po.User" resultType="org.itstack.demo.design.po.User">
        SELECT id, name, age, createTime, updateTime
        FROM user
        where age = #{age}
    </select>

</mapper>

操作配置(學校)

<mapper namespace="org.itstack.demo.design.dao.ISchoolDao">

    <select id="querySchoolInfoById" resultType="org.itstack.demo.design.po.School">
        SELECT id, name, address, createTime, updateTime
        FROM school
        where id = #{id}
    </select>

</mapper>

3.4 單個結果查詢測試

@Test
public void test_queryUserInfoById() {
    String resource = "mybatis-config-datasource.xml";
    Reader reader;
    try {
        reader = Resources.getResourceAsReader(resource);
        SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sqlMapper.openSession();
        try {
            User user = session.selectOne("org.itstack.demo.design.dao.IUserDao.queryUserInfoById", 1L);
            logger.info("測試結果:{}", JSON.toJSONString(user));
        } finally {
            session.close();
            reader.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 這裏的使用方式和Mybatis是一樣的,都包括了;資源加載和解析、SqlSession工廠構建、開啟SqlSession以及最後執行查詢操作selectOne

測試結果

16:56:51.831 [main] INFO  org.itstack.demo.design.demo.ApiTest - 測試結果:{"age":18,"createTime":1576944000000,"id":1,"name":"水水","updateTime":1576944000000}

Process finished with exit code 0
  • 從結果上看已經滿足了我們的查詢需求。

3.5 集合結果查詢測試

@Test
public void test_queryUserList() {
    String resource = "mybatis-config-datasource.xml";
    Reader reader;
    try {
        reader = Resources.getResourceAsReader(resource);
        SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sqlMapper.openSession();
        try {
            User req = new User();
            req.setAge(18);
            List<User> userList = session.selectList("org.itstack.demo.design.dao.IUserDao.queryUserList", req);
            logger.info("測試結果:{}", JSON.toJSONString(userList));
        } finally {
            session.close();
            reader.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 這個測試內容與以上只是查詢方法有所不同;session.selectList,是查詢一個集合結果。

測試結果

16:58:13.963 [main] INFO  org.itstack.demo.design.demo.ApiTest - 測試結果:[{"age":18,"createTime":1576944000000,"id":1,"name":"水水","updateTime":1576944000000},{"age":18,"createTime":1576944000000,"id":2,"name":"豆豆","updateTime":1576944000000}]

Process finished with exit code 0
  • 測試驗證集合的結果也是正常的,目前位置測試全部通過。

七、總結

  • 以上通過中介者模式的設計思想我們手寫了一個ORM框架,隱去了對數據庫操作的複雜度,讓外部的調用方可以非常簡單的進行操作數據庫。這也是我們平常使用的Mybatis的原型,在我們日常的開發使用中,只需要按照配置即可非常簡單的操作數據庫。
  • 除了以上這種組件模式的開發外,還有服務接口的包裝也可以使用中介者模式來實現。比如你們公司有很多的獎品接口需要在營銷活動中對接,那麼可以把這些獎品接口統一收到中台開發一個獎品中心,對外提供服務。這樣就不需要每一個需要對接獎品的接口,都去找具體的提供者,而是找中台服務即可。
  • 在上述的實現和測試使用中可以看到,這種模式的設計滿足了;單一職責開閉原則,也就符合了迪米特原則,即越少人知道越好。外部的人只需要按照需求進行調用,不需要知道具體的是如何實現的,複雜的一面已經有組件合作服務平台處理。

八、推薦閱讀

  • 1. 重學 Java 設計模式:實戰工廠方法模式「多種類型商品不同接口,統一發獎服務搭建場景」
  • 2. 重學 Java 設計模式:實戰原型模式「上機考試多套試,每人題目和答案亂序排列場景」
  • 3. 重學 Java 設計模式:實戰橋接模式「多支付渠道(微信、支付寶)與多支付模式(刷臉、指紋)場景」
  • 4. 重學 Java 設計模式:實戰組合模式「營銷差異化人群發券,決策樹引擎搭建場景」
  • 5. 重學 Java 設計模式:實戰外觀模式「基於SpringBoot開發門面模式中間件,統一控制接口白名單場景」
  • 6. 重學 Java 設計模式:實戰享元模式「基於Redis秒殺,提供活動與庫存信息查詢場景」

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

迄今最大海外訂單!比亞迪獲美國60輛電動大巴訂購

4月28日,比亞迪宣佈,洛杉磯大都會部分地區提供服務的長灘運輸署將訂購比亞迪的10輛電池動力巴士,並有增購不超過50輛電動巴士的選擇權。這是比亞迪迄今為止在國際市場上最大一筆電動巴士訂單。   據比亞迪的資訊顯示,其一年前在加州開設一家巴士工廠,以打入美國、加拿大和拉美市場,目前美國大約有50輛比亞迪電動巴士在運營。而比亞迪銷售總監侯雁上週在上海車展表示,比亞迪2015年計畫銷售大約15,000輛電動計程車和大約6,000輛電動巴士。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

解Bug之路-中間件”SQL重複執行”

前言

我們的分庫分表中間件在線上運行了兩年多,到目前為止還算穩定。在筆者將精力放在處理各種災難性事件(例如中間件物理機宕機/數據庫宕機/網絡隔離等突發事件)時。竟然發現還有一些奇怪的corner case。現在就將排查思路寫成文章分享出來。

Bug現場

應用拓撲

應用通過中間件連後端多個數據庫,sql會根據路由規則路由到指定的節點,如下圖所示:

錯誤現象

應用在做某些數據庫操作時,會發現有比較大的概率失敗。他們的代碼邏輯是這樣:

	int count = updateSql(sql1);
	...
	// 偽代碼
	int count = updateSql("update test set value =1 where id in ("100","200") and status = 1;
	if( 0 == count ){
		throw new RuntimeException("更新失敗");
	}
	......
	int count = updateSql(sql3);
	...

即每做一次update之後都檢查下是否更新成功,如果不成功則回滾並拋異常。
在實際測試的過程中,發現經常報錯,更新為0。而實際那條sql確實是可以更新到的(即報錯回滾后,我們手動執行sql可以執行並update count>0)。

中間件日誌

筆者根據sql去中間件日誌裏面搜索。發現了非常奇怪的結果,日誌如下:

2020-03-13 11:21:01:440 [NIOREACTOR-20-RW] frontIP=>ip1;sqlID=>12345678;rows=>0;sql=>update test set value =1 where id in ("1","2") and status = 1;start=>11:21:01:403;time=>24266;
2020-03-13 11:21:01:440 [NIOREACTOR-20-RW] frontIP=>ip1;sqlID=>12345678;rows=>2;sql=>update test set value =1 where id in ("1","2") and status = 1;start=>11:21:01:403;time=>24591;

由於中間件對每條sql都標識了唯一的一個sqlID,在日誌表現看來就好像sql執行了兩遍!由於sql中有一個in,很容易想到是否被拆成了兩條執行了。如下圖所示:

這條思路很快被筆者否決了,因為筆者explain並手動執行了一下,這條sql確實只路由到了一個節點。真正完全否決掉這條思路的是筆者在日誌裏面還發現,同樣的SQL會打印三遍!即看上去像執行了三次,這就和僅僅只in了兩個id的sql在思路上相矛盾了。

數據庫日誌

那到底數據真正執行了多少條呢?找DBA去撈一下其中的sql日誌,由於線下環境沒有日誌切割,日誌量巨大,搜索時間太慢。沒辦法,就按照現有的數據進行分析吧。

日誌如何被觸發

由於當前沒有任何思路,於是筆者翻看中間件的代碼,發現在update語句執行后,中間件會在收到mysql okay包后打印上述日誌。如下圖所示:

注意到所有出問題的update出問題的時候都是同一個NIOREACTOR線程先後打印了兩條日誌,所以筆者推斷這兩個okay大概率是同一個後端連接返回的。

什麼情況會返回多個okay?

這個問題筆者思索了很久,因為在筆者的實際重新執行出問題的sql並debug時,永遠只有一個okay返回。於是筆者聯想到,我們中間件有個狀態同步的部分,而這些狀態同步是將set auto_commit=0等sql拼接到應用發送的sql前面。即變成如下所示:

sql可能為
set auto_commit=0;set charset=gbk;>update test set value =1 where id in ("1","2") and status = 1;

於是筆者細細讀了這部分的代碼,發現處理的很好。其通過計算出前面拼接出的sql數量,再在接收okay包的時候進行遞減,最後將真正執行的那條sql處理返回。其處理如下圖所示:

但這裏確給了筆者一個靈感,即一條sql文本確實是有可能返回多個okay包的。

真相大白

在筆者發現(sql1;sql2;)這樣的拼接sql會返回多個okay包后,就立刻聯想到,該不會業務自己寫了這樣的sql發給中間件,造成中間件的sql處理邏輯錯亂吧。因為我們的中間件只有在對自己拼接(同步狀態)的sql做處理,明顯是無法處理應用傳過來即為拼接sql的情況。
由於看上去有問題的那條sql並沒有拼接,於是筆者憑藉這條sql打印所在的reactor線程往上搜索,發現其上面真的有拼接sql!

2020-03-1311:21:01:040[NIOREACTOR-20RW]frontIP=>ip1;sqlID=>12345678;rows=>1;
sql=>update test_2 set value =1 where id=1 and status = 1;update test_2 set value =1 where id=2 and status = 1;

如上圖所示,(update1;update2)中update1的okay返回被驅動認為是所有的返回。然後應用立即發送了update3。前腳剛發送,update2的okay返回就回來了而其剛好是0,應用就報錯了(要不是0,這個錯亂邏輯還不會提前暴露)。那三條”重複執行”也很好解釋了,就是之前的拼接sql會有三條。

為何是概率出現

但奇怪的是,並不是每次拼接sql都會造成update3″重複執行”的現象,按照筆者的推斷應該前面只要是多條拼接sql就會必現才對。於是筆者翻了下jdbc驅動源碼,發現其在發送命令之前會清理下接收buffer,如下所示:

MysqlIO.java
final Buffer sendCommand(......){
	......
	// 清理接收buffer,會將殘存的okay包清除掉
	clearInputStream();
	......
	send(this.sendPacket, this.sendPacket.getPosition());
	......
}

正是由於clearInputStream()使得錯誤非必現(暴露),如果okay(update2)在應用發送第三條sql前先到jdbc驅動會被驅動忽略!
讓我們再看一下不會讓update3″重複執行”的時序圖:

即根據okay(update2)返回的快慢來決定是否暴露這個問題,如下圖所示:

同時筆者觀察日誌,確實這種情況下”update1;update2″這條語句在中間件裏面日誌有兩條。

臨時解決方案

讓業務開發不用這些拼接sql的寫法后,再也沒出過問題。

為什麼不連中間件是okay的

業務開發這些sql是就在線上運行了好久,用了中間件后才出現問題。
既然不連中間件是okay的,那麼jdbc必然有這方面的完善處理,筆者去翻了下mysql-connect-java(5.1.46)。由於jdbc裏面存在大量的兼容細節處理,筆者這邊只列出一些關鍵代碼路徑:

MySQL JDBC 源碼
MySQLIO
stack;
executeUpdate
	|->executeUpdateInternel
		|->executeInternal
			|->execSQL
				|->sqlQueryDirect
					|->readAllResults (MysqlIO.java)
readAllResults: //核心在這個函數的處理裏面
ResultSetImpl readAllResults(......){
		......
       while (moreRowSetsExist) {
			  ......
			  // 在返回okay包的保中其serverStatus字段中如果SERVER_MORE_RESULTS_EXISTS置位
			  // 表明還有更多的okay packet
            moreRowSetsExist = (this.serverStatus & SERVER_MORE_RESULTS_EXISTS) != 0;
        }
        ......
}

正確的處理流程如下圖所示:

而我們中間件的源碼確實這麼處理的:

@Override
public void okResponse(byte[] data, BackendConnection conn) {
	......
	// 這邊僅僅處理了autocommit的狀態,沒有處理SERVER_MORE_RESULTS_EXISTS
	// 所以導致了不兼容拼接sql的現象
	ok.serverStatus = source.isAutocommit() ? 2 : 1;
	ok.write(source);
	......
}

select也”重複執行”了

解決完上面的問題后,筆者在日誌里竟然發現select盡然也有重複的,這邊並不會牽涉到okay包的處理,難道還有問題?日誌如下所示:

2020-03-13 12:21:01:040[NIOREACTOR-20RW]frontIP=>ip1;sqlID=>12345678;rows=>1;select abc;
2020-03-13 12:21:01:045[NIOREACTOR-21RW]frontIP=>ip2;sqlID=>12345678;rows=>1;select abc;

從不同的REACTOR線程號(20RW/21RW)和不同的frontIP(ip1,ip2)來看是兩個連接執行了同樣的sql,但為何sqlID是一樣的?任何一個詭異的現象都必須一查到底。於是筆者登錄到應用上看了下應用日誌,確實應用有兩個不同的線程運行了同一條sql。
那肯定是中間件日誌打印的問題了,筆者很快就想通了其中的關竅,我們中間件有個對同樣sql緩存其路由節點結構體的功能(這樣下一次同樣sql就不必解析,降低了CPU),而sqlID信息正好也在那個路由節點結構體裏面。如下圖所示:

這個緩存功能感覺沒啥用(因為線上基本是沒有相同sql的),於是筆者在筆者優化的閃電模式下(大幅度提高中間件性能)將這個功能禁用掉了,沒想到為了排查問題而開啟的詳細日誌碰巧將這個功能開啟了。

總結

任何系統都不能說百分之百穩定可靠,尤其是不能立flag。在線上運行了好幾年的系統也是如此。只有對所有預料外的現象進行細緻的追查與深入的分析並解決,才能讓我們的系統越來越可靠。

公眾號

關注筆者公眾號,獲取更多乾貨文章:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

敢反抗開發就坐牢 原民反土地改革惡法 印尼動亂中媒體忽略的訴求

環境資訊中心外電;姜唯 翻譯;林大利 審校;稿源:Mongabay

9月下旬,印尼史上繼1998年獨裁者蘇哈托倒台以來最大規模的抗爭行動,佔據國際新聞版面。英國、美國]、和其他外國媒體頭條報導成千上萬民眾在全國各地大城市示威遊行,抗議婚前性行為納入刑法。

撤銷新刑法法條,包括不得侮辱總統和提供避孕資訊,只是抗議者的訴求之一。根據網上流傳的七點聲明,訴求還包括反對廢除一條弱化反貪腐機構的新法、停止蘇門答臘和婆羅洲的森林大火,以及從印尼東邊的巴布亞地區撤軍。印尼對分裂主義的軍事鎮壓行動已經進行了數十年。

撤銷土地利用新法也在訴求清單上。

這條尚未被媒體大幅報導,但觀察者表示,它的重要性不亞於其他幾乎立法完成的爭議性法案。

評論家說,該法案定義了新的罪行,並增加了刑罰,使當局更容易監禁抵抗開發商入侵的農村居民,使農業公司能保留土地特許經營權更長的時間。

印尼巴布亞省一條切開森林的公路,涉嫌剝奪了原住民的土地所有權。Nanang Sujana攝;來源:Mongabay。

在批評者眼中,最令人髮指的是,該法案設定了一個兩年期限,要求公民必須在期限內向政府註冊土地,否則土地將收歸國有,成為佐科威總統土地改革計畫的一部分重新分配,或授權私人公司使用。

但是,原住民尋求正式承認其土地就起碼要花兩年,通常還要更久,才能通過層層官僚關卡。因此,兩年期限對印尼弱勢的原住民權利來說更是一記沈重的打擊,印尼原住民組織「AMAN」副秘書長卡亞迪(Erasmus Cahyadi)說。

2013年印尼憲法法院作出歷史性裁決,駁回了州政府對原住民森林所有權的主張,此後總統佐科威陸續承認55個原住民群體對森林的權利,總面積達248平方公里(96平方英里)。但是AMAN說他們欲承認的原民土地有77,600平方公里(30,000平方英里),屬於704個原住民族。

AMAN法律與人權事務負責人穆罕默德(Arman Muhammad)說,該法案違反了憲法的精神。

印尼大學生走上雅加達街頭,反對新法律弱化反貪腐機構。Hans Nicholas Jong攝;來源:Mongabay。

該法案的支持者則認為,通過該法案對於佐科威的大型土地改革計畫來說是必要的。

佐科威於今年4月當選第二個五年任期,他已承諾賦予農村社區更大的權力,控制其21.7萬平方公里(84,000平方英里)的土地,但是實踐進度緩慢。

截至10月,控制該國約一半土地的環境和林業部僅分配了總計28,000平方公里的土地,遠低於目標127,000平方公里。

民主黨國會議員卡隆(Herman Khaeron):「土地改革計畫的土地很難找。」

為了解決這個問題,卡隆說,該法案要求建立一個新的機構,稱為土地管理署,負責收購、管理和分配兩年的時間內沒有被公民登記的土地,這些土地將自動收歸國有。

根據該法案,土地管理署將充當「土地銀行」,能夠透過租賃或出售土地產生收入,同時仍以非營利組織的形式運作。該機構必須保證為「社會利益」和「發展利益」提供土地。

法案的措詞含糊,批評者擔心該機構會將土地當作商品出售給強勢投資者,以犧牲普通市民為代價。

「誰將能夠使用這個土地銀行?小農嗎?當然不是,」印尼茂物農業研究所(Bogor Institute of Agriculture, IPB)人類生態學系研究員卡友諾(Eko Cahyono)說,「這個土地銀行將為有大量資本、企業和開發計畫的人服務。」

評論家說,該法案中的其他條款將使企業受益,傷害農村社區。

該法案將允許農業公司持有「HGU」耕種權許可證,有效期長達90年,而現行規定為60年。油棕公司可以拖更久的時間才將小農地釋出給當地社區。

此外,該法條還規定,凡訂定「引起土地糾紛之惡意協議」者,將被判處5至15年監禁,「妨礙土地機關僱員和/或執法人員執行任務」者可判處兩年監禁。

倡議組織土地改革聯盟(Consortium for Agrarian Reform, KPA)秘書長卡蒂卡(Dewi Kartika)向記者,根據後項條款,反抗土地掠奪的原住民、行動人士等人可被入罪。

「它賦予警察將任何人定罪的合法性。最極端的詮釋之下,可被用來逮捕任何人。例如,當居民試圖阻止他們的土地被用來建造機場時,就可能會被逮捕。」

成百上千的印尼村莊在和農業公司對抗時陷入困境,社區成員常常以肉身擋推土機,甚至縱火燒毀公司設備。

9月26日,一名21歲的大學生在蘇拉威西省東南部省會肯達里的大規模抗議活動中被警察槍殺。抗議活動演變成暴亂後,另一名19歲學生卡德哈維(Yusuf Qardhawi)因鈍器重創頭部而死亡。

「我們非常沮喪和失望,」參加抗議活動的社區組織者、23歲的馬斯庫里(Mando Maskuri)說,「國家應該保護人民,但他們卻在殺死人民。」

。與印尼其他地方一樣,當地人往往缺乏證明土地所有權的文件,這使得州政府很容易在未經他們同意的情況下引入企業投資者。

馬斯庫里說,許多旺尼居民嘗試向州政府登記其土地。但他擔心土地法案設定的時間表不切實際,最終導致居民失去土地,逼他們搬走。

大學生在肯達里用行動劇抗議礦場開發。Kamaruddin攝,來源:Mongabay

在9月抗議活動的高峰期,對土地法案和其他爭議性法案的審議被。跛鴨議會會期即將結束,新的議員宣誓就職。

現任議員在最後一刻同意將土地法案移交至新議會會期,這表示新任議員可以從同一階段繼續審議,不必從頭開始。

根據調查性新聞機構Tempo和非政府組織Auriga Nusantara的,接下來五年負責立法工作的575名議員中,將近一半是與至少1,016家企業有聯繫的商人,其中包括採礦公司和油棕公司。

佐科威總統說,他想,使之對投資者更加友善。許多觀察家表示,不少與已列入清單。

研究人員卡友諾說,如果議員試圖通過土地法案,反對者可以在最後一道關卡提出司法審查。

同時,馬斯庫里說他準備再次走上街頭,「如果議會要強行通過該法案,將面臨來自農民、漁民和民間社會團體的巨大阻力。」

Indonesia protests: Land bill at center of unrest by Basten Gokkon, Hans Nicholas Jong, Philip Jacobson on 3 November 2019

  • In recent weeks, Indonesia has seen its largest mass protests since the “people power” movement that forced President Suharto to step down in 1998.
  • Among a variety of pro-democracy demands, the protesters want lawmakers to scrap a controversial bill governing land use in the country.
  • The bill defines new crimes critics say could be used to imprison indigenous and other rural citizens for defending their lands against incursions by private companies.
  • It also sets a two-year deadline by which citizens must register their lands with the government, or else watch them pass into state control. Activists say the provision would deal a “knockout blow” to the nation’s indigenous rights movement.

JAKARTA — In late September, international news outlets caught flak for their coverage of Indonesia’s largest mass protests since the 1998 uprising that led to the fall of the dictator Suharto.

Headlines published by the , , and other foreign media implied the demonstrations, involving tens of thousands of people in major cities across the country, had arisen in response to a proposed new criminal code that would ban sex before marriage.

“I did not get tear-gassed so Australians could keep having sex in Bali,” one netizen on Twitter, among a barrage of reactions to the reductive reports. “This is about the future of the country.”

Scrapping the criminal code changes — which also include new penalties for insulting the president and providing information about contraception — was just one of the protesters’ demands, enumerated in a seven-point declaration that has circulated online. They also want the government to repeal a new law weakening the nation’s anti-corruption agency, stop forest fires in Sumatra and Borneo, and withdraw troops from Indonesia’s easternmost Papua region, where a military crackdown against separatists has been going on for decades.

Also on the list: scrap a proposed new law governing land use.

Though the land bill has gotten scant media coverage, observers say it is among the most potentially transformative of a raft of on the verge of being passed into law.

The bill defines new crimes and introduces increased penalties that, critics say, would make it easier for authorities to imprison rural citizens for defending their lands against incursions by developers. It would also allow plantation companies to retain vast land concessions for longer periods of time.

Most damningly in the eyes of critics, the bill sets a two-year deadline by which citizens must register their lands with the government, or else watch them pass into state control, where they could be redistributed as part of President Joko Widodo’s land reform program or licensed out to private firms.

But indigenous groups seeking formal recognition of their lands already spend at least that long, and often far longer, jumping through bureaucratic hoops. The two-year deadline would therefore constitute a “knockout blow” for the nation’s embattled indigenous rights movement, Erasmus Cahyadi, deputy secretary-general of AMAN, Indonesia’s main advocacy group for indigenous peoples, told Mongabay.

Since 2013, when a landmark Constitutional Court ruling struck down the state’s claim to indigenous peoples’ forests, President Joko Widodo has recognized the rights of 55 indigenous groups to forests spanning a total of 248 square kilometers (96 square miles). But AMAN says it has mapped more than 77,600 square kilometers (30,000 square miles) of land it says belongs to 704 indigenous communities.

“The bill is contrary to the spirit of the constitution,” said Arman Muhammad, AMAN’s law and human rights director.



University students protest the new corruption law in Jakarta. Image by Hans Nicholas Jong/Mongabay.

The bill’s supporters argue its passage is necessary to support President Widodo’s flagship land reform program.

Widodo, who was elected to a second five-year term in April, has promised to give rural communities greater control over 217,000 square kilometers (84,000 square miles) of land. But progress has been slow.

As of October, the Ministry of Environment and Forestry, which controls around half of the nation’s land, had only distributed a total of 28,000 square kilometers (10,800 square miles), far short of its target of 127,000 square kilometers (49,000 square miles).

“It’s hard to find land for the agrarian reform [program],” Democrat Party lawmaker Herman Khaeron at a recent panel event in Jakarta.

To solve that, Herman said, the bill calls for the creation of a new body called the Land Management Agency to acquire, manage and distribute land that had gone unclaimed by citizens during the two-year window, that therefore automatically fell under state control.

The bill says the agency will function as a “land bank,” implying it will be able to generate an income from leasing or selling lands, while still operating as a “nonprofit,” according to the bill. The agency must guarantee the availability of land for “social interests” as well as “development interests.”

The language in the bill is vague, but critics fear the agency would treat land as a commodity to be sold to powerful investors at the expense of ordinary citizens.

“Who would be able to access this land bank? Small farmers? Of course not,” Eko Cahyono, a researcher in the Department of Human Ecology at the Bogor Institute of Agriculture (IPB), told Mongabay. “The ‘land bank’ would serve those with big capital, companies and development projects.”

Other provisions in the bill would benefit corporations at the expense of rural communities, critics say.

The bill would allow plantation companies to hold a right-to-cultivate permit, known as an HGU, for 90 years, up from 60 years under the current rules.

It would also let oil palm firms wait longer before providing smallholdings to local communities, a requirement under existing laws.

Furthermore, the legislation stipulates prison time of five to 15 years for anyone who makes an “evil agreement that gives rise to a land dispute,” and a jail term of two years for those who “obstruct an employee and/or law enforcement officer from carrying out tasks in the land sector.”

The latter provision could be used to “criminalize indigenous peoples, activists or anyone who tries to organize” against a land grab, Dewi Kartika, the secretary-general of the Consortium for Agrarian Reform (KPA), an advocacy group, reporters in Jakarta recently.

“It grants the police legal legitimacy to criminalize anyone,” she said. “Of course this will be interpreted to the maximum extent possible, to freely arrest anyone. For example, if residents try to stand in the way of their land being used to build an airport.”

Hundreds, if not thousands, of Indonesian villages are embroiled in conflict with natural resources firm, with community members often resorting to physically blocking bulldozers or even setting fire to company facilities.

On Sept. 26, a 21-year-old college student in Kendari, the capital of Southeast Sulawesi province and one of the cities where mass protests took place in September, was shot dead by police. Another student in Kendari, 19-year-old Yusuf Qardhawi, died of blunt-force head injuries after a protest turned into a violent riot.

“We were all so upset and disappointed,” Mando Maskuri, 23, a community organizer who joined the protests in Kendari, told Mongabay. “The state is supposed to protect us, but they’re killing us.”

Residents of Mando’s home island of Wawonii are with mining firms that hold permits to operate on their lands. As elsewhere in Indonesia, locals tend to lack documents backing their land claims, making it easy for the state to bring in corporate investors without their consent.

Many people in Wawonii are trying to register their lands with the state, Mando said. But he fears the land bill sets an unrealistic timeline that will eventually cause residents to lose their lands, forcing them to migrate to other parts of the country.



Students in Kendari stage a mock burial in early 2019 to express their opposition to the mining in Wawonii. Image by Kamaruddin for Mongabay.

At the height of the protests in September, deliberations on the land bill and other controversial legislation were . The lame-duck parliament was nearing the end of its session. New lawmakers have since been sworn in.

In their final hour, however, the previous lawmakers agreed to “carry over” the land bill to the current parliament session, meaning deliberations can be resumed from the same stage by the new batch of legislators, rather than having to start all over again.

Nearly half of the 575 lawmakers for the next five years are businesspeople who are affiliated with at least 1,016 companies, including mining and oil palm, according to an by investigative journalism outlet Tempo and Auriga Nusantara, an NGO.

President Widodo says he wants to to make them friendlier to investors; many observers have said are on the list.

If lawmakers try to pass the land bill, opponents could file a judicial review in a last-ditch attempt to oppose it, said Eko, the researcher.

In the meantime, Mando says he is ready to take to the streets again.

“If parliament tries to pass the bill, there will be massive resistance from farmers, fishermen, and civil society groups,” he said.

※ 全文及圖片詳見:

作者

如果有一件事是重要的,如果能為孩子實現一個願望,那就是人類與大自然和諧共存。

於特有生物研究保育中心服務,小鳥和棲地是主要的研究對象。是龜毛的讀者,認為龜毛是探索世界的美德。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

違法噴灑遭禁殺蟲劑 孟山都將付3億罰款

摘錄自2019年11月22日中央通訊社美國報導

美國農業生技巨擘孟山都(Monsanto)今天(22日)同意認罪,承認在夏威夷毛伊島(Maui)的設施對研究作物違法噴灑遭禁的劇毒殺蟲劑,將支付1000萬美元(約新台幣3億532萬元)罰款。

法新社報導,孟山都在提交給檀香山聯邦地區法院的法庭文件中承認,2014年在農場谷(Valley Farm)對玉米種子等作物噴灑Penncap-M殺蟲劑,即使已知環境保護署於2013年禁用這款化學物。

審理此案的加州中區聯邦檢察官韓納(Nick Hanna)說:「此案的違法行徑對環境、周圍社區和孟山都工人構成威脅。」他說:「聯邦法律與相關規範規定,使用管制和危險化學物的每個人,都有責任確保產品是經過安全儲存、運送與使用。」

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家前需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

西安電動計程車要試運營啦!6月5日首批亮相36輛

陝西省西安市首批36輛比亞迪e6電動計程車將於6月5日投入試運營。電動計程車可享受社會公共停車場2小時內免費停車,且西汽公司將建的士大廳,供駕駛員就餐休息。西安市一共購進了300輛電動計程車,其中西汽公司擁有90輛,由服務部代管,而這36輛將首批亮相。   為了滿足這些電動計程車充電,西汽總公司的院子裡已建成20個充電樁,將在22日投入使用。西汽服務部副經理張向東表示,由於現在部分充電站並未建成投入使用,因此公司會要求駕駛員在跑了200公里的時候就返回充電,這樣本來需要滿放滿充兩小時,最快充電可能幾十分鐘便可完成。而充電的費用將全部由公司承擔。   據工作人員介紹,雖然電動計程車的成本較高,但乘客乘坐電動計程車的價格初定與普通計程車一樣。按照政府推廣新能源車輛的相關規定,電動計程車不但能免交購置稅,而且可享受兩小時免費停車,隨時可走公交專用道。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

Postman之API測試使用全指南

Postman

Postman是一個可擴展的API開發和測試協同平台工具,可以快速集成到CI/CD管道中。旨在簡化測試和開發中的API工作流。

Postman 工具有 Chrome 擴展和獨立客戶端,推薦安裝獨立客戶端。

Postman 有個 workspace 的概念,workspace 分 personal 和 team 類型。Personal workspace 只能自己查看的 API,Team workspace 可添加成員和設置成員權限,成員之間可共同管理 API。

當然我個人使用一般是不登錄的,因為登錄之後會自動將你的測試歷史數據保存到賬戶里,你可以登陸網頁端進行查看。
因為API的很多數據是很敏感的,有的含有Token,或者就是一些私密信息,雖然Postman自己也強調說這樣很安全,不會私下窺探用戶的信息之類的,但是呢還是至少做一點有效的防範吧,自己不上傳,因為網絡並沒有絕對的安全。
所以我每次測試之後會將數據(Case)保存在本地,下次使用或者換設備的情況下將數據拷貝過來又可以繼續使用了。

下面正式開始介紹如何使用Postman吧。

為什麼選擇Postman?

如今,Postman的開發者已超過1000萬(來自官網),選擇使用Postman的原因如下:
簡單易用 – 要使用Postman,你只需登錄自己的賬戶,只要在電腦上安裝了Postman應用程序,就可以方便地隨時隨地訪問文件。
使用集合 – Postman允許用戶為他們的API調用創建集合。每個集合可以創建子文件夾和多個請求。這有助於組織測試結構。
多人協作 – 可以導入或導出集合和環境,從而方便共享文件。直接使用鏈接還可以用於共享集合。
創建環境 – 創建多個環境有助於減少測試重複(DEV/QA/STG/UAT/PROD),因為可以為不同的環境使用相同的集合。這是參數化發生的地方,將在後續介紹。
創建測試 – 測試檢查點(如驗證HTTP響應狀態是否成功)可以添加到每個API調用中,這有助於確保測試覆蓋率。
自動化測試 – 通過使用集合Runner或Newman,可以在多個迭代中運行測試,節省了重複測試的時間。
調試 – Postman控制台有助於檢查已檢索到的數據,從而易於調試測試。
持續集成——通過其支持持續集成的能力,可以維護開發實踐。

如何下載安裝Postman?

Step 1) 官網主頁:https://www.postman.com/downloads/, 下載所需版本進行安裝即可。

Step2)安裝完成之後會要求你必須登錄才能使用,沒有賬號可以進行註冊,註冊是免費的。(也可使用Google賬號,不過基本不能登錄,你懂的)

Step3)在Workspace選擇你要使用的工具並點擊“Save My Preferences”保存。

Step4)你將看到啟動后的頁面如下

如何使用Postman?

下圖是Postman的工作區間,各個模塊功能的介紹如下:

1、New,在這裏創建新的請求、集合或環境;還可以創建更高級的文檔、Mock Server 和 Monitor以及API。
2、Import,這用於導入集合或環境。有一些選項,例如從文件,文件夾導入,鏈接或粘貼原始文本。
3、Runner,可以通過Collection Runner執行自動化測試。後續介紹。
4、Open New,打開一個新的標籤,Postman窗口或Runner窗口。
5、My Workspace – 可以單獨或以團隊的形式創建新的工作區。
6、Invite – 通過邀請團隊成員在工作空間上進行協同工作。
7、History – 所有秦秋的歷史記錄,這樣可以很容易地跟蹤你所做的操作。
8、Collections – 通過創建集合來組織你的測試套件。每個集合可能有子文件夾和多個請求。請求或文件夾也可以被複制。
9、Request tab – 這將显示您正在處理的請求的標題。默認對於沒有標題的請求會显示“Untitled Request”。
10、HTTP Request – 單擊它將显示不同請求的下拉列表,例如 GET, POST, COPY, DELETE, etc. 在測試中,最常用的請求是GET和POST。
11、Request URL – 也稱為端點,显示API的URL。.
12、Save – 如果對請求進行了更改,必須單擊save,這樣新更改才不會丟失或覆蓋。
13、Params – 在這裏將編寫請求所需的參數,比如Key – Value。
14、Authorization – 為了訪問api,需要適當的授權。它可以是Username、Password、Token等形式。
15、Headers – 請求頭信息
16、Body – 請求體信息,一般在POST中才會使用到
17、Pre-request Script – 請求之前 先執行腳本,使用設置環境的預請求腳本來確保在正確的環境中運行測試。
18、Tests – 這些腳本是在請求期間執行的。進行測試非常重要,因為它設置檢查點來驗證響應狀態是否正常、檢索的數據是否符合預期以及其他測試。
19、Settings – 最新版本的有設置,一般用不到。

如何處理GET請求

Get請求用於從指定的URL獲取信息,不會對端點進行任何更改。
在這裏我們使用如下的URL作為演示:

https://jsonplaceholder.typicode.com/users	

在Postman的工作區中:
1、選擇HTTP請求方式為GET
2、在URL區域輸入 鏈接
3、點擊 “Send”按鈕
4、你將看到下方返回200狀態碼
5、在正文中應該有10個用戶結果,表明您的測試已經成功運行。

注意:在某些情況下,Get請求失敗可能由於URL無效或需要身份驗證。

如何處理POST請求

Post請求與Get請求不同,因為存在用戶向端點添加數據的數據操作。使用之前GET 請求中相同數據,現在添加我們自己的用戶。
Step 1)創建一個新請求

Step 2 )在新請求中
1、選擇HTTP請求方式為GET
2、在URL區域輸入 鏈接:https://jsonplaceholder.typicode.com/users
3、切換到Body選項

Step 3) Body選項
1、選中raw選項
2、選擇JSON

Step 4) 複製前面GET請求返回的json內容的第一節
更改id為11,更改name以及uesrname和email

[
    {
        "id": 11,
        "name": "Krishna Rungta",
        "username": "Bret",
        "email": "Sincere@april.biz
	",
        "address": {
            "street": "Kulas Light",
            "suite": "Apt. 556",
            "city": "Gwenborough",
            "zipcode": "92998-3874",
            "geo": {
                "lat": "-37.3159",
                "lng": "81.1496"
            }
        },
        "phone": "1-770-736-8031 x56442",
        "website": "hildegard.org",
        "company": {
            "name": "Romaguera-Crona",
            "catchPhrase": "Multi-layered client-server neural-net",
            "bs": "harness real-time e-markets"
        }
    }
]

注意: 檢查Body里用到的JSON格式很重要,以確保數據正確。
檢測的工具比如:https://jsonformatter.curiousconcept.com/

Step 5 )發送請求
1、完成上述的信息輸入,點擊Send按鈕
2、Status:應該是201,显示為創建成功
3、在Body里返回數據

如何將請求參數化

數據參數化是Postman最有用的特徵之一。你可以將使用到的變量進行參數化,而不是使用不同的數據創建相同的請求,這樣會事半功倍,簡潔明了。
這些數據可以來自數據文件環境變量。參數化有助於避免重複相同的測試,可用於自動化迭代測試。

參數通過使用雙花括號創建:{{sample}}
比如下面的請求:

接下來創建一個參數化get請求:
Step 1) 創建一個參數化get請求
1、將HTTP請求設置為GET
2、輸入URL: https://jsonplaceholder.typicode.com/users;將鏈接的域名部分替換為參數,例如{{url}}。請求url現在應該是{{url}}/users。
3、點擊Send按鈕。
應該沒有響應,因為我們沒有設置參數的源,如下圖:

Step 2) 使用環境設置所需的參數
1、點擊眼睛圖標
2、單擊Edit將該變量設置為可在所有集合中使用的全局環境。

Step 3) 變量–variable
1、將名稱設置為url,該url為https://jsonplaceholder.typicode.com
2、點擊保存按鈕

Step 4) 如果看到下面截圖的樣式,請單擊Close

Step 5 ) 回到你的Get請求頁面,然後單擊發送Send按鈕,Get請求應該就會返回結果了,如下圖:

注意:請確保所有的參數都有準確的源數據,不管是環境變量還是數據文件,以避免出錯。

如何創建Postman Tests

Postman Tests在請求中添加JavaScript代碼來協助驗證結果,如:成功或失敗狀態、預期結果的比較等等。
通常從pm.test開始。它可以與斷言相比較,驗證其他工具中可用的命令。
接下來創建一個包含Tests的請求:
Step 1) 創建一個Get請求
1、切換到Tests選項,右邊是代碼片段選項。
2、從右邊的代碼片段選項裏面選中 “Status code: Code is 200”
3、JS代碼就自動出現在窗口中

Step 2) 點擊發送請求按鈕。測試結果就显示出來了,如下圖:

Step 3) 回到Tests選項卡,讓我們添加另一個測試。這次我們將比較預期結果和實際結果。
在右邊的SNIPPETS區域選擇”Response body:JSON value check”選項,我們將檢查Leanne Graham是否擁有userid 1。

Step 4)
1、將代碼中的“Your Test Name”替換為“Check if user with id1 is Leanne Graham”,以便測試名稱確切描述我們想測試的內容。
2、使用jsonData[0].name代替jsonData.value; 獲取路徑,在獲取結果之前檢查Body。因為Leanne Graham是userid 1,所以jsonData在第一個結果中,這個結果應該從0開始。如果你想獲得第二個結果,那麼對後續結果使用jsonData[1] 即可。
3、在eql中,輸入“Leanne Graham”

pm.test("Check if user with id1 is Leanne Graham", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData[0].name).to.eql("Leanne Graham");
});

Step 5) 點擊發送請求,可以看到你的請求之後測試結果中有兩項显示測試通過。

注意:
有不同種類的測試可以在Postman中創建。嘗試探索這個工具,看看哪些測試適合你實際測試。

如何創建測試集合

集合在組織測試套件中扮演着重要的角色。它可以被導入和導出,使得在團隊之間共享集合變得很容易。在本教程中,我們將學習如何創建和執行集合。

Step 1) 單擊頁面左上角的New按鈕,如下圖:

Step 2) 選擇Collection(集合). 創建collection窗口彈出,如下圖.

Step 3) 輸入所需的集合名稱和描述,然後單擊create。
現在已經創建了一個集合。

Step 4 ) 和前面的Get請求一樣,點擊保存。

Step5 )
1、選擇Postman 測試集合(Test Collection)。
2、點擊保存Postman Test Collection

Step 6) Postman test collection現在應該包含了一個請求,如下圖:

Step 7) 重複上述的Step4-5,繼續創建請求,這樣,測試集合就應該有2個請求了,如下圖。

如何使用Collection Runner 運行集合

有兩種方式來運行一個集合,即Collection Runner和Newman。
Collection Runner:
Step 1) 單擊頁面頂部導入按鈕旁邊的Runner按鈕,如下圖。

Step 2)Collection Runner頁面應該出現如下所示。以下是對各個字段的描述

Step 3) 做如下設置,運行你的測試集合

  • 選擇Postman測試集合-集合迭代次數為3
  • 設置延遲為2500毫秒
  • 點擊Start Run按鈕

    Step 4) 單擊Run按鈕后將显示Run結果頁。根據延遲的不同,你應該在測試執行的同時看到显示的結果。

1、一旦測試完成,你就可以看到測試狀態是通過還是失敗,以及每個迭代的結果。
2、你將看到Get請求的Pass狀態;
3、由於我們沒有任何Post測試,所以應該會出現請求沒有任何測試的消息。

可以出在請求中進行測試是多麼重要,這樣你就可以驗證HTTP請求狀態是否成功,以及是否創建或檢索了數據。

如何使用Newman運行集合

運行集合的另一種方式是通過Newman。Newman和Collection Runner之間的主要區別如下:
1、Newman是Postman的替代品,所以需要單獨安裝Newman;
2、Newman使用命令行,而Collection Runner使用UI界面;
3、Newman可以用於持續集成。

安裝Newman並運行Collection,步驟如下:
Step 1) 下載並安裝NodeJs: http://nodejs.org/download/
Step 2) 打開命令行窗口並輸入下面命令:

npm install -g newman

安裝后 如下圖:

Step 3 )
Newman安裝好之後,讓我們回到Postman的workspace。在Collections框中,單擊三個點 會出現新的選擇選項,可看到Export選項,如下圖:

Step 4 )
選擇導出集合,默認使用推薦的集合版本,比如此處是v2.1,然後單擊導出:

Step 5 ) 選擇你想要保存的地址之後點擊保存,這裏建議專門新建一個文件夾來存放你的Postman tests。
Step 6 ) 另外還需要導出我們的環境(enviroment)。單擊全局環境下拉菜單旁邊的eye圖標,選擇JSON格式下載。選擇你想要的位置,然後單擊Save。最好將環境放在與Step5 導出的集合相同的文件夾中。

Step 7 ) 導出Environment 到集合文件夾后,現在回到命令行,將目錄更改為保存集合和環境的位置。

cd C:\Users\Asus\Desktop\Postman Tests

Step 8 ) 使用下面的命令運行你的測試集合:

newman run PostmanTestCollection.postman_collection.json -e Testing.postman_globals.json

運行的結果應該如下圖:

關於Newman的一些基礎指導如下:
1、只運行集合(如果沒有環境或測試數據文件依賴關係,則可以使用此選項。)

newman run <collection name> 

2、運行集合和環境(參數-e 是environment)

newman run <collection name> -e <environment name> 

3、使用所需的編號運行集合的迭代。

newman run <collection name> -n <no.of iterations>

4、運行數據文件

newman run <collection name> --data <file name>  -n <no.of iterations> -e <environment name> 

5、設置延遲時間。(這一點很重要,因為如果由於請求在後台服務器上,完成前一個請求時沒有延遲時間直接啟動下一個請求,測試可能會失敗。)

newman run <collection name> -d <delay time>

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

遼寧瀋陽法院公開宣判兩起涉疫情犯罪案件

  中國消費者報瀋陽訊(記者 王文郁)2月28日,遼寧省瀋陽經濟技術開發區人民法院、瀋陽市瀋河區人民法院公開宣判2起涉疫情犯罪案件,所涉罪名分別為銷售偽劣產品罪和詐騙罪,涉案3名被告人分別被判處有期徒刑10個月至有期徒刑6年6個月不等刑期。

  瀋陽經濟技術開發區人民法院對被告人王某瑩、楊某雨銷售偽劣產品案,通過雲上法庭開庭審理。法院經審理查明,1月30日至2月2日間,王某瑩、楊某雨二人趁國內暴發大規模新冠肺炎民眾急需佩戴口罩之際,利用微信朋友圈和微信群進行口罩銷售的宣傳。在買方確定購買后,二人從其上家張某(另案處理)處以每個12至13元不等的價格大量購進劣質仿冒3M口罩,后以每個16元至25元不等的價格進行對外銷售,銷售金額共計90110元。經3M口罩生產商明尼蘇達礦業製造(中國)投資有限公司鑒定,涉案口罩與正品不符。經遼寧省勞動防護用品產品質量監督檢驗中心檢驗,涉案3M自吸過濾式防顆粒物呼吸器過濾效率不符合標準要求。法院認為,王某瑩、楊某雨銷售偽劣產品,銷售金額5萬元以上,被告人王某瑩、楊某雨構成銷售偽劣產品罪,王某瑩被判處有期徒刑11個月,並處罰金6萬元,楊某雨被判處有期徒刑10個月,並處罰金5萬元。

  瀋陽市瀋河區人民法院對被告人張某涵詐騙案,依法適用刑事簡易程序,利用遼寧法院互聯網庭審雲平台開庭審理。法院經審理查明,2月,在新冠肺炎疫情防控期間,張某涵在微信朋友圈發布出售防護用口罩的信息。被害人姜某某、文某獲知后,先後與張某涵聯繫購買口罩。張某涵在明知無法提供口罩的情況下,於2月4日至2月6日間,分多次收取二人購買口罩款37萬元(其中姜某某3.2萬元,文某33.8萬元)。張某涵取得錢款后即揮霍一空。2月7日4時許,張某涵在無法隱瞞犯罪事實的情況下向公安機關投案,對上述事實供認不諱。法院認為,張某涵以非法佔有為目的,採用虛構事實、隱瞞真相的方法騙取他人財物,數額巨大。被告人張某涵構成詐騙罪,被判處有期徒刑6年6個月,罰金20萬元。

  在全國上下萬眾一心抗擊新冠肺炎疫情之際,總有人在特殊時期以身試法,利用疫情違法犯罪不僅會對疫情防控工作造成惡劣影響,更會嚴重危及人民群眾的身體健康和生命安全。上述案件的審理充分體現了人民法院為堅決打贏疫情防控阻擊戰提供有力司法保障的決心,同時,瀋陽法院利用遠程視頻提訊系統開庭審理刑事案件,有效避免審判過程中人員聚集,保障了訴訟參与人和司法工作人員在疫情防控期間的人身健康安全。

責任編輯:邊靜

本站聲明:網站內容來源再生能源資訊網http://www.ccn.com.cn/,如有侵權請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務