一、配置文件
1. 兩種注解掃描的區別
1.1 使用MapperScannerConfigurer
類
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 掃描映射文件比如:AccountMapper.xml 加載該文件; 還會掃描接口AccountMapper接口創建代理對象 -->
<property name="basePackage" value="com.lagou.mapper"/>
</bean>
1.2 使用context:component-scan
標簽
<context:component-scan base-package="com.lagou.service"/>
區別:
第一種方法的作用有兩個:第一個是加載com.lagou.mapper
包下的xxxMapper.xml
文件;第二個作用是為該包下的接口創建代理對象,存放在IOC容器中;通常是用在dao層,為該層中的接口創建動態代理對象。
第二種方法的作用是對com.lagou.service
包下的類創建實例對象放到IOC容器中;通常用在service層,為該層下的實現類創建對象。
2. 各層配置文件的加載位置
2.1 mybatis配置文件
在spring配置文件中創建SqlSessionFactoryBean
實例對象的時候引入mybatis配置文件。
<bean id="sqlSesionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入連接池, public void setDataSource(DataSource dataSource){...}-->
<property name="dataSource" ref="dataSource"/>
<!-- 加載mybatis-config.xml
public void setConfiguration(Configuration configuration) {this.configuration = configuration;}
因為在SqlSessionFactoryBean類中有configuration的set方法,所以可以使用property來注入
-->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
</bean>
2.2 spring配置文件
在web.xml
配置文件中創建監聽器的時候加載spring所有的配置文件(如果spring配置文件是根據層分別創建的)
<!--監聽器,加載spring所有的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2.3 加載springMVC配置文件
在web.xml
配置文件中創建前端控制器的時候加載springmvc的配置文件
<!--前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc/springmvc.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3. 加載properties配置文件
3.1 方式一
<properties resource="jdbc.properties"></properties>
3.2 方式二
<!--需要引入context命名空間-->
<context:property-placeholder location="classpath:jdbc.properties"/>
4. 加載映射配置文件
4.1 mybatis核心配置文件加載映射配置文件
<mappers>
<!--:class屬性的方式
注意:這種方式下xml文件的位置一定要和接口的位置同包同名
比如:接口包是com.lagou.mapper,那么UserMapper.xml的位置也應該是在com.lagou.mapper下
-->
<mapper class="com.lagou.mapper.UserMapper"></mapper>
</mappers>
4.2 spring核心配置文件加載映射配置文件
<!--Mapper包掃描-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 掃描映射文件比如:AccountMapper.xml 加載該文件; 還會掃描接口AccountMapper接口創建代理對象 -->
<property name="basePackage" value="com.lagou.mapper"/>
</bean>
二、SSM
1. mybatis多條件查詢
1.1 重要標簽
resultMap
標簽
在實體屬性名與表中屬性名不一致的時候,使用該標簽進行映射。
1.2 多條件查詢
適用於接口方法的參數有多個的情況
方式一
在XXXMapper.xml配置文件中需要使用到#{arg0}
或者#{param1}
<select id="findByIdAndUsername1" resultType="com.lagou.domain.User">
select * from user where id = #{arg0} and username = #{arg1}
</select>
方式二
使用注解,引入 @Params() 注解獲取參數
//接口中,方法的參數使用@Params()注解
public User findByIdAndName(@Params("id") int id, @(Params"username") String username);
<!--配置文件中直接使用注解中指定的名字-->
<select id="findByIdAndUsername1" resultType="com.lagou.domain.User">
select * from user where id = #{id} and username = #{username}
</select>
方式三(推薦)
使用pojo對象的方式,將查詢的結果封裝到實體。因此接口中的方法的參數也是一個實體對象。
public User findByIdAndName(User user);
<select id="findByIdAndUsername3" parameterType="com.lagou.domain.User" resultType="com.lagou.domain.User">
<!--注意,這里#{}里面的值就需要和實體的屬性名保持一致了-->
select * from user where id = #{id} and username = #{username}
</select>
2. mybatis多表查詢
2.1 聯合查詢
2.1.1 一對一查詢
association
標簽、resultZMap
標簽 結合使用
<resultMap id="orderMap" type="com.lagou.domain.Order">
<id column="id" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="money" property="money"></result>
<!--
一對一(多對一)使用association標簽關聯
property="user" 封裝實體的屬性名
javaType="user" 封裝實體的屬性類型
-->
<association property="user" javaType="com.lagou.domain.User">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="sex" property="sex"></result>
<result column="address" property="address"></result>
</association>
</resultMap>
2.1.2 一對多查詢
collection
標簽、resultMap
標簽結合使用
<resultMap id="userMap" type="com.lagou.domain.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="sex" property="sex"></result>
<result column="address" property="address"></result>
<!--
一對多使用collection標簽關聯
property="orderList" 封裝到集合的屬性名
ofType="order" 封裝集合的泛型類型
-->
<collection property="orderList" ofType="com.lagou.domain.Order">
<id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="money" property="money"></result>
</collection>
</resultMap>
2.1.2 多對多查詢
同一對多查詢差不多,只是在編寫SQL語句的時候,需要關聯一個中間表。
SELECT * FROM USER u LEFT JOIN user_role ur ON u.`id`=ur.`uid` INNER JOIN role r ON ur.`rid` = r.`id`;
-- user_role就是一個中間表
2.2 嵌套查詢
只是把聯合查詢語句分成多個部分分步查詢
2.2.1 一對一嵌套查詢
association
標簽中要添加select屬性
。其他的都和聯合查詢差不多
<!--一對一嵌套查詢-->
<resultMap id="orderMap" type="order">
<id column="id" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="money" property="money"></result>
<!--根據訂單中uid外鍵,查詢用戶表,即將uid作為參數傳遞到下面的查詢語句-->
<association property="user" javaType="com.lagou.domain.User" column="uid"
select="com.lagou.mapper.UserMapper.findById">
</association>
</resultMap>
<select id="findAllWithUser" resultMap="orderMap" >
SELECT * FROM orders
</select>
2.2.2 一對多嵌套查詢
<!--一對多嵌套查詢-->
<resultMap id="userMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="sex" property="sex"></result>
<result column="address" property="address"></result>
<!--根據用戶id,查詢訂單表-->
<collection property="orderList" column="id" ofType="com.lagou.domain.Order"
select="com.lagou.mapper.OrderMapper.findByUid"></collection>
</resultMap>
<select id="findAllWithOrder" resultMap="userMap">
SELECT * FROM `user`
</select>
2.2.3 多對多嵌套查詢
和一對多嵌套查詢一樣,只是SQL語句編寫不一致。
<!--多對多嵌套查詢-->
<resultMap id="userAndRoleMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="sex" property="sex"></result>
<result column="adress" property="address"></result>
<!--根據用戶id,查詢角色列表-->
<collection property="roleList" column="id" ofType="com.lagou.domain.Role"
select="com.lagou.mapper.RoleMapper.findByUid"></collection>
</resultMap>
<select id="findAllWithRole" resultMap="userAndRoleMap">
SELECT * FROM `user`
</select>
3. mybatis開發總結
- 使用動態代理的方式開發:持久層只編寫接口和Mapper.xml文件,不編寫實現類。
- XXXMapper.xml配置文件的位置必須要和接口所處的位置一致(比如:
com.lagou.mapper
),配置文件名字也需要同接口的名字保持一致(比如:UserMapper)。 - mybatis傳統開發方式:在實現類中存在代碼重復和硬編碼的問題,實際開發中不用。
- 盡量使用配置文件的方式開發,不用純注解的方式開發,因為純注解開發要修改源碼,不好維護。
4. spring兩大核心
4.1 IOC
把對象的創建權利交給spring,降低代碼的耦合度。
在mybatis開發的測試方法中,需要new SqlSessionFactoryBuilder()。有了spring之后,就可以讓spring來創建該對象。
在之前service層調用dao的方法時,需要手動創建 new UserDaoImpl()。有了spring之后,就可以讓spring來創建該對象。
4.2 AOP
在不修改源碼的情況下,對方法的功能進行增強(轉賬案例)。
5. spring IOC開發
使用注解結合配置文件開發(推薦)
使用注解開發必須在xml文件中配置注解掃描
<context:component-scan base-package="com.lagou.service"/>
-
注解代替bean標簽
<!--xml方式開發--> <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"></bean>
// 注解開發 @Repository // 如果沒有寫value屬性值,Bean的id為:類名首字母小寫 public class UserDaoImpl implements UserDao { }
-
注解代替依賴注入
<!--xml方式開發--> <bean id="userService" class="com.lagou.service.impl.UserServiceImpl"> <property name="userDao" ref="userDaoImpl"/> </bean>
// 注解開發 @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; // 去掉set方法
-
注解方式代替測試類
// xml方式開發,調用spring的API加載xml文件,並生成對象存放到IOC容器中 public class AccountServiceTest { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); AccountService accountService = (AccountService) classPathXmlApplicationContext.getBean("accountService"); ... }
// 注解結合xml開發的測試類 @RunWith(SpringJUnit4ClassRunner.class) //@RunWith指定junit的運行環境 SpringJUnit4ClassRunner是spring提供的作為junit運行環境的類 @ContextConfiguration({"classpath:applicationContext.xml"}) public class AccountServiceTest { ... }
// 純注解的測試類 @RunWith(SpringJUnit4ClassRunner.class) //@RunWith指定junit的運行環境 SpringJUnit4ClassRunner是spring提供的作為junit運行環境的類 @ContextConfiguration(classes = {SpringConfig.class}) public class AccountServiceTest { ... }
6. spring AOP開發
使用注解結合配置文件開發(推薦)
6.1 基於xml方式的AOP開發
-
創建目標接口和目標實現類(即要給哪個對象增強功能)
public interface AccountService { public void transfer(); }
public class AccountServiceImpl implements AccountService { @Override public void transfer() { System.out.println("轉賬業務..."); } }
-
創建通知類
public class MyAdvice { public void before() { System.out.println("前置通知..."); } }
-
將目標類和通知類對象創建權交給spring
<!--目標類交給IOC容器--> <bean id="accountService" class="com.lagou.service.impl.AccountServiceImpl"> </bean> <!--通知類交給IOC容器--> <bean id="myAdvice" class="com.lagou.advice.MyAdvice"></bean>
-
在核心配置文件中配置織入關系,及切面
<aop:config> <!--引入通知類--> <aop:aspect ref="myAdvice"> <!--配置目標類的transfer方法執行時,使用通知類的before方法進行前置增強--> <aop:before method="before" pointcut="execution(public void com.lagou.service.impl.AccountServiceImpl.transfer())"> </aop:before> </aop:aspect> </aop:config>
其中,
execution(public void com.lagou.service.impl.AccountServiceImpl.transfer())
是切面表達式。可以將切面表達式單獨抽取出來,方便使用
<aop:config> <!--抽取的切點表達式--> <aop:pointcut id="myPointcut" expression="execution(* com.lagou.service..*.* (..))"> </aop:pointcut> <aop:aspect ref="myAdvice"> <aop:before method="before" pointcut-ref="myPointcut"></aop:before> </aop:aspect> </aop:config>
6.2 基於注解的AOP開發
-
創建目標接口和實現類
public interface AccountService { public void transfer(); }
public class AccountServiceImpl implements AccountService { @Override public void transfer() { System.out.println("轉賬業務..."); } }
-
創建通知類
public class MyAdvice { public void before() { System.out.println("前置通知..."); } }
-
將目標類和通知類對象創建權交給spring
@Service public class AccountServiceImpl implements AccountService {} @Component public class MyAdvice {}
-
在通知類中使用注解配置織入關系,升級為切面類
@Component @Aspect public class MyAdvice { @Before("execution(* com.lagou..*.*(..))") public void before() { System.out.println("前置通知..."); } }
這里也可以抽取切面表達式
@Component @Aspect public class MyAdvice { @Pointcut("execution(* com.lagou..*.*(..))") public void myPoint(){} @Before("MyAdvice.myPoint()") public void before() { System.out.println("前置通知..."); }
-
在配置文件中開啟組件掃描和 AOP 的自動代理
<!--組件掃描--> <context:component-scan base-package="com.lagou"/> <!--aop的自動代理--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
6.3 對比xml開發和注解開發
- 注解方式:在接口實現類添加
@Service
注解;在通知類上添加@Component
和@Aspect
注解,織入關系就在通知類里面編寫。 - XML方式:對象創建是在spring配置文件中編寫,織入關系也是在配置文件中編寫。
6.4 spring中的事務控制
聲明式事務控制(開發中常用)
6.4.1 基於XML的聲明式事務控制
解決什么問題呢?在執行一個業務的時候(比如轉賬操作),如果全部執行成功就提交事務,如果出現異常就回滾事務。這中間就可以通過配置事務管理器來實現
主要配置如下:
事務管理器通知配置
<!--事務管理器-->
<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="*"/>
</tx:attributes>
</tx:advice>
事務管理器AOP配置
<!--aop配置-->
<aop:config>
<!--切面配置-->
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* com.lagou.serivce..*.*(..))">
</aop:advisor>
</aop:config>
總結:
相比較於之前基於xml方式的AOP開發,我們需要編寫一個通知類,然后在該類中編寫前置通知、后置通知、異常通知、最終通知的業務邏輯,然后再配置文件中指定通知。
現在通過事務管理器,我們只需要在配置文件中添加一個事務管理器對象的bean標簽,然后在tx:advice
標簽中引入該事務管理器對象,最后在切面配置中配置該通知就可以了。不需要再去創建一個通知類,然后寫各種通知的處理邏輯。
事務管理器AOP配置使用的是aop:advisor
標簽,而基於xml方式的AOP配置使用的是aop:aspect
標簽。
6.4.2 基於注解的聲明式事務控制
直接在service層的實現類中需要事務控制的方法上增加@Transactional
注解,或者直接在類上添加@Transactional
注解
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional(propagation = Propagation.REQUIRED, isolation =
Isolation.REPEATABLE_READ, timeout = -1, readOnly = false)
@Override
public void transfer(String outUser, String inUser, Double money) {
accountDao.out(outUser, money);
int i = 1 / 0;
accountDao.in(inUser, money);
}
}
然后在配置文件中配置如下:
<!--事務管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事務的注解支持-->
<tx:annotation-driven/>
其他的就都不用配置了
7. springMVC開發
7.1 springMVC三大組件
-
處理器映射器:找到Controller類中的需要執行的方法,返回給前端控制器。
@Controller @RequestMapping("/user") @Transactional public class UserController { @Autowired private IUserService userService; @RequestMapping(value = "/login.do" , method = RequestMethod.POST) @ResponseBody public ServiceResponse<User> login(String username, String password, HttpSession session) { ServiceResponse<User> response = userService.login(username, password); // 判斷是否登錄成功 if (response.getStatus() == ResponseCode.SUCCESS.getCode()) { session.setAttribute(Const.CURRENT_USER, response.getData()); } return response; } // 比如用戶通過瀏覽器訪問www.lagou.com/user/login.do,那么先經過前端控制器,然后前端控制器將請求發送給處理器映射器,處理器映射器就到controller層去找‘/user/login.do’資源路徑,看看能匹配到哪個類中的哪個方法。 // 最后找到UserController類中的login方法 // 上面的處理器映射器是通過xml的方式進行指定的,如果是通過注解或者接口的方式進行指定,那么springMVC都可以實現不同的映射方式。
-
處理器適配器:能夠對多個Controller類進行適配
-
視圖解析器
7.2 配置文件
web.xml
-
配置前端控制器
<!--前端控制器,加載springmvc核心配置文件--> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc/springmvc.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
-
配置監聽器
<!--監聽器,加載spring所有的配置文件--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
-
中文亂碼過濾器
<!--配置全局過濾的filter--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter- class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
spring-mvc.xml
-
配置處理器映射器和處理器適配器
<!--處理器映射器和適配器增強--> <mvc:annotation-driven></mvc:annotation-driven>
-
配置視圖解析器
<!--視圖解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean>
-
開啟靜態資源
<!--在springmvc配置文件中開啟DefaultServlet處理靜態資源--> <mvc:default-servlet-handler/>
-
配置自定義類型轉換器
SpringMVC 默認已經提供了一些常用的類型轉換器;例如:客戶端提交的字符串轉換成int型進行參
數設置,日期格式類型要求為:yyyy/MM/dd 不然的話會報錯,對於特有的行為,SpringMVC提供了自
定義類型轉換器方便開發者自定義處理。<!--自定義轉換器配置--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.lagou.converter.DateConverter"></bean> </set> </property> </bean>
public class DateConverter implements Converter<String, Date> { public Date convert(String dateStr) { //將日期字符串轉換成日期對象 返回 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; try { date = format.parse(dateStr); } catch (ParseException e) { e.printStackTrace(); } return date; } }
-
配置自定義異常處理器
public class GlobalExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("error", ex.getMessage()); modelAndView.setViewName("error"); return modelAndView; } }
<bean id="globalExecptionResovler" class="com.lagou.exception.GlobalExecptionResovler"></bean>
-
掃描路徑
<context:component-scan base-package="com.lagou.controller"></context:component-scan>
8. 方法參數名與請求參數名不一致
8.1 dao層接口方法的參數名與請求的參數名不一致
使用的是@Params()
注解
//接口中,方法的參數使用@Params()注解
public User findByIdAndName(@Params("id") int id, @(Params"username") String username);
8.2 controller層業務方法的參數名與請求的參數不一致
使用@RequestParam
注解
<!--請求時傳遞的參數名-->
<a href="${pageContext.request.contextPath}/user/findByPage?pageNo=2">
分頁查詢
</a>
@RequestMapping("/findByPage")
public String findByPage(@RequestParam(name = "pageNo", defaultValue = "1")
Integer pageNum, @RequestParam(defaultValue = "5") Integer pageSize) {
System.out.println(pageNum);
System.out.println(pageSize);
return "success";
}
9. ajax異步交互
9.1 @RequestBody
注解
該注解用於Controller的方法的形參聲明,當使用ajax提交並指定contentType為json形式時,通過
HttpMessageConverter接口轉換為對應的POJO對象。
<button id="btn1">ajax異步提交</button>
<script>
$("#btn1").click(function () {
let url = '${pageContext.request.contextPath}/ajaxRequest';
let data = '[{"id":1,"username":"張三"},{"id":2,"username":"李四"}]';
$.ajax({
type: 'POST',
url: url,
data: data,
contentType: 'application/json;charset=utf-8',
success: function (resp) {
alert(JSON.stringify(resp))
}
})
})
</script>
@RequestMapping(value = "/ajaxRequest")
public void ajaxRequest(@RequestBody List<User>list) {
System.out.println(list);
}
9.2 @ResponseBody
注解
該注解用於將Controller的方法返回的對象,通過HttpMessageConverter接口轉換為指定格式的數
據如:json,xml等,通過Response響應給客戶端。
// 默認返回的數據是json格式
@RequestMapping(value = "/ajaxRequest")
@ResponseBody
public List<User> ajaxRequest(@RequestBody List<User> list) {
System.out.println(list);
return list;
}
10 springMVC中的過濾器、攔截器和前端控制器
10.1 三者的執行順序
過濾器-->攔截器-->前端控制器
10.2 三者的功能
springMVC的攔截器,只能攔截地址欄訪問對controller的請求,無論你攔截的地址配置到天上,它只攔截對controller的請求。
springMVC的過濾器,這個會根據你配置的路徑選擇性攔截,攔截什么請求路徑,按個人口味選擇;
springMVC的前端控制器,這個也是根據你配置的路徑選擇性攔截,若直接配置根路徑,靜態資源也會被攔截;
10.3 攔截器和過濾器的區別
過濾器是Servlet中的一部分,任何Javaweb工程都可以使用;而攔截器是springmvc自己的,只有使用了springmvc框架才可以使用攔截器。
過濾器可以對所有要訪問的資源進行攔截;而攔截器只能攔截控制器類中的方法,如果訪問js、html、css、jsp、image是不會攔截的。
三、SSM整合開發
1. spring整合mybatis
將對象的創建權交給spring,原本使用單獨的mybatis開發時,在測試類中會手動創建接口的代理類對象,代碼如下:
public class MybatisTest {
@Test
public void testFindAll() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
AccountDao mapper = sqlSession.getMapper(AccountDao.class);
List<Account> accountList = mapper.findAll();
for (Account account : accountList) {
System.out.println(account);
}
}
}
通過spring整合mybatis之后,就不要手動去創建了,只需要在spring的核心配置文件中進行配置就可以了,代碼如下:
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="druidDataSource"></property>
<!--spring配置文件中起別名的方法-->
<property name="typeAliasesPackage" value="com.lagou.domain"></property>
</bean>
<!--將AccountDAO接口的實現類對象交給spring創建,需要使用以下類對接口進行掃描,創建接口實現類-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lagou.dao"></property>
</bean>
值得一提的是:在sqlSessionFactory標簽中,可以配置很多的屬性。比如:
<!--加載mybatis核心配置文件-->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
在spring的核心配置文件中配置以上配置之后,原本在mybatis中的以下配置就可以刪除了
<!--配置別名-->
<typeAliases>
<typeAlias type="com.lagou.domain.Account" alias="account"></typeAlias>
</typeAliases>
<!--environments:運行環境-->
<environments default="development">
<!--可以配置多個環境-->
<environment id="development">
<!--當前的事務管理器是JDBC-->
<transactionManager type="JDBC"></transactionManager>
<!--數據源信息
POOLED:使用mybatis的連接池
UNPOOLED:不使用連接池
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射配置文件,動態代理的時候用到-->
<mappers>
<mapper class="com.lagou.dao.AccountDao"></mapper>
</mappers>
spring整合mybatis之后,測試的時候只需要將dao層的接口注入到service層就可以了,不需要再手動創建,代碼如下:
public class AccountServiceImpl implements AccountService {
// 注入接口
@Autowired
private AccountDao accountDao;
@Override
public List<Account> findAll() {
List<Account> accountList = accountDao.findAll();
return accountList;
}
@Override
public void save(Account account) {
accountDao.save(account);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
@Autowired
private AccountService accountService;
@Test
public void testFindAll() {
accountService.findAll();
}
}
2. spring整合springmvc
整合的地方就是讓springmvc加載spring的配置文件,在web.xml文件中整合如下:
<!--web.xml-->
<!--監聽器,其作用是監聽ServletContext容器,一旦啟動就加載spring的核心配置文件-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
四、springboot開發
1. 全局配置文件
Spring Boot使用一個application.properties或者application.yaml的文件作為全局配置文件,該文件存放在src/main/resource目錄或者類路徑的/config
1.1 application.properties配置文件
可以配置系統屬性、環境變量、命令參數等信息,也可以是自定義配置文件名稱和位置。
# tomcat服務端口
server.port=8081
# spring相關配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.config.additional-location=
spring.config.location=
spring.config.name=application
# person實體類相關配置
person.id=1
person.name=tom
person.hobby=吃飯,睡覺,打游戲
person.family=father,mother
person.map.k1=v1
person.map.k2=v2
person.pet.type=dog
person.pet.name=旺財
1.2 application.yaml配置文件
YAML文件格式是Spring Boot支持的一種JSON超集文件格式,相較於傳統的Properties配置文件,YAML文件以數據為核心,是一種更為直觀且容易被電腦識別的數據序列化格式。
注意:冒號后面必須要有一個空格
-
value值為普通數據類型(例如數字、字符串、布爾等)
server: port: 8080 servlet: context-path: /hello
-
value值為數組和單列集合
person: hobby: [play,read,sleep]
-
value值為Map集合和對象
person: map: {k1: v1,k2: v2}
1.3 注意事項
使用application.yaml配置文件進行測試時需要提前將application.properties配置文件中編寫的配置注釋,這是因為application.properties配置文件會覆蓋application.yaml配置文件。
2. 配置文件屬性值的注入
使用Spring Boot全局配置文件設置屬性時:
如果配置屬性是Spring Boot已有屬性,例如服務端口server.port,那么Spring Boot內部會自動掃描並讀取這些配置文件中的屬性值並覆蓋默認屬性。
如果配置的屬性是用戶自定義屬性,例如剛剛自定義的Person實體類屬性,還必須在程序中注入這些配置屬性方可生效。
Spring Boot支持多種注入配置文件屬性的方式,下面來介紹如何使用注解@ConfigurationProperties和@Value注入屬性
2.1 使用@ConfigurationProperties注入屬性
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private int id;
// 屬性的setXX()方法
public void setId(int id) {
this.id = id;
}
}
上述代碼使用@Component和@ConfigurationProperties(prefix = “person”)將配置文件中的每個屬性映射到person類組件中。
2.2 使用@Value注入屬性
@Value注解是Spring框架提供的,用來讀取配置文件中的屬性值並逐個注入到Bean對象的對應屬性中,Spring Boot框架從Spring框架中對@Value注解進行了默認繼承,所以在Spring Boot框架中還可以使用該注解讀取和注入配置文件屬性值。使用@Value注入屬性的示例代碼如下:
@Component
public class Person {
@Value("${person.id}")
private int id;
}
上述代碼中,使用@Component和@Value注入Person實體類的id屬性。其中,@Value不僅可以將配置文件的屬性注入Person的id屬性,還可以直接給id屬性賦值,這點是@ConfigurationProperties不支持的.
@Component
public class Student {
@Value("${person.id}")
private int id;
@Value("${person.name}")
private String name; //名稱
//省略toString
}
Student類使用@Value注解將配置文件的屬性值讀取和注入。
從上述示例代碼可以看出,使用@Value注解方式需要對每一個屬性注入設置,同時又免去了屬性的setXX()方法.
3. 自定義配置文件
3.1 使用@PropertySource
加載配置文件
-
打開Spring Boot項目的resources目錄,在項目的類路徑下新建一個test.properties自定義配置文件,在該配置文件中編寫需要設置的配置屬性
#對實體類對象MyProperties進行屬性配置 test.id=110 test.name=test
-
在com.lagou.pojo包下新創建一個配置類MyProperties,提供test.properties自定義配置文件中對應的屬性,並根據@PropertySource注解的使用進行相關配置
@Component // 自定義配置類 @PropertySource("classpath:test.properties") // 指定自定義配置文件位置和名稱 @ConfigurationProperties(prefix = "test") // 指定配置文件注入屬性前綴 public class MyProperties { private int id; private String name; // 省略屬性getXX()和setXX()方法 // 省略toString()方法 }
說明:
@PropertySource("classpath:test.properties")注解指定了自定義配置文件的位置和名稱,此示例表示自定義配置文件為classpath類路徑下的test.properties文件;
@ConfigurationProperties(prefix = "test")注解將上述自定義配置文件test.properties中以test開頭的屬性值注入到該配置類屬性中。
3.2 使用@Configuration
編寫自定義配置類
// 實體類
public class MyService {
}
@Configuration // 定義該類是一個配置類````
public class MyConfig {
@Bean // 將返回值對象作為組件添加到Spring容器中,該組件id默認為方法名
public MyService myService(){
return new MyService();
}
}
MyConfig是@Configuration注解聲明的配置類(類似於聲明了一個XML配置文件),該配置類會被Spring Boot自動掃描識別;使用@Bean注解的myService()方法,其返回值對象會作為組件添加到了Spring容器中(類似於XML配置文件中的標簽配置),並且該組件的id默認是方法名myService.
4. SpringBoot整合MyBatis
4.1 編寫與數據表對應的實體類
public class Comment {
private Integer id;
private String content;
private String author;
private Integer aId;
// 省略屬性getXX()和setXX()方法
// 省略toString()方法
}
public class Article {
private Integer id;
private String title;
private String content;
// 省略屬性getXX()和setXX()方法
// 省略toString()方法
}
4.2 在application.properties配置文件中進行數據庫連接配置
# MySQL數據庫連接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
4.3 注解方式整合Mybatis
-
創建一個對t_comment表數據操作的接口CommentMapper
@Mapper public interface CommentMapper { @Select("SELECT * FROM t_comment WHERE id =#{id}") public Comment findById(Integer id); }
需要在類上添加
@Mapper
注解, 然后在方法上添加@Select
注解
4.4 使用配置文件的方式整合mybatis
-
創建一個用於對數據庫表t_article數據操作的接口ArticleMapper
@Mapper public interface ArticleMapper { public Article selectArticle(Integer id); }
-
創建XML映射文件
resources目錄下創建一個統一管理映射文件的包mapper,並在該包下編寫與ArticleMapper接口對應的映射文件ArticleMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.lagou.mapper.ArticleMapper"> <select id="selectArticle" resultType="Article"> select * from Article </select> </mapper>
-
在application.properties配置文件中做如下配置
#開啟駝峰命名匹配映射 mybatis.configuration.map-underscore-to-camel-case=true #配置MyBatis的xml配置文件路徑 mybatis.mapper-locations=classpath:mapper/*.xml
5. SpringBoot整合SSM
最核心的地方是要在application.yml配置文件中配置spring和mybatis的相關配置,其他的基本都一樣的。
#服務器配置
server:
port: 8090
servlet:
context-path: /
# spring相關配置
spring:
datasource:
name: druid
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/spring_db?characterEncoding=utf-
8&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
mvc:
view:
prefix: /
suffix: .html
# mybatis相關配置
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml #聲明Mybatis映射文件所在的位置