JSP/Servlet基礎
許多同學學習框架的時候,往往會忽視這部分內容,有的甚至沒學JSP直接學習了框架,導致基礎知識不扎實,只是會用框架,最后連JSP一共有幾個內置對象都不知道。自己當時學的時候也沒怎么學這部分知識,就開始學Struts了,也是最近幾天又認真地把這部分知識看了一遍。
JSP和Servlet,區別上一個是Servlet沒有內置對象,還有就是JSP可以在HTML中嵌入Java代碼。而實際上,我們都知道,JSP最后也會被翻譯為Servlet.所以廣義的Servlet也可以指JSP+Servlet. 而JSP中的7個動作指令,9種內置對象,還有EL表達式,以及EL表達式的11個內置對象。都是我們必須要掌握的。
1.關于Cookie
Cookie用于網站記錄用戶的某些信息,它和session的區別在于:session是存放在服務器中,超出服務器設置的失效時間就會失效,而Cookie會一直存放在客戶端機器上,除非超出Cookie的生命期限。增加Cookie也是使用response內置對象完成的。事實上,用來實現session的sessionId也是存放在Cookie上,如果瀏覽器禁用了Cookie,同樣session也會失效。
(1)jQuery中操作Cookie
jQuery中操作Cookie非常簡單,要先下載jQuery的Cookie插件jquery.cookie.js.
增加Cookie:$.cookie("c1","zhazha");
將值"zhzha"寫入cookie名為c1的cookie中。
.cookie("c1","zhazha",{path: "/", expiress: 7});
創建一個有效期為7天,路徑與創建頁路徑一致的cookie. 刪除Cookie:
.cookie("c1");` 得到cookie名為c1的cookie的value值。
- 注:對于Chrome,使用本地測試時,cookie是基于域名來儲存的。要放到測試服務器上或者本地localhost服務器上才會生效。cookie具有不同域名下儲存不可共享的特性。單純的本地一個html頁面打開獲取cookie是無效的。可以使用IE瀏覽器或者火狐瀏覽器。
(2)利用response增加,刪除Cookie
Cookie c=new Cookie("username","name");
c.setMaxAge(24 * 3600);//設置生存期為24小時
response.addCookie(c);//增加Cookie
c.setMaxAge(0);//刪除Cookie
Struts
Struts是Web框架,學習Struts首先要理解MVC思想,即Model(模型)、View(視圖)和Controller(控制器)。學習Struts時間最長,也是在spring mvc之前用得最多的。Struts 2框架本身大致可以分為3個部分:核心控制器FilterDispatcher、業務控制器Action和用戶實現的企業業務邏輯組件。三個組件相互配合,完成各個邏輯功能。
1.Struts的MVC結構
剛想學習Struts的時候,常常有人要把之前用的三層結構和MVC對應起來。其實沒有必要,之前的三層架構和MVC結構還是有區別的。那么Struts的MVC分別指什么呢。
Model模型:這里的Model不只指我們項目Model層里的POJO對象。還包括Action對象,以及action調用的業務邏輯組件。
View視圖:顯然,視圖就是指我們的JSP頁面,以及Struts提供的標簽庫能夠與我們的ActionFrom(包括request,session)進行交互。
Controller控制器:控制其主要就是指Struts的ActionServlet和ActionMapping,也就是我們配置的struts.xml.
2.ValueStack和StackContext
學習OGNL的時候,對這兩個概念經常搞不清,總容易混淆。
ValueStack 稱之為值棧,可以理解為StackContext的根對象,在Action里,要有set和get方法。在使用OGNL時,若訪問的屬性屬于根對象,可以直接訪問該屬性,不用加'#'.
StackContext 叫做Stack的上下文,是整個OGNL的計算和求值的Context. 除了包含ValueStack這個根對象外,還包含一系列對象,包括request/session/application等。而訪問這些命名對象時,要加'#'.
3.jstl和struts標簽庫
一直糾結這兩個到底哪個好用,當然struts標簽庫只用應用與struts項目中。先學習過jstl,后來做項目的時候又一直用的struts的標簽庫,用起來感覺沒什么差別,后來結合富文本編輯器從后臺取數據的時候才發現,二者的取值方式不同。jstl取值的時候會轉換里面的html標簽,而struts標簽取值的時候只是把值當做字符串輸出到頁面。(后來發現struts標簽也可以通過設置escape='1',對html字符經行轉義,當然jstl也可設置對html不進行轉義,只是二者默認方式不同。但是Struts標簽的訪問速度要比jstl慢,效率低)
4.Struts的Ajax支持
自己做項目的時候最多用的就是jQuery中的Ajax的post函數,來實現異步請求。
用法:$.post("",{},function(data,textStatus){})
第一個引號里面傳一個URL,一般就是一個action路徑,第二個{}中傳一個JSON對象,如{a:1,b:2}這樣,把這個對象傳給后臺Action,后臺通過set和get方法得到a和b的值,第三個function是方法實現體。用來處理后臺傳送回的數據和前臺經行交互。
后臺通過response.getWriter.print("")
來向前臺傳遞數據,存放到function中的data里。這樣就實現了簡單的Ajax的異步請求。
Hibernate
Hibernate是位于持久層的ORM框架,ORM即對象/關系數據庫映射。Hibernate工作就是將數據庫中的關系型數據映射成Java對象。
由于Hibernate過于厚重,學習成本高,導致其逐漸被Mybatis取代。
當然Hibernate也有優點,比如一套hql可以適配所有數據庫,還有其緩存機制等都是優點。
由于Hibernate門檻較高,還是建議直接學習Mybatis.
Spring
作為應用范圍最廣的容器框架,無論走到哪基本都會用到Spring. Spring可以說是企業應用開發的不二之選,Spring貫穿表現層,業務層,持久層。并且能以高度的開放性與他們無縫整合。
Spring的核心是IOC(控制反轉),DI(依賴注入)和AOP(面向切面的編程)。實際上,IOC和DI是同一個概念,只是spring設計者認為DI能更準確表示Spring核心技術。
1.IOC/DI
IOC的思想最核心的地方在于,資源不由使用資源的雙方管理,而由不使用資源的第三方管理,這可以帶來很多好處。第一,資源集中管理,實現資源的可配置和易管理。第二,降低了使用資源雙方的依賴程度,也就是耦合度。
2.AOP
AOP思想能從程序運行角度考慮程序的流程,提取業務處理過程的切面。其有著各個步驟之間有良好的隔離性,源代碼無關性的特性。可以這樣理解,可以把代碼看成一坨面,同樣用刀來切面,切完了,想在前面、中間、后面或者四周放些“香料”什么的隨便你。你只要把這把刀實現好就行了。AOP面向的是程序運行中各個步驟,希望以更好的方式來組合業務處理的各個步驟。
SSH 整合開發
1.Spring整合Struts2
Spring整合Struts2有兩種策略,一種是讓Spring管理控制器,一種是使用Spring的自動裝備。兩種方式各有優缺點。本人應用的是第二種,即使用自動裝備策略。
(1)首先載入配置文件
在web.xml中加入以下信息。當然如果你使用IDEA開發時,這些都是已經自動生成好的。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
(2)配置struts.xml
由于使用自動裝配策略,所以struts.xml的配置方式和原來一模一樣。即和在沒有Spring整合之前的配置方式一樣。
(3)注入Action中的Service組件。
在applicationContext.xml中配置Service的Bean,其中Bean的id與Action定義的Service中其getService中的名字一樣。例如:
public UserService us;
public UserService getUs() {
return us;
}
public void setUs(UserService us) {
this.us = us;
}
如果定義了這樣一個Service,那么bean id也應該設置為us
,即:
<bean id="us" class="com.service.serviceimpl.UserServiceImpl"/>
2.Spring整合Hibernate
(1)配置管理SessionFactory.
在applicationContext.xml中配置以下信息,例子中包含兩個POJO,即User和Friend.
<!--使用c3p0配置數據源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://localhost/friends"
p:user="root"
p:password="123"
p:maxPoolSize="40"
p:minPoolSize="2"
p:initialPoolSize="2"
p:maxIdleTime="30"/>
<!--配置SeesionFactory,注入數據源(dataSource)-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="dataSource">
<property name="annotatedClasses">
<list>
<value>com.models.User</value>
<value>com.models.Friend</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQL5InnoDBDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">
update
</prop>
</props>
</property>
</bean>
(2)定義DAO組件,并將SessionFactory注入DAO組件。
以下代碼含有兩個DAO組件,即UserDao和FriendDao.
<bean id="ud" class="com.dao.impl.UserDaoImpl" p:sessionFactory-ref="sessionFactory"/>
<bean id="fd" class="com.dao.impl.FriendDaoImpl" p:sessionFactory-ref="sessionFactory"/>
(3)定義Service組件,并將DAO組件注入Service組件。
同理,以下代碼含有兩個Service組件,UserService和FriendService
<bean id="us" class="com.service.impl.UserServiceImpl" p:ud-ref="ud" p:fd-ref="fd"/>
<bean id="fs" class="com.service.impl.FriendServiceImpl" p:fd-ref="fd"/>
(4)配置事務管理器
注:若寫入tx報錯,說明你沒有導入相應的xmlns.
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="myPointcut" expression="bean(us)||bean(fs)"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
</aop:config>
這樣只要在Action中定義Service組件,在Service中定義DAO組件,生成set和get方法,這樣,一個SSH項目就搭建好了。
Mybatis
相對于厚重的Hibernate, Mybatis就比較好掌握了。就算沒看過Hibernate的新手,看看文檔,讀讀Demo,兩天基本就可以掌握上手了。Mybatis實際上是一個不完全的ORM框架,他主要完成的可以說是輸入和輸出映射。需要手動寫sql語句,就簡單的增刪改查來說,個人更喜歡Hibernate. 覺得比Mybatis操作簡單,能讓讓人更加專注于寫業務邏輯。而學習了Mybatis的高級映射和緩存機制后,確實感覺很簡單,比Hibernate容易理解。尤其是學完逆向工程之后,發現Mybatis也可以如此輕松。
1.Mybatis與Hibernate的比較
Mybatis優勢
(1).MyBatis可以進行更為細致的SQL優化,可以減少查詢字段。
(2).MyBatis容易掌握,而Hibernate門檻較高。
Hibernate優勢
(1).Hibernate的DAO層開發比MyBatis簡單,Mybatis需要維護SQL和結果映射。
(2).Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。
(3).Hibernate數據庫移植性很好,MyBatis的數據庫移植性不好,不同的數據庫需要寫不同SQL。
(4).Hibernate有更好的二級緩存機制,可以使用第三方緩存。MyBatis本身提供的緩存機制不佳。
他人總結
(1).Hibernate功能強大,數據庫無關性好,O/R映射能力強,如果你對Hibernate相當精通,而且對Hibernate進行了適當的封裝,那么你的項目整個持久層代碼會相當簡單,需要寫的代碼很少,開發速度很快,非常爽。
(2).Hibernate的缺點就是學習門檻不低,要精通門檻更高,而且怎么設計O/R映射,在性能和對象模型之間如何權衡取得平衡,以及怎樣用好Hibernate方面需要你的經驗和能力都很強才行。
(3).Mybatis入門簡單,即學即用,提供了數據庫查詢的自動對象綁定功能,而且延續了很好的SQL使用經驗,對于沒有那么高的對象模型要求的項目來說,相當完美。
(4).Mybatis的缺點就是框架還是比較簡陋,功能尚有缺失,雖然簡化了數據綁定代碼,但是整個底層數據庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應快速數據庫修改。
- 注:以上內容摘自知乎
2.Mybatis的分頁
分頁是Mybatis的一個弱項,不能像Hibernate那樣直接有分頁的方法供你調用。而自己通過寫sql語句來寫分頁也是個苦力活,很麻煩,所以我強烈向大家推薦一款插件:PageHelper. 來自OSChina社區的某位自己寫的插件,無論是配置還是操作都超級簡單,愛不釋手。
3.Mybatis的逆向工程
Mybatis需要我們自己寫sql語句,每張表的增刪改查無疑給我們帶來了巨大的工作量,所以項目中一般使用Mybatis的逆向工程工具,自動生成Java代碼,為我們提供豐富的操作數據庫的功能。
(1)使用之前需要先下載用于支持逆向工程的jar包
點擊下載,網上的方法都是基于Maven或者用的是Eclipse的插件。自己使用IDEA開發的,所以用的是第三種方法,通過配置xml文件,通過運行它提供主程序生成Java代碼。當然,用第一種方法也行。
(2)配置generatorConfig.xml
配置要求以下代碼中注釋寫的很清楚
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自動生成的注釋 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--數據庫連接的信息:驅動類、連接地址、用戶名、密碼 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/friends" userId="root"
password="123">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO類的位置 -->
<javaModelGenerator targetPackage="com.models"
targetProject=".\src">
<!-- enableSubPackages:是否讓schema作為包的后綴 -->
<property name="enableSubPackages" value="false" />
<!-- 從數據庫返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否讓schema作為包的后綴 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否讓schema作為包的后綴 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定數據庫表 -->
<table tableName="user"></table>
<table tableName="friend"></table>
</context>
</generatorConfiguration>
(3)運行GeneratorSqlmap
以下代碼只需要修改generatorConfig.xml的位置
package com.service;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class GeneratorSqlmap {
public void generator() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
這樣所有的model和mapping就自動生成好了,具體的用法看代碼,有的看方法名就能直接看出他的用法,其中的selectByExample類似于Hibernate的Criteria, 也就是按條件查詢。用法也很簡單,就不演示了。
Spring mvc
作為替代Struts2的另一個web框架,Spring mvc當然有它的優勢。剛接觸Spring mvc時,為了理解Spring mvc的結構,要接觸許多名詞,往往搞得我們頭疼。包括前端控制器,處理器映射器,處理器適配器,以及視圖解析器。所以我們首先要了解Spring mvc的工作流程。
1.Spring mvc的工作流程
(1)瀏覽器發起請求到前端控制器(DispatcherServlet)
(2)前端控制器請求HandlerMapping查找 Handler
(3)處理器映射器HandlerMapping向前端控制器返回Handler
(4)處理器適配器執行Handler并返回ModelAndView
(5)視圖解析器向前端控制器返回View
(6)前端控制器進行視圖渲染
2.關于@RequestParam
真正做項目時,@RequestParam是必須配置的,即使你傳入的參數名和你的形參名一樣也配置,因為在Eclipse的Debug模式下編譯時,參數名都會保留在class文件中,spring由此可以反射綁定。而自己使用的IDEA,無論怎么調試怎樣都得不到前面傳過來的值,調了很長時間,只有加上@RequestParam(value = "username") String username
這樣的同名注解才行,即使文檔里說可以省略。
3.Spring mvc的優勢
(1)學習完Spring mvc之后可以發現,Spring mvc是基于于方法開發的,所有需要的參數都通過Controller里面的方法形參進行傳遞,而Struts是基于于類開發的。這種基于方法的Controller開發更類似于Service開發,邏輯上更符合我們的編程邏輯。
(2)由于Struts的標簽庫,導致Struts的效率要低于Spring mvc.
(3)Struts有安全漏洞,Spring mvc沒有發現安全隱患。
SSM 整合開發
項目結構:src下一共四個包,com.models, com.mapper, com.service, com.controller. 其中com.models包含兩個POJO對象User和Friend. com.models和com.mapper均由mybatis逆向工程自動生成。
1.配置web.xml
這個很簡單,如果使用IDEA開發,這些都是自動生成好的。例子中除了Mapper的xml一共包含三個xml,即WEB-INF下的applicationContext.xml和dispatcher-servlet.xml. 以及src下的sqlMapConfig.xml.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
2.配置sqlMapConfig.xml
這里我只給model配置了一個別名,可以根據需要自行配制,例如可以配置二級緩存。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置別名-->
<typeAliases>
<package name="com.models"/>
</typeAliases>
</configuration>
3.配置applicationContext.xml
這里的配置方式和整合SSH的配置方式類似
<!--使用c3p0配置數據源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://localhost/friends"
p:user="root"
p:password="123"
p:maxPoolSize="40"
p:minPoolSize="2"
p:initialPoolSize="2"
p:maxIdleTime="30"/>
<!--配置sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
</bean>
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.mapper.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="friendMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.mapper.FriendMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="us" class="com.service.impl.UserServiceImpl" p:userMapper-ref="userMapper"/>
<bean id="fs" class="com.service.impl.FriendServiceImpl" p:friendMapper-ref="friendMapper"/>
<!--配置事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="myPointcut" expression="bean(us)||bean(fs)"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
</aop:config>
3.配置dispatcher-servlet.xml
<!--配置Handler-->
<bean class="com.controller.UserController" p:us-ref="us"/>
<bean class="com.controller.FriendController" p:fs-ref="fs"/>
<!--配置使用注解開發方式-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--配置視圖解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
這樣配置好之后,同樣的,只要在Service層添加Mapper對象,在Controller層添加Service對象,這樣一個SSM項目就搭建好了。
總結:
利用這個假期把Spring,Mybatis,Spring mvc過了一遍,有些感悟與體會。希望上面的內容能對看的人有所幫助,還有上面關于概念的理解與對比也是經常被問,經常讓人困惑的,愿學有所成。