`

spring日记(八):使用Spring JDBC访问数据库

阅读更多

本人博客已搬家,新地址为:http://yidao620c.github.io/

在xml中配置jdbcTemplate:

<context:component-scan base-package="com.springzoo"/>
     
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
    p:driverClassName="${jdbc.driverClassName}"
    p:url="${jdbc.url}"
    p:username="${jdbc.username}"
    p:password="${jdbc.password}" />
 
<bean id="jdbcTemplate"
      class="org.springframework.jdbc.core.JdbcTemplate"
      p:dataSource-ref="dataSource"/>

下面是DAO的示例:

@Repository
public class ForumDao {
 
    @Autowired
    private JdbcTemplate jdbcTemplate;
 
    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
 
    public void initDb() {
        String sql = "create table t_user(user_id int primary key,user_name varchar(60))";
        jdbcTemplate.execute(sql);
    }
 
    /**
     * 更新一条数据
     * 
     * @param forum
     */
    public void addForum(final Forum forum) {
        final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
        Object[] params = new Object[] { forum.getForumName(),
                forum.getForumDesc() };
        // 方式1
        // jdbcTemplate.update(sql, params);
 
        // 方式2
        // jdbcTemplate.update(sql, params,new
        // int[]{Types.VARCHAR,Types.VARCHAR});
 
        // 方式3
        /*
         * jdbcTemplate.update(sql, new PreparedStatementSetter() { public void
         * setValues(PreparedStatement ps) throws SQLException { ps.setString(1,
         * forum.getForumName()); ps.setString(2, forum.getForumDesc()); } });
         */
 
        // 方式4
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {
            public PreparedStatement createPreparedStatement(Connection conn)
                    throws SQLException {
                PreparedStatement ps = conn.prepareStatement(sql);
                ps.setString(1, forum.getForumName());
                ps.setString(2, forum.getForumDesc());
                return ps;
            }
        }, keyHolder);
        forum.setForumId(keyHolder.getKey().intValue());
    }
 
    public void addForumByNamedParams(final Forum forum) {
        final String sql = "INSERT INTO t_forum(forum_name, forum_desc) VALUES(:forumName,:forumDesc)";
        SqlParameterSource sps = new BeanPropertySqlParameterSource(forum);
        namedParameterJdbcTemplate.update(sql, sps);
    }
 
    /**
     * 批量更新数据
     * 
     * @param forums
     */
    public void addForums(final List<Forum> forums) {
        final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
        jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            public int getBatchSize() {
                return forums.size();
            }
 
            public void setValues(PreparedStatement ps, int index)
                    throws SQLException {
                Forum forum = forums.get(index);
                ps.setString(1, forum.getForumName());
                ps.setString(2, forum.getForumDesc());
            }
        });
    }
 
    /**
     * 根据ID获取Forum对象
     * 
     * @param forumId
     * @return
     */
    public Forum getForum(final int forumId) {
        String sql = "SELECT forum_name,forum_desc FROM t_forum WHERE forum_id=?";
        final Forum forum = new Forum();
 
        jdbcTemplate.query(sql, new Object[] { forumId },
                new RowCallbackHandler() {
                    public void processRow(ResultSet rs) throws SQLException {
                        forum.setForumId(forumId);
                        forum.setForumName(rs.getString("forum_name"));
                        forum.setForumDesc(rs.getString("forum_desc"));
                    }
                });
        return forum;
    }
 
    public List<Forum> getForums(final int fromId, final int toId) {
        String sql = "SELECT forum_id,forum_name,forum_desc FROM t_forum WHERE forum_id between ? and ?";
        // 方法1:使用RowCallbackHandler接口
        /*
         * final List<Forum> forums = new ArrayList<Forum>();
         * jdbcTemplate.query(sql,new Object[]{fromId,toId},new
         * RowCallbackHandler(){ public void processRow(ResultSet rs) throws
         * SQLException { Forum forum = new Forum();
         * forum.setForumId(rs.getInt("forum_id"));
         * forum.setForumName(rs.getString("forum_name"));
         * forum.setForumDesc(rs.getString("forum_desc")); forums.add(forum);
         * }}); return forums;
         */
 
        return jdbcTemplate.query(sql, new Object[] { fromId, toId },
                new RowMapper<Forum>() {
                    public Forum mapRow(ResultSet rs, int index)
                            throws SQLException {
                        Forum forum = new Forum();
                        forum.setForumId(rs.getInt("forum_id"));
                        forum.setForumName(rs.getString("forum_name"));
                        forum.setForumDesc(rs.getString("forum_desc"));
                        return forum;
                    }
                });
 
    }
 
    int getForumNum() {
        return 0;
    }
}

返回数据库的自增主键方法:

Statement stmt = conn.createStatement();
String sql = "INSERT INTO t_topic(....) values(...)";
stmt.executeUpate(sql, Statement.RETURN_GENERATED_KYES);
ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()) {
    int key = rs.getInt();
}

spring利用这一技术,提供了一个可以返回新增记录主键的方法,就是上面的方式4:

// 方式4
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
    public PreparedStatement createPreparedStatement(Connection conn)
            throws SQLException {
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1, forum.getForumName());
        ps.setString(2, forum.getForumDesc());
        return ps;
    }
}, keyHolder);
forum.setForumId(keyHolder.getKey().intValue());

不过要注意的是,采用数据库的自增主键是不安全的,可以通过查询sequence或者在应用程序中提供主键两种方式保证安全性。

从功能上讲,RowCallbackHandler和RowMapper<T>没有太大区别,在返回多行时候RowMapper<T>更适合,因为不需要手动去往List里面添加。spring宣称RowCallbackHandler接口实现类可以使有状态的,如果它有状态我们就不能在多个地方重用。而RowMapper<T>实现类是没有状态的。

但是注意:如果处理大结果集的时候,使用RowMapper可能会内存泄露,最好使用RowCallbackHandler的实现类RowCountCallbackHandler,在processRow方法中处理结果集数据。一句话,RowMapper是将所有结果返回到一个List中,再去处理。而RowCallbackHandler是一行一行的去处理。

单值查询:

@Repository
public class TopicDao {
 
    @Autowired
    private JdbcTemplate jdbcTemplate;
 
    public double getReplyRate(int userId) {
        String sql = "SELECT topic_replies,topic_views FROM t_topic WHERE user_id=?";
        double rate = jdbcTemplate.queryForObject(sql, new Object[] { userId },
                new RowMapper<Double>() {
                    public Double mapRow(ResultSet rs, int index)
                            throws SQLException {
                        int replies = rs.getInt("topic_replies");
                        int views = rs.getInt("topic_views");
                        if (views > 0)
                            return new Double((double) replies / views);
                        else
                            return new Double(0.0);
                    }
                });
        return rate;
    };
 
    public int getUserTopicNum(final int userId) {
        String sql = "{call P_GET_TOPIC_NUM(?,?)}";
        //方式1
/*      Integer num = jdbcTemplate.execute(sql,
                new CallableStatementCallback<Integer>() {
                    public Integer doInCallableStatement(CallableStatement cs)
                            throws SQLException, DataAccessException {
                        cs.setInt(1, userId);
                        cs.registerOutParameter(2, Types.INTEGER);
                        cs.execute();
                        return cs.getInt(2);
                    }
                });
        return num;*/
         
        //方式2
        CallableStatementCreatorFactory fac = new CallableStatementCreatorFactory(sql); 
        fac.addParameter(new SqlParameter("userId",Types.INTEGER)); 
        fac.addParameter(new SqlOutParameter("topicNum",Types.INTEGER)); 
        Map<String,Integer> paramsMap = new HashMap<String,Integer>();
        paramsMap.put("userId",userId);
        CallableStatementCreator csc = fac.newCallableStatementCreator (paramsMap); 
        Integer num = jdbcTemplate.execute(csc,new CallableStatementCallback<Integer>(){
            public Integer doInCallableStatement(CallableStatement cs) 
                throws SQLException, DataAccessException {
                cs.execute();
                return cs.getInt(2);
            }   
        });
        return num;
    }
 
    public int getUserTopicNum2(int userId) {
        return 0;
    };
 
    public SqlRowSet getTopicRowSet(int userId) {
        String sql = "SELECT topic_id,topic_title FROM t_topic WHERE user_id=?";
        return jdbcTemplate.queryForRowSet(sql,userId);
 
    };
}

处理BLOB/COLB的大数据:

spring定义了一个独立于java.sql.Blob/Clob接口,以统一方式操作各种数据库Lob类型的LobCreator接口。为了方便在PreparedStatement中使用LobCreator,可以直接使用JDBCTemplate#execute(String sql, AbstractLobCreatingPreparedStatementCallback lcpsc)方法。用来set大字段的值

LobHandler接口为操作大二进制字段和大文本字段提供了统一访问接口,不管底层数据库究竟以大对象还是以一般数据类型方式进行操作,此外,LobHandler还充当LobCreator的工厂类。一般使用DefaultLobHandler即可。用来get返回的大字段的值

xml配置,注意lazy-init要设置成true,因为nativeJdbcExtractor需要通过运行时反射机制获取底层JDBC对象:

 

<bean id="jdbcTemplate"
      class="org.springframework.jdbc.core.JdbcTemplate"
      p:dataSource-ref="dataSource"/>
 
<bean id="nativeJdbcExtractor"
    class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"
    lazy-init="true" />
 
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"
    lazy-init="true" />

DAO中的用法,往数据库中插入或更新大数据操作:

@Repository
public class PostDao {
 
    @Autowired
    private JdbcTemplate jdbcTemplate;
 
    @Autowired
    private LobHandler lobHandler;
 
    public void addPost(final Post post){
        String sql = " INSERT INTO t_post(post_id,user_id,post_text,post_attach)"
                   + " VALUES(?,?,?,?)";
        jdbcTemplate.execute(sql,new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) {
          protected void setValues(PreparedStatement ps,LobCreator lobCreator)
                  throws SQLException {
                                //1:固定主键
                                ps.setInt(1,1);
                   
                    ps.setInt(2, post.getUserId()); 
                    lobCreator.setClobAsString(ps, 3, post.getPostText());
                    lobCreator.setBlobAsBytes(ps, 4, post.getPostAttach());
                }
            });
 
    }
    .....
}

以块数据方式读取数据库中大数据:

public List<Post> getAttachs(final int userId) {
    String sql = " SELECT post_id,post_attach FROM t_post where user_id =? and post_attach is not null ";
    return jdbcTemplate.query(sql, new Object[] { userId },
            new RowMapper<Post>() {
                public Post mapRow(ResultSet rs, int rowNum)
                        throws SQLException {
                    int postId = rs.getInt(1);
                    byte[] attach = lobHandler.getBlobAsBytes(rs, 2);
                    Post post = new Post();
                    post.setPostId(postId);
                    post.setPostAttach(attach);
                    return post;
                }
            });
 
}

以流数据方式读取Lob数据:

对于体积很大的Lob数据,比如超过50M,我们可以使用流的方式进行访问,减少内存占用。

public void getAttach(final int postId, final OutputStream os) {
    String sql = "SELECT post_attach FROM t_post WHERE post_id=? ";
    jdbcTemplate.query(sql, new Object[] {postId},
        new AbstractLobStreamingResultSetExtractor() {          
            protected void handleNoRowFound() throws LobRetrievalFailureException {
                    System.out.println("Not Found result!");
                }
            
            public void streamData(ResultSet rs) throws SQLException,IOException {
                    InputStream is = lobHandler.getBlobAsBinaryStream(rs, 1);
                    if (is != null) {
                        FileCopyUtils.copy(is, os);
                    }
            }
        }
    );
 
}

自增键和行集RowSet:

之前说过依靠数据库提供的自增键功能,比如mysql的auto_increment是不安全的。spring允许用户在应用层产生主键值,为此定义了org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer接口,提供两种产生主键的方案:一个是通过序列sequence产生,另一个是通过表产生主键。

* AbstractDataFieldMaxValueIncrementer:使用sequence或者模拟序列表产生主键,被下面两个类继承。

* AbstractSequenceMaxValueIncrementer使用标准的sequence产生主键

* AbstractColumnMaxValueIncrementer使用模拟序列表产生主键,可以指定cacheSize一次性缓冲多少个主键值,减少数据库访问次数。

首先在DAO中加入这一行:

@Autowired
private DataFieldMaxValueIncrementer incre;

然后再xml中定义:

<!-- 1:基于数据库序列的自增器 -->
<!-- 
<bean id="incre" 
 class="org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer"
 p:incrementerName="seq_post_id"
 p:dataSource-ref="dataSource"/>  
-->
 
<!-- 1:基于数据表的自增器 -->
<bean id="incre"
    class="org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer"
    p:incrementerName="t_post_id"
    p:columnName="sequence_id"
    p:cacheSize="10"
    p:dataSource-ref="dataSource"/>

用法:

public void addPost(final Post post){
String sql = " INSERT INTO t_post(post_id,user_id,post_text,post_attach)"
               + " VALUES(?,?,?,?)";
jdbcTemplate.execute(sql,new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) {
      protected void setValues(PreparedStatement ps,LobCreator lobCreator)
      throws SQLException {
            //2:通过自增键指定主键值        
            ps.setInt(1, incre.nextIntValue());
                ps.setInt(2, post.getUserId()); 
                lobCreator.setClobAsString(ps, 3, post.getPostText());
                lobCreator.setBlobAsBytes(ps, 4, post.getPostAttach());
            }
        });
 
}

规划主键方案:

所有主键全部采用应用层主键产生方案,使用UUID或者DataFieldMaxValueIncrementer生产主键。

以行集返回数据:

RowSet会一次性装载所有的匹配数据,同时会断开数据库的连接。而不是像ResultSet那样,分批次返回一批数据,一批的行数为fetchSize。所以,对于大结果集的数据,使用SqlRowSet会造成很大的内存消耗。

其他的JDBCTemplate:

NamedParameterJDBCTemplate:提供命名参数绑定功能

SimpleJDBCTemplate:将常用的API开放出来

先看一下xml配置文件:

<bean id="namedParamJdbcTemplate"
      class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
      <constructor-arg ref="dataSource"/>
</bean>

用法如下:

public void addForumByNamedParams(final Forum forum) {
    final String sql = "INSERT INTO t_forum(forum_name, forum_desc) VALUES(:forumName,:forumDesc)";
    // SqlParameterSource sps = new BeanPropertySqlParameterSource(forum);
    MapSqlParameterSource sps = new MapSqlParameterSource().
        addValue("forumName", forum.getForumName()).
        addValue("forumDesc", forum.getForumDesc());
    namedParameterJdbcTemplate.update(sql, sps);
}
分享到:
评论

相关推荐

    华为OD机试D卷 - 用连续自然数之和来表达整数 - 免费看解析和代码.html

    私信博主免费获取真题解析以及代码

    Screenshot_2024-05-10-20-21-01-857_com.chaoxing.mobile.jpg

    Screenshot_2024-05-10-20-21-01-857_com.chaoxing.mobile.jpg

    数字图像处理|Matlab-频域增强实验-彩色图像的频域滤波.zip

    数字图像处理|Matlab-频域增强实验-彩色图像的频域滤波.zip

    2024-2030中国定向转向膜市场现状研究分析与发展前景预测报告.docx

    2024-2030中国定向转向膜市场现状研究分析与发展前景预测报告

    开源工时填报管理系统安装包

    开源工时填报管理系统安装包

    激光雷达深度报告:产业化加速,国产供应链迎来投资机遇.pdf

    电子元件 电子行业 行业分析 数据分析 数据报告 行业报告

    node-v0.12.10-darwin-x86.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    18-17.网站域名DNS被劫持,网站服务器密码被改.mp4

    18-17.网站域名DNS被劫持,网站服务器密码被改.mp4

    QYResearch:2023年前五大2,3,3',4'-联苯四甲酸二酐(α-BPDA)企业占据全球91%的市场份额.docx

    QYResearch:2023年前五大2,3,3',4'-联苯四甲酸二酐(α-BPDA)企业占据全球91%的市场份额.docx

    2024-2030中国仿生智能餐饮机器人市场现状研究分析与发展前景预测报告.docx

    2024-2030中国仿生智能餐饮机器人市场现状研究分析与发展前景预测报告

    82-82.渗透测试-CVE-2017-8464“震网三代 反弹shell演示课件.mp4

    82-82.渗透测试-CVE-2017-8464“震网三代 反弹shell演示课件.mp4

    node-v6.11.5-darwin-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    33-33.渗透测试渗透测试之SQL注入基于报错注入(下)

    渗透测试渗透测试之SQL注入基于报错注入(下)

    基于Android的云游四海手机端应用.zip

    Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

    node-v4.8.0-sunos-x86.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    46-46.渗透测试-Kali Linux安全渗透.mp4

    46-46.渗透测试-Kali Linux安全渗透.mp4

    电子周跟踪:华为P70系列开售,台积电指引AI需求依旧强劲.pdf

    电子元件 电子行业 行业分析 数据分析 数据报告 行业报告

    node-v6.13.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    【名企实践】华为如何打造高绩效团队glq.pptx

    【名企实践】华为如何打造高绩效团队glq.pptx

    node-v4.9.1-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

Global site tag (gtag.js) - Google Analytics