LOADING

加载过慢请开启缓存 浏览器默认开启

WEB应用开发

速通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.表单关键元素和相关设置

MDN form元素

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.正则表达式

MDN 正则表达式

22.JSON是一种轻量级的数据交换格式

正确.

23.JSON和XML比较JSON体积更小

正确. JSON有更简洁的语法结构.

24.JSON数据前端显示

MDN 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配置等.