速通WEB考试重点,祝大家都能顺利通过()
1.Web应用开发流程
需求分析: 确定项目的业务需求, 明确用户的功能和交互需求, 定义项目的范围、功能和特性, 确定开发团队的目标.
项目规划: 制定项目计划, 包括开发阶段、测试阶段、上线时间等.
UI/UX设计: 进行用户界面(UI)和用户体验(UX)的设计, 设计页面布局、颜色和交互流程.
前端开发: 使用HTML、CSS、JavaScript等技术实现UI设计, 前端框架(如React、Vue、Angular)的选择和使用.
后端开发: 选择后端技术栈(如Java、Python、Node.js), 开发后端业务逻辑.
数据库开发: 设计数据库表结构, 确定数据存储方式. 使用数据库管理系统(如MySQL、PostgreSQL、MongoDB)进行开发.
集成测试: 对前端、后端和数据库进行集成测试, 确保系统各部分协同工作,并检查系统是否满足需求.
系统测试: 对整个系统进行全面测试, 包括功能测试、性能测试、安全测试等.
部署: 部署到服务器, 配置服务器环境,设置域名、SSL证书等, 配置反向代理(如Nginx、Apache).
维护和优化: 定期进行系统维护,如数据库备份、日志清理等.根据用户反馈和系统监控数据,进行系统优化和升级.
C/S架构: 开发客户端/服务端软件、部署服务端程序、部署客户端程序、安装客户端软件.
B/S架构: 开发服务器端代码、部署到Web服务器.C/S偏向用户体验, B/S偏向功能服务实现, 两者并没有优劣之分.
2.静态网页的显示可以不依赖于Web服务器
正确.
3.表格布局比DIV+CSS布局的兼容性更好
正确. 由于采用的是HTML标签 <table>,各种浏览器都能准确解析该标签, DIV+CSS还没有实现所有浏览器的统一兼容.
4.表格布局比DIV+CSS布局更灵活多样
错误. 请多相信CSS的能力!
5.表单标记通过method属性设置后台的处理程序
正确. method可以取”GET”和”POST”值.
6.表单的主要作用是发布信息
错误. 表单的主要作用是收集和提交信息.
7.表单中的输入组件都是通过<input>标记定义的
错误. 其实不仅限于<input>, <textarea><select>等都能标记定义.
8.表单中的密码框的输入回显字符只能是” * “
错误. 通常是圆点或者星号.
9.表单中一组单选按钮的name属性要相同
正确. radio是以name属性进行分组的.
10.表单中一组复选按钮的name属性不需要相同
正确. checkbox的name属性不用于分组.
11.表单中的列表默认只显示1个选项
正确.
12.表单中的列表只能选择1个选项
错误. 使用multiple属性可以多个.
13. 通过CSS的应用可以同时更新多个网页的样式
正确.
14.CSS可以在网页中定义也可以在CSS文件中定义
正确.
15.表单关键元素和相关设置
form标签用于向Web服务器提交信息.
主要属性:
name: 表单名称
action: 表单提交的URL
method: HTTP方式提交表单
<form action="/submit" method="post">
<!-- 表单中的其他元素 -->
</form>
16.JavaScript变量名是区分大小写的
正确.
17.JavaScript主要用于接受服务器端的响应
错误. 不仅仅接受服务器端的响应, 还有用户与页面的交互.
18.JavaScript变量的类型根据变量赋值来确定
正确. 弱类型语言.
19.JavaScript变量使用var声明时必须赋初值
错误. 完全可以不赋初值, 默认undefined.
20.JavaScript实现表单提交参数验证
来源于PPT.
<button onclick="check();"/>
<script language="JavaScript">
function check(){
if(frm.userName.value==""){
alert("userName excepted!");
frm.userName.focus();
return;
}
frm.submit();
}
</script>
<submit onclick="return check();"/>
<script language="JavaScript">
function check(){
if(frm.userName.value==""){
alert("userName excepted!");
frm.userName.focus();
return false;
}
return true;
}
</script>
21.正则表达式
22.JSON是一种轻量级的数据交换格式
正确.
23.JSON和XML比较JSON体积更小
正确. JSON有更简洁的语法结构.
24.JSON数据前端显示
JSON是一种语法.
JSON不是JavaScript, JavaScript不是JSON.
JSON方法:
//JSON.parse():解析JSON字符串, 转换为JavaScript值(JSON字符串不允许用逗号结尾)
const json = '{"result":true, "count":40}';
const obj = JSON.parse(json);
console.log(obj.count); // Expected output: 42
console.log(obj.result); // Expected output: true
//JSON.stringify(): 将JavaScript值转换为JSON字符串
console.log(JSON.stringify({ x: 5, y: 6 })); // Expected output: '{"x":5,"y":6}'
console.log(
JSON.stringify([new Number(3), new String('false'), new Boolean(false)]),
);// Expected output: '[3,"false",false]'
//undefined、任意的函数以及 symbol 值, 在序列化过程中会被转换成 null.
console.log(JSON.stringify({ x: [10, undefined, function () {}, Symbol('')] }));// Expected output: '{"x":[10,null,null,null]}'
//以 symbol 为属性键的属性都会被完全忽略掉
JSON.stringify({ [Symbol.for("foo")]: "foo" }, [Symbol.for("foo")]);// '{}'
课上示例:
<script type="text/javascript">
var testData;
testData=[
{"code":"00001","name":"王亮","sex":0,"grade":2015,"major":"软件工程"},
{"code":"00002","name":"李树国 ","sex":0,"grade":2015,"major":"软件工程"},
{"code":"00003","name":"赵欣","sex":1,"grade":2015,"major":"空间信息"}
];
function WriteStList(data){
var studentList=data;
var strHtml="";
strHtml+="<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\"> ";
for(var i=0;i<studentList.length;i++){
strHtml+="<tr class=\"td_"+(i%2+1)+"\">";
strHtml+="<td width=\"15%\">"+studentList[i]["code"]+"</td>";
strHtml+="<td width=\"15%\">"+studentList[i]["name"]+"</td>";
strHtml+="<td width=\"15%\">"+(studentList[i]["sex"]==0?"男":"女")+"</td>";
strHtml+="<td width=\"15%\">"+studentList[i]["grade"]+"</td>";
strHtml+="<td width=\"15%\">"+studentList[i]["major"]+"</td>";
strHtml+="<td><a href=\"student_edit.html\">编辑</a>";
strHtml+="<a href=\"JavaScript:alert('准备删除学号为"+studentList[i]["code"]+"的学生信息')\">删除</a></td></tr>";
}
strHtml+="</table>";
document.getElementById("studentsSpan").innerHTML =strHtml;
}
</script>
25.JSP开发中最常用的两种设计模式
1.JSP+JavaBean
用户通过客户端请求WEB服务器, 服务端接收请求后调用JSP页面, JSP中调用JavaBean, JavaBean中连接和操作数据库实现业务逻辑后将结果返回到JSP页面, WEB服务器读取JSP中的内容并将最终结果返回到客户端中进行显示.
2.MVC模式
即模型-视图-控制器.
模型: 用于存储数据的对象(一个或多个JavaBean对象). 视图:显示模型中的数据(一个或多个JSP页面). 控制器:业务逻辑操作(一个或多个servlet对象).
26.JSP技术的MVC模式描述
用户通过浏览器发送请求到servlet, servlet将调用JavaBean完成数据的操作处理与封装并调用相应的JSP页面, JSP页面将调用JavaBean获取需要的数据, 最终将结果返回到客户端浏览器上进行显示.27.JSP页面中的Java脚本标记包括哪三种元素
JSP表达式: <%= %>
声明标识: <%! %>
脚本程序: <% %>
28.JSP页面中<%! %>标记的用途
声明变量或代码.
29.JSP内置对象
request: 请求对象
response: 响应对象
out: JSP输出流对象
session: 会话对象
application: ServletContext对象
config: ServletConfig对象
page: 指向当前jsp的对象
pageContext: jsp上下文对象
exception: 异常对象
30.JSP第一次访问过后,将生成一个exe文件
错误. 转换为一个servlet文件, servlet文件编译为class文件后再执行.
JSP页面转换为java类, 该类继承了HttpJspBase类, 而HttpJspBase类继承了HttpServlet类, 故一个JSP可以理解为一个Servlet.
31.转发和重定向的区别
转发可以通过request对象直接传递到目标页面, 而重定向需要使用更大范围的Session等方式进行传递.
转发是服务器内部行为, 过程中, 浏览器URL是不会发生变化的; 而重定向过程中, 浏览器会根据新的URL发送请求.
32.JavaBean的特点, 一次编写, 任何地方执行, 任何地方重用
JavaBean用于封装对象, 要提供get、set方法.
public class MyClass {
private String propertyName;
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
}
33.根据用途JavaBean分类
通用工具JavaBean: 实现基本功能(字符转换、类型转换等)
值JavaBean: 封装实体
业务处理JavaBean: 处理数据
34.不可视化JavaBean的属性主要有哪些
get、set、构造方法之类.
35.JavaBean编写规范
实现java.io.Serializable接口
是一个公共类
存在无参数的构造函数
提供set、get方法
36.JDBC访问数据库过程
加载驱动程序 -> 建立数据库连接 -> 执行sql语句 -> 处理结果 -> 关闭连接
String diverClass= "com.mysql.jdbc.Driver";
String dbUrl= "jdbc:mysql://localhost:3306/db_database08";
//1、建立数据库连接
Class.forName(diverClass); // 1.1加载驱动程序
Connection con=
DriverManager.getConnection (dbUrl, “root", “rootpassword"); //1.2创建链接
//2、执行SQL语句(不建议用statement了)
Statement sql=con.createStatement(); //2.1创建sql语句执行对象
ResultSet rs=sql.executeQuery("select * from tb_user”); //2.2执行sql
//3、处理SQL语句执行结果
while(rs.next()){ 获取记录中每个字段的数据 }//遍历结果集对象
//4、关闭数据库连接
rs.close(); sql.close(); con.close();
37.JDBC常用接口及其描述
Driver: 驱动程序接口, 用于加载驱动.
Class.forName("com.mysql.jdbc.Driver"); // 加载类时自动注册mysql驱动
DriverManager: 管理用户与数据库连接, 一般使用getConnection方法.
DriverManager.getConnection(String url, String user, String password) // 连接数据库
Connection: 数据库连接接口, 有close方法.
Connection conn = DriverManager.getConnection(url, user, password);
Statement: 执行静态Sql语句, 返回结果集ResultSet, 不推荐(存在sql注入问题)
PreparedStatement: 执行动态Sql语句, 需要填充占位符”?”.
String sql = "select * from users WHERE name = ?"; // sql语句
PreparedStatement ps = conn.prepareStatement(sql)l //预编译
ps.setObject(1, "bin"); //填充占位符, 注意是从1开始编号
ResultSet rs = ps.executeQuery(); //执行sql语句
CallableStatement: 调用存储过程, 继承于PreparedStatement.
ResultSet: 类似于sql中的一个表, 可以获得表行列的数据.
ResultSet维护了一个指向当前数据行的游标, 可以通过next()方法移动到下一行并判断该行是否有效.相当于Iterator的hasNext()与next()的结合.
public static <T> List<T> newselect1(Class<T> clazz, String sql, Object ...args){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++)
{
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
ArrayList<T> list = new ArrayList<T>();
while(rs.next()){
T t = clazz.newInstance();
for (int i = 0; i < count; i++){
Object columnValue = rs.getObject(i + 1);
String columnName = rsmd.getColumnLabel(i + 1);
Field field = t.getClass().getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, columnValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
}
38.PreparedStatement接口的特点
PreparedStatement是Statement的子接口, 它的重要特点是预编译, 性能提升的同时还可以防止SQL注入的问题.
39.Resultset接口
同37.
40.DBManager类获得数据库连接, 执行sql查询操作流程
同37.
使用DriverManager.registerDriver(com.mysql.jdbc.Driver)来注册驱动, 但在调用Driver接口时, 自动执行静态代码块, 所以不需要额外编写, 只需加载类即可.
41.业务逻辑Bean(获取数据库数据封装到值型JavaBean)流程
1.定义JavaBean
public class User {
private int id;
private String username;
private String email;
// 省略 getter 和 setter 方法
}
2.创建业务逻辑Bean
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class UserBean {
// 获取数据库连接
private Connection getConnection() throws SQLException {
// 实现获取数据库连接的逻辑,可以使用连接池等方式
// 返回数据库连接对象
}
// 查询所有用户信息
public List<User> getAllUsers() {
List<User> userList = new ArrayList<>();
try (Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user");
ResultSet resultSet = preparedStatement.executeQuery()) {
while (resultSet.next()) {
User user = new User();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setEmail(resultSet.getString("email"));
userList.add(user);
}
} catch (SQLException e) {
e.printStackTrace(); // 实际中应该进行异常处理
}
return userList;
}
}
42.Servlet的生命周期
1.用户通过客户端浏览器请求服务器,服务器加载Servlet,并创建一个Servlet实例.
2.容器调用Servlet的init()方法构造.
3.容器调用service()方法,并将HttpServletRequest和HttpServletResponse对象传递给该方法,在service()方法中处理用户请求.
4.在Servlet中请求处理结束后,将结果返回给容器.
5.容器将结果返回给客户端进行显示.
6.当Web服务器关闭时,调用destroy()方法销毁Servlet实例.
43.web.xml中servlet配置的XML标记
<servlet> //定义servlet
<servlet-name>EmpServlet</servlet-name> //servlet名称
<servlet-class>cuit.emp.EmpServlet</servlet-class> //servlet类
</servlet>
<servlet-mapping> //定义servlet映射
<servlet-name>EmpServlet </servlet-name> //servlet名称
<url-pattern> /servlet/EmpServlet </url-pattern> //servlet地址
</servlet-mapping>
44.Ajax代码异步请求方式
传统派:
let s = document.getElementById("btn");
s.onclick = function(){
let xhr = new XMLHttpRequest(); //创建Ajax对象
xhr.open("GET", url, true); //设置属性
xhr.send(); //提交请求
xhr.onreadystatechange = function(){ //接受返回内容
if (xhr.readyState == 4 && xhr.status == 200) {
}
}
}
维新派:
$.get("deal.jsp",
{name:"无语",branch:"java"}
);
$.post("deal.jsp",
{title:"祝福",content:"祝愿天下的所有母亲平安、健康…"},
function(data){
alert(data);
}
);
45.服务器端servlet相应处理请求流程(获取表单参数、校验和提交、生成响应)
用户在客户端浏览器中发送请求至WEB服务器, WEB服务器调用实例servlet的service方法创建一个request和response对象, servlet从request中读取信息, 处理数据后将其写入response中封装, 由WEB服务器传回数据给客户端浏览器.
46.Ajax请求获取列表形式的JSON数据
document.addEventListener("DOMContentLoaded", function () {
var xhr = new XMLHttpRequest(); // 创建 XMLHttpRequest 对象
xhr.open("GET", "your_backend_endpoint", true); // 配置请求
xhr.responseType = "json"; // 设置响应类型为 JSON
xhr.onload = function () {
if (xhr.status === 200) { // 请求成功,处理返回的 JSON 数据
var userList = xhr.response;
renderUserList(userList);
} else {
console.error("Failed to fetch user data. Status code: " + xhr.status); // 请求失败,处理错误
}
};
xhr.onerror = function () { // 处理网络错误时的回调函数
console.error("Network error occurred");
};
xhr.send(); //发送请求
});
function renderUserList(userList) {
var userListElement = document.getElementById("userList");
userListElement.innerHTML = "";
// 遍历用户列表并添加到 HTML 中
userList.forEach(function (user) {
var listItem = document.createElement("li");
listItem.textContent = "ID: " + user.id + ", Name: " + user.name + ", Email: " + user.email;
userListElement.appendChild(listItem);
});
}
47.Spring MVC是对Servlet的再封装
正确. Spring MVC通过对Servlet进行封装,提供了更高级别的抽象,使得Web应用程序的开发更加简便和灵活.
48.Spring MVC的工作原理
1.客户端请求提交到DispatcherServlet.
2.由DispatcherServlet控制器寻找一个或多个HandlerMapping,找到处理请求的Controller.
3.DispatcherServlet将请求提交到Controller.
4.Controller调用业务逻辑处理后,返回ModelAndView.
5.DispatcherServlet寻找一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图.
6.视图负责将结果显示到客户端.
49.Spring容器管理的bean默认是单实例的
正确. 应用程序启动时, Spring容器都会创建并初始化Bean, 每次请求该Bean时, 都会返回相同的实例.
50.Spring配置文件名是固定的
错误. 可以更改,最好固定.
51.Spring用标签定义对象时,标签中必须申明id
错误. 不声明id时, Spring自动生成一个唯一的标识符.
52.Spring获取容器创建的对象的方法
ApplicationContext接口 和 注解.
53.Spring AOP的一个切入点可能横切多个业务组件。
正确.
54.Spring容器实现了I0C和AOP机制, 这些机制可以简化Bean对象创建和Bean对象之间的解耦。
正确.
55.@Autowired用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作,默认按照Bean的名称进行装配
正确.
56.Hibernate和MyBatis均是全自动映射的框架
错误. Mybatis是半自动映射框架.
57.Hibernate和MyBatis都可以自动生成SQL
错误. Mybatis不能.
58.应用在Web应用中的数据库系统有哪些
MySQL、PostgreSQL、Oracle、Redis、Microsoft SQL Server等.
59.使用MyBatis框架,一般需要先建立与数据库表对应的实体类。
正确.
60.MyBatis和Hibernate是目前流行的ORM框架.
正确.
61.MyBatis 的程序里最终使用的对象
数据库表对应的 Java 对象(实体类、POJO).
62.MyBatis工作流程或主要步骤
1.读取MyBatis配置文件mybatis-config.xml, 该文件配置了MyBatis的运行环境等信息.
2.加载SQL映射文件, 文件中配置了操作数据库的SQL语句, 需要在mybatis-config.xml中加载, 可以加载多个映射文件.
3.构建会话工厂SqlSessionFactory.
4.创建SqlSession对象, 该对象中包含执行SQL语句的所有方法.
5.使用Executor接口来操作数据库, 根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护.
6.在Executor接口的执行方法中有MappedStatement类型参数, 该参数是对映射信息的封装, 用于存储要映射的SQL语句的id、参数等信息.
7.输入参数映射. 输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型, 输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程.
8.输出结果映射. 输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型, 输出结果映射过程类似于JDBC对结果集的解析过程.
63.MyBatis映射文件中的常用元素及其作用
select
<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
insert
<insert id="insertUser" parameterType="User">
INSERT INTO users (username, password) VALUES (#{username}, #{password})
</insert>
update
<update id="updateUser" parameterType="User">
UPDATE users SET username = #{username}, password = #{password} WHERE id = #{id}
</update>
delete
<delete id="deleteUser" parameterType="int">
DELETE FROM users WHERE id = #{id}
</delete>
resultMap
<resultMap id="userResultMap" type="User">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="password" column="password" />
</resultMap>
64.MyBatis中动态SQL的常用元素及其作用
if元素: 判断
<select id="getUsers" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
</select>
choose、when、otherwise: switch
<select id="getUsers" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<choose>
<when test="username != null">
AND username = #{username}
</when>
<when test="email != null">
AND email = #{email}
</when>
<otherwise>
AND status = 'ACTIVE'
</otherwise>
</choose>
</where>
</select>
trim、set: 修剪
<update id="updateUser" parameterType="User">
UPDATE users
<set>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
</set>
WHERE id = #{id}
</update>
foreach: 迭代
<select id="getUsersByIdList" parameterType="list" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach collection="idList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
blind: 定义变量
<select id="getUsersByNameAndAge" parameterType="map" resultType="User">
<bind name="nameCondition" value="'%' + name + '%'"/>
SELECT * FROM users
WHERE name LIKE #{nameCondition}
AND age = #{age}
</select>
65.Spring中的通知按照在目标类方法的连接点位置,分为5种通知
环绕通知: 在目标方法执行前和执行后实施增强.
前置通知: 在目标方法执行前实施增强.
后置返回通知: 在目标方法成功执行后实施增强.
最终通知: 不管是否发生异常, 在目标方法执行后实施增强.
异常通知: 在方法抛出异常后实施增强.
66.Hibernate和MyBatis和JDBC各自特点和优势
JDBC: 简单直接,适用于小型项目或者需要直接控制数据库操作的场景, 基于标准化, 可以与任何支持JDBC的数据库进行交互.
Hibernate: ORM框架, 不需要编写SQL语句.
Mybatis: 使用连接池管理, 提供了更多的抽象和方便的映射, 基于XML配置的持久化框架,将Java对象映射到数据库中的SQL语句.
67.JSP、Servlet、SpringMVC各自优势
JSP: 使用标记语言, 在HTML中嵌入Java代码, 易于上手; 将Java代码与HTML结合, 实现前端和后端的紧密集合, 开发网页相对简单; 通常用于表示视图层, 与Servlet结合使用.
Servlet: 控制强大, 可以处理请求、响应、会话管理等功能; 编写Java代码处理HTTP请求和响应, 具有强大的灵活性; 适用于处理业务逻辑, 实现底层逻辑控制.
SpringMVC: 模块化和松耦合, 通过使用MVC架构, 将应用程序分为模型、视图和控制器, 实现了更好的松耦合; 支持AOP, 允许开发人员通过切面处理横切关注点; 拥有强大的配置, 允许使用注解或XML配置定义映射、拦截器等; 与SpringBoot等整合, 提供了更全面的解决方案.
68.Spring框架的优势和特点
轻量级和非侵入性:
Spring是一个轻量级的框架,不需要大量的配置信息,使得开发更加简单;不需要继承特定的类或实现特定的接口,可以与其他框架和应用程序集成.
依赖注入:
提供了依赖注入机制,通过IoC容器管理对象的依赖关系,降低了组件之间的耦合度, 对象的创建和组装由Spring容器负责,提高了代码的可维护性和可测试性.
面向切面编程:
支持AOP,允许通过切面在应用程序中横切关注点,如事务管理、日志记录等. 可以将横切关注点从核心业务逻辑中分离,提高了代码的模块化和可重用性.
模块化设计: Spring采用了模块化的设计,各个模块提供不同的功能,如数据访问、事务管理、消息传递. 可以选择性地使用这些模块,根据项目需求进行集成.
数据访问抽象层: 提供了一致的数据访问抽象层,支持多种数据访问技术,如JDBC、Hibernate、JPA等.简化了数据访问代码的编写,提高了灵活性.
事务管理: 支持声明式事务管理,通过注解或XML配置,简化了事务的控制. 提供了编程式事务管理的方式,允许更细粒度的控制事务.
灵活配置: 支持多种配置方式,包括XML配置、注解配置、Java配置等.