`

让Struts与Hibernate顺利协同工作

 
阅读更多
 安装篇

  一,下载安装 j2sdk1.4(www.sun.com))或以上,设置 CLASSPATH,java_home。

  二,下载服务器,免费版本的有 tomcat,resin,当然也还有 weblogic之类的巨无霸,不过得看你电脑的配置是否承受的了!

  这里只以resin来说明,其他的配置都差不多,可以查看各个服务器自带的说明文件。

  resin 服务器可以在 caucho.com下载,选择合适的版本,下载解压缩就可以直接使用。

  这里resin有一个 resin-ee版本,这个主要是带ejb功能支持的。 如果用不到ejb,一般的就足够了。
  三,然后就是数据库,有很多数据库产品可以选择,DB2,Oracle,MSSQL,MySQL等等太多了。这里我选择MySQL,不仅因为它是免费的,而且它的4.0版本在继承以前版本的快速稳定的基础上,整合了InnoDB(http://www.innodb.com)先进的事务处理机制。相信伴随着Linux的壮大,它将在商业数据库市场占的一席之地。不过就数据库本身,它还缺少子查询等强大功能的支持。
安装就不多说了,配置好用户名,密码。 然后就可以下载 MySQL-Front 来可视化操作数据库。

  四,在Java编程上,一个IDE的功能显然不可缺少,现在流行的IDE很多,有JBuilder,Eclipse,IntellJ IDEA,JCreator等等,其中 eclipse借着开源东风,依靠强大的插件功能被誉为最有前途的工具,JBuilder从来都最强大功能的java工具,不过大到我的电脑实在运行不了,穷啊,可没钱配新电脑。所以我还是喜欢JCreator,小巧而又功能不俗,应付小规模的应用绰绰有余。编译开发时要想获得提示支持,需要在 configure--option--JDK Profiles 导入jar文件。

  五,一个站点前台的界面开发,当然离不开大名鼎鼎的 Dreamweaver 了,它支持jsp,asp等很多语言的开发。特别是最近的Dreamweaver MX 2004 增强了站点的功能,可以方便的对一个站点进行控制。面对struts的前台自定义标签,有一个mxp插件可以用来支持显示sturts的标签。使用前还要在编辑--标签库 里面导入.tld文件,目前只支持html,和bean 两个标签。

  配置篇

  一,resin虚拟站点配置

<host id='yourweb:8080' app-dir='e:/blog/' class-update-interval='2'>
<web-app id='/'>
<directory-servlet id='false'/>
</web-app>
<error-log id='log/web-error.log'/>
<host>

  然后在定义的目录下面建立站点。

  二,Dreamweaver站点的配置就不多说了。

  三,Struts的配置

  这里我们使用的是struts1.1,下载并解压缩到临时文件夹,就假设是tem文件夹吧。

  首先拷贝tem/lib/下面所有的.tld文件到站点的/WEB-INF/目录下,再拷贝所有的.jar文件到/WEB-INF/lib/目录下,最后web.xml文件中的配置差不多如下:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>


<!-- The Usual Welcome File List -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>


<!-- Struts Tag Library Descriptors -->
<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>/tags/struts-logic</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>/tags/struts-nested</taglib-uri>
<taglib-location>/WEB-INF/struts-nested.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>/tags/struts-tiles</taglib-uri>
<taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
</taglib>

</web-app>

  四,Hibernate配置

  下载并拷贝/lib目录下的

hibernate2.jar
commons-beanutils.jar
commons-collections.jar
commons-dbcp.jar
commons-lang.jar
commons-logging.jar
commons-pool.jar
dom4j.jar
cglib-asm.jar
connector.jar

  到应用站点的/lib目录下。接下来配置 hibernate.cfg.xml文件

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>

<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/yourdatabase
</property>
<property name="hibernate.connection.driver_class">
org.gjt.mm.mysql.Driver
</property>
<property name="hibernate.connection.username">
yourname
</property>
<property name="hibernate.connection.password">
youyrpassword
</property>

<!?- 是否将运行期生成的SQL输出到日志以供调试-->
<property name="show_sql">false</property>

<!--dialect ,每个数据库都有其对应的Dialet以匹配其平台特性-->
<propertyname="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!?- 事务管理类型,这里我们使用JDBC Transaction -->
<property name="transaction.factory_class">
net.sf.hibernate.transaction.JDBCTransactionFactory</property>

<property name="jdbc.batch_size">10</property>
<property name="jdbc.use_scrollable_resultset">true</property>

<!?映射文件配置,注意配置文件名必须包含其相对于根的全路径-->
<mapping resource="net/seerlog/hbm/Cat.hbm.xml"/>

</session-factory>

</hibernate-configuration>

  以上配置了数据库连接所用的地址和用户名,密码等。具体参数的含义请参考官方文档。

  映射文件的内容可以手工来写,也可通过一些工具来自动生成。

  整个需要两种文件: .hbm.xml配置文件 和 .java持久化对象 , 两者是相互关联的,.hbm.xml 对数据库的映射还需要 .java这个bean来操作。所以整个过程需要首先设计好数据库,然后根据数据库导出 .hbm.xml文件 ,然后再导出 .java 文件。 有很多工具可以实现这个工程,我们这里采用 Middlegen-Hibernate来实现 数据库到.hbm.xml文件的转化,用Hibernate-Extension工具包中的 hbm2java 来实现 .hbm.xml 到 .java 文件的转化!



  查找关键字”!ENTITY”,得到:

<!DOCTYPE project [
<!ENTITY database SYSTEM
"file:./config/database/hsqldb.xml">
]>

  b) Application name

<property name="name" value="airline"/>

  c) 输出目录

  查找关键字“name="build.gen-src.dir"”,得到:

<property name="build.gen-src.dir" value="${build.dir}/gen-src"/>

  d) 对应代码的Package name

<hibernate
destination="${build.gen-src.dir}"
package="${name}.hibernate"
genXDocletTags="false"
genIntergratedCompositeKeys="false"
javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"
/>

  配置完成后,在MiddleGen 根目录下运行ant,就将出现MiddleGen的界面:

  选择需要的表,单击窗口顶部的Generate 按钮,MiddleGen 即为我们生成这些数据库表所对应的Hibernate映射文件。

  接下来的工作通过Hibernate Extension 来完成,Hibernate Extension 的tools/bin目录下包含三个工具:

  1. hbm2java.bat

  根据映射文件生成对应的POJO。通过MiddleGen 我们已经得到了映射文件,下一步就是通过hbm2java.bat工具生成对应的POJO。

  2. class2hbm.bat

  根据POJO class 生成映射文件,这个工具很少用到,这里也就不再详细介绍。

  3. ddl2hbm.bat

  由数据库导出库表结构,并生成映射文件以及POJO。这个功能与MiddleGen的功能重叠,但由于目前还不够成熟(实际上已经被废弃,不再维护),提供的功能也有限,所以我们还是采用MiddleGen生成映射文件,之后由hbm2java根据映射文件生成POJO 的方式。

  这里我们使用第一个hbm2java.bat,利用刚才生成的.hbm.xml文件自动生成 java 文件。

  为了使用这个工具,首先我们需要配置一些参数,打开tools/bin/setenv.bat 文件,修改其中的JDBC_DRIVER和HIBERNATE_HOME环境变量,使其指向我们的实际JDBC Driver文件和Hibernate所在目录。同时检查一下环境变量CP中的各个项目中是否实际存在,特别是%CORELIB%下的jar文件,某些版本的发行包中,默认配置中的文件名与实际的文件名有所出入(如%CORELIB%/commons-logging.jar, 在Hibernate 发行包中,可能实际的文件名是commons-logging-1.0.3.jar,诸如此类)。

  使用hbm2java,根据MiddleGen生成的映射文件生成Java 代码:

  打开Command Window,在tools/bin目录下执行:

hbm2java c:/sample/org/hibernate/sample/*.xml --output=c:/sample/

  通过以上步骤我们就生成了所需要的所有基本配置文件。接下来就可以来初始化这些配置啦。

  实战篇

  在这一节我们要配置一个完整的应用配置。其实每一个单独拿出来都能写本书,不过我只是侧重对自己总结,在以后我会不断地把学习的经验教训写下来。

  一,Log4j 的初始化

  配置log4j.properties

### direct log messages to stdout ###
#log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout.Target=System.out
#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
%c{1}:%L - %m%n
#log4j.appender.stdout.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %l%n%m%n
log4j.logger.seerlog=DEBUG,A2
log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A2.file=d://log//applog.txt
log4j.appender.A2.DatePattern='.'yyyy-MM-dd
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %m%n

#log4j.logger.ALL=DEBUG,A1
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.file=d://log//all.log
log4j.appender.A1.DatePattern='.'yyyy-MM-dd
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %l%n%m%n

### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

###log4j.rootLogger=warn, stdout
log4j.rootLogger=info, A1

#以下是hibernate API需要的配置

log4j.logger.net.sf.hibernate=info

### log just the SQL
#log4j.logger.net.sf.hibernate.SQL=debug

### log JDBC bind parameters ###
log4j.logger.net.sf.hibernate.type=info

### log schema export/update ###
log4j.logger.net.sf.hibernate.tool.hbm2ddl=debug

### log cache activity ###
#log4j.logger.net.sf.hibernate.cache=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.net.sf.hibernate.connection.DriverManagerConnectionProvider=trac

  配置后如下来调用,首先需要初始化配置文件,这个过程只需要一次,所以我们可以在ServletContextListener中来进行。

String prefix = context.getRealPath("/");
PropertyConfigurator.configure(prefix+"/WEB-INF/classes/log4j.properties");

  这里需要你的配置文件的路径来初始化。

  初始化完成后,我们在以后的action中就可以 象下面一样来调用:

static Logger log=Logger.getLogger("seerlog");
log.warn("it's log4j warn");
log.info("it's log4j info");

  关于 log4j 的完全使用方法,偶会在以后做详细的说明!

  二,hibernate 的初始化

  首先我们要把hibernate.cfg.xml 放到应用的 classes 目录中,然后可以使用hibernate参考文档提供的例子来封装对后台的使用。

public class Hi{

private static final SessionFactory sessionFactory;
private static Connection conn;
static {
 try {
  sessionFactory = new Configuration().configure().buildSessionFactory();
 } catch (HibernateException ex) {
  throw new RuntimeException("Exception building SessionFactory: " + ex.getMessage(), ex);
 }
}

public static final ThreadLocal session = new ThreadLocal();
public static Session getSession() throws HibernateException {
 Session s = (Session) session.get();
 // 假如没有一个可用的线程,开启一个新 Session,
 if (s == null) {
  conn=DBConnectionManager.getConnection();
  s = sessionFactory.openSession(conn);
  session.set(s);
 }
 return s;
}

public static void closeSession() throws HibernateException {
 Session s = (Session) session.get();
 session.set(null);
 if (s != null)
  s.close();
 if(conn!=null)
  DBConnectionManager.returnConnection(conn);
 }
}

  文中DBConnectionManager.getConnection()是一个DAO类,提供连接池的实现。

  我们使用这个con连接来创建一个 session ,sission是一个数据库连接操作的会话周期,它提供了强大的管理数据的能力。

  以后我们在action的 execute 方法中就可以使用 Hi.getSession()来获得一个会话支持。典型的应用如下:

try{
 //开启一个会话,并启动事务回滚能力
 Session session = Hi.getSession();
 Transaction tx= session.beginTransaction();

 //查询数据库,使用HQL
 Query q = session.createQuery("from Topic as topic order by topic.id desc");
 q.setFirstResult(0);
 q.setMaxResults(5);

 //得到一个List类型的数据
 List newTopicList = q.list();

 // 业务处理
 NewTopicList ntlBean=new NewTopicList();
 ntlBean.setList(newTopicList);
 req.setAttribute("newtopiclist",ntlBean);

 //事务提交,记得关闭会话!
 tx.commit();
 Hi.closeSession();

}//因为整个会话会抛出异常,所以需要用try--catch来包裹
catch(HibernateException e){

 //日志记录
 Log.error(e.toString());
}

  其中的HQL 可以参考 hibernate 官方文档来学习。

 三,Struts

  struts 的配置文件 struts-config.xml 放在 应用的 /WEB-INF/目录下面,大致的配置如下

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
<struts-config>

<form-beans>
<form-bean name="loginForm" type="net.seerlog.vo.LoginForm"/>
<form-bean name="replyForm" type="net.seerlog.vo.ReplyForm"/>
</form-beans>

<global-forwards>
<forward name="index" path="/first.jsp"/>
</global-forwards>

<action-mappings>

<action path="/login" type="net.seerlog.action.LoginAction" scope="request" name="loginForm" input="/login.jsp">
<forward name="success" path="/success.jsp"/>
</action>

<action path="/blog" type="net.seerlog.action.BlogAction" scope="request">
<forward name="success" path="/sublog.jsp"/>
</action>

<action path="/topic" type="net.seerlog.action.TopicAction" scope="request">
<forward name="success" path="/sutopic.jsp"/>
</action>

<action path="/posttopic" type="net.seerlog.action.PostTopicAction" scope="request" >
</action>

<action path="/postreply" type="net.seerlog.action.PostReplyAction" scope="request" name="replyForm" input="/sublog.jsp">
</action>

<action path="/index" type="net.seerlog.action.IndexAction" scope="request">
</action>

</action-mappings>

<message-resources parameter="resouse.application">
</message-resources>
</struts-config>

  这里的配置有一个可视化工具叫做 struts-console,目前版本4.8,网上可以免费下载的到。

  配置文件其实不用去记,需要时参考一下,拷贝一个过来修改一下即可。只是这里的主要是在于设计 ,设计好有什么formbean,什么action,他们的关系,等等问题。一个好的设计绝对能为后期节省大量的返工可能性。struts有一本《struts on action》,绝对是学习struts的经典书籍,我手上有翻译的前8章,有需要的可以联系我。

  我们这里不详细说明各个配置,只讲struts 和hibernate 合作的过程。

  一个action 有一个 execute 方法,当然也可以用 perform方法,不过 perform 方法 在struts1.1已经不推荐使用了,而使用了更强大的execute()方法。 package net.seerlog.action;

//导入所有用的到的包
import java.util.List;

import net.seerlog.po.*;
import net.seerlog.vo.*;
import net.seerlog.util.*;

import net.sf.hibernate.*;

import org.apache.struts.action.*;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import javax.servlet.ServletException;

public class IndexAction extends Action{

 //action的主体方法 execute ,注意要抛出异常
 public ActionForward execute (ActionMapping mapping,ActionForm form,HttpServletRequest req,
HttpServletResponse res) throws IOException, ServletException{
  try{
   //开启会话
   Session session = Hi.getSession();
   Transaction tx= session.beginTransaction();
   //查询
   Query q = session.createQuery("from Topic as topic order by topic.id desc");
   q.setFirstResult(0);
   q.setMaxResults(5);
   List newTopicList = q.list();

   NewTopicList ntlBean=new NewTopicList();
   ntlBean.setList(newTopicList);
   req.setAttribute("newtopiclist",ntlBean);

   //事务提交,关闭session
   tx.commit();
   Hi.closeSession();

   //捕获异常
  }catch(HibernateException e){
   Log.error(e.toString()); //日志记录
 }

 //返回一个 actionForward 对象
 return mapping.findForward("index");
}

}

  以上就是 struts hibernate协同工作的全部内容了,这篇文章只能让你了解整个过程,这里的例子不能作为实现的学习例子。

分享到:
评论

相关推荐

    spring_struts_hibernate整合开发书籍

    书中会详细讲述如何配置这些框架,使它们协同工作,包括Spring与Hibernate的事务管理、数据源配置、以及Struts2与Spring的整合等。 除此之外,书中还可能涵盖了单元测试、异常处理、安全性配置等方面的内容,这些都...

    struts+hibernate做的商城

    Struts和Hibernate是两种在Java Web开发中广泛使用的开源框架,它们共同构成了许多企业级应用...对于学习Java Web开发的人员,这是一个极好的实战案例,有助于理解这两个框架的协同工作方式以及如何应用于实际项目中。

    struts+hibernate实现在线音乐系统源码

    通过阅读和分析代码,可以深入理解Struts和Hibernate如何协同工作,如何处理Web请求,以及如何设计和实现一个完整的Web应用。此外,对于想了解音乐服务后台处理机制的开发者,这个项目也是一个很好的参考实例。 ...

    struts2与Hibernate整合

    **Struts2整合Hibernate**的核心目标是将这两者结合起来,实现业务逻辑层和数据访问层的高效协同工作。在本实例中,我们将使用Eclipse作为开发环境,Tomcat6.0作为应用服务器,MySQL作为数据库系统。以下是对这个...

    struts和hibernate注册

    本篇将深入探讨这两个框架以及它们如何协同工作来实现数据库的简单插入操作。 **Struts框架** Struts是一个开源的MVC框架,它提供了构建Web应用程序的结构和规范。在Struts中,模型负责业务逻辑,视图负责用户界面...

    struts.hibernate工作流程

    这两个框架协同工作时,Struts处理用户的请求,调用业务逻辑,而Hibernate负责数据的持久化操作。Struts的Action可以通过依赖注入(DI)或服务定位器模式获取Hibernate的SessionFactory,进而创建Session进行数据库...

    简单Struts+Hibernate实例

    在这个"简单Struts+Hibernate实例"中,我们将深入探讨这两个框架如何协同工作以构建高效、灵活的J2EE应用。 首先,让我们了解一下Struts。Struts框架提供了丰富的控制器组件,如Action和ActionForm,用于处理用户...

    JSP源码——Struts+Hibernate实现MVC_strutsmvc.zip

    下面将详细阐述Struts和Hibernate的核心概念以及它们如何协同工作。 **Struts框架**: 1. **MVC模式**:Struts是一个基于MVC设计模式的开源框架,它将业务逻辑、数据和用户界面分离,使得代码更易于维护和扩展。 2....

    struts +hibernate 电子留言系统

    Spring作为中间件,提供依赖注入(DI)和面向切面编程(AOP)等功能,使得Struts和Hibernate可以更好地协同工作。在电子留言系统中,Spring可能用于管理Struts的Action和Hibernate的SessionFactory,提供事务管理等...

    基于Struts+Hibernate论坛系统

    总结,基于Struts和Hibernate的论坛系统是Java Web开发中一个典型的实例,它充分展示了这两种框架的协同工作能力,为开发者提供了高效、可扩展的平台,使得构建大型的、功能丰富的论坛应用成为可能。

    struts+hibernate开发的项目源代码集合

    通过学习和分析这些源代码,开发者可以了解到如何在实际项目中有效地结合Struts和Hibernate,提高开发效率,同时也能深入理解这两种框架的协同工作原理。这对于提升Java Web开发技能和解决实际问题非常有帮助。

    struts+hibernate实例 网上书店

    Struts框架会处理这些请求,调用相应的业务逻辑(可能包含在Action类中),而Hibernate则负责与数据库交互,进行数据的增删改查。 总的来说,这个"struts+hibernate实例 网上书店"项目是一个典型的Java Web开发案例...

    Struts+hibernate+spring学习实例

    7. 整合配置:在struts-config.xml、hibernate.cfg.xml和Spring的配置文件(如applicationContext.xml)中,正确配置各个组件,使它们能协同工作。 8. 错误和异常处理:设计合适的错误页面和异常处理器,处理可能...

    Struts+Hibernate实现用户登录案例

    在Java Web开发中,"Struts+Hibernate实现用户登录案例"是一个常见的应用场景,它结合了两个重要的...通过实际操作,可以深入理解Struts和Hibernate如何协同工作,为Web应用程序提供高效的数据访问和业务逻辑处理能力。

    JavaEE struts2 Hibernate结合贴吧小案例

    这样,Struts2负责处理用户交互,Hibernate则负责数据管理,两者协同工作,极大地提高了开发效率和代码的可维护性。 在"Day01_Tieba"文件中,可能包含了项目的源代码、配置文件、数据库脚本等。源代码中,Action类...

    struts和hibernate 用户登录示例

    Struts和Hibernate是Java开发中两个非常重要的框架,它们在构建Web应用程序时起着关键作用。...这个"用户登录示例"提供了实践经验,让初学者能够深入理解这两个框架的协同工作方式,从而提升他们的技能。

    Struts+Hibernate+Ajax注册示例

    Struts、Hibernate和Ajax是Java Web开发中的三个关键框架,它们各自解决不同的问题,并且可以协同工作以构建高效、功能丰富的应用程序。在这个“Struts+Hibernate+Ajax注册示例”中,我们将深入探讨这三个技术如何...

    jsp+JavaScript+struts+hibernate+css+mysql的网上书店

    这不仅有助于理解各技术间的协同工作,也有助于提高JavaWeb开发技能。对于初学者,这是一个很好的实践项目,可以加深对JavaWeb开发流程的理解;对于有经验的开发者,这也可以作为一个参考案例,了解如何在实际项目中...

    springMVC+struts+hibernate

    Spring MVC、Struts和Hibernate是Java Web开发中的三个重要框架,它们各自负责应用程序的不同层面,协同工作以构建高效的企业级应用。Spring MVC是Spring框架的一部分,主要处理HTTP请求和响应,提供模型-视图-控制...

Global site tag (gtag.js) - Google Analytics