Java Web

Java Web

JSP 的本质?

JSP的本质

  • JSP 文件本质上是一个特殊的 HTML 文件,里面可以嵌入 Java 代码

第一次访问JSP文件时会进行编译过程

  1. 将 JSP 文件解析成纯 Java 代码
  2. 这个 Java 代码会被编译成 .class 文件
  3. 这个 .class 文件就是一个 Servlet 类

转换示例

public class user_login_jsp extends HttpServlet {
public void _jspService(HttpServletRequest request, HttpServletResponse response) {
// 设置响应类型
response.setContentType("text/html;charset=UTF-8");

// 输出 HTML 开始部分
out.write("<html><body>");

// 执行 Java 代码
String message = "Hello";

// 输出变量值
out.write("<h1>");
out.print(message);
out.write("</h1>");

// 输出 HTML 结束部分
out.write("</body></html>");
}
}

当访问JSP文件时

  1. 服务器检查是否已经有对应的编译后的 Servlet
  2. 如果没有,就进行上述转换和编译过程
  3. 如果有,就直接使用编译好的 Servlet
  4. 然后执行这个 Servlet 的 _jspService 方法
  5. 生成 HTML 响应

为什么有数据库存数据还要又创建Java对象把数据重复存入Java对象?

  • 分层架构的需要:
    • 数据库层 (model):负责数据的持久化存储
    • 业务逻辑层 (controller):处理业务规则和逻辑
    • 表现层 (view):负责数据的展示
    • 每一层都需要用适合该层的方式来表示数据
  • 面向对象编程的优势:
    • 数据库是关系型的,而 Java 是面向对象的
    • Java 对象可以包含行为(方法)和状态(属性)
    • 可以在对象中添加业务逻辑,比如 Order 类中的 addGoods()、lessen() 等方法
    • 可以建立对象之间的关系,比如 Order 和 User 的关联
  • 数据操作的安全性:
    • 直接操作数据库容易出错
    • 通过 Java 对象可以添加数据验证
    • 可以在 setter 方法中添加业务规则
    • 可以控制数据的访问权限
  • 代码的可维护性:
    • 业务逻辑集中在 Java 类中,而不是分散在 SQL 语句里
    • 修改业务规则只需要修改 Java 代码,不需要修改数据库
    • 可以方便地添加新的功能,比如计算订单总价、处理折扣等
  • 框架支持:
    • 很多框架(如 Hibernate)需要 Java 类来映射数据库表
    • 这些框架可以自动处理数据库和 Java 对象之间的转换
    • 减少了手动编写 SQL 语句的工作

Java类属性名和数据库表的列名怎么建立映射关系的?

1. 默认情况:名称一致(自动映射)

如果 Java 类的属性名和数据库列名完全一致,大多数 ORM 框架(如 MyBatis、Hibernate、JPA)会自动映射:

public class User {
private Integer id; // 对应数据库列 `id`
private String name; // 对应数据库列 `name`
}
CREATE TABLE user (
id INT PRIMARY KEY,
name VARCHAR(100)
);

优点:无需额外配置,简洁直观。

2. 名称不一致时如何映射?

如果属性名和列名不一致,可以通过以下方式解决:

(1) 使用注解(JPA/Hibernate)

@Entity
@Table(name = "user")
public class User {
@Id
@Column(name = "user_id") // 映射到数据库列 `user_id`
private Integer id;

@Column(name = "full_name") // 映射到数据库列 `full_name`
private String name;
}

(2) MyBatis 的 @Result 或 XML 映射

// 注解方式
@Results({
@Result(property = "id", column = "user_id"),
@Result(property = "name", column = "full_name")
})
@Select("SELECT user_id, full_name FROM user")
List<User> getUsers();
<!-- XML 方式 -->
<resultMap id="userMap" type="User">
<result property="id" column="user_id"/>
<result property="name" column="full_name"/>
</resultMap>

(3) 别名(SQL 查询时临时映射)

SELECT user_id AS id, full_name AS name FROM user;

3. 为什么推荐松耦合?

  • 数据库设计:列名可能使用下划线(如 user_name),而 Java 属性通常用驼峰(如 userName)。
  • 历史遗留系统:数据库列名可能无法随意修改。
  • 跨团队协作:数据库和代码可能由不同团队维护。

4. 注意事项

  1. 区分大小写:
  • 数据库列名大小写是否敏感取决于数据库配置(如 MySQL 默认不敏感,Oracle 敏感)。
  • Java 属性名严格区分大小写。
  1. 特殊字符:
  • 数据库列名可能包含特殊字符(如 user-name),需用反引号或引号包裹:
    SELECT `user-name` FROM table;
  1. ORM 框架差异:
  • JPA/Hibernate 默认将驼峰属性名转换为下划线列名(如 userNameuser_name)。
  • MyBatis 需要显式配置映射。

总结

  • 不必完全一致:通过注解、配置文件或别名可以灵活映射。
  • 一致性优先:如果项目允许,尽量保持命名一致,减少配置。
  • 明确映射关系:避免因命名差异导致的隐蔽错误。

Servlet中的doGet()和doPost区别?

在 Servlet 中,doGet() 和 doPost() 是处理 HTTP 请求的两种核心方法,它们的区别主要在于 HTTP 方法的语义和使用场景,但都能获取请求参数。以下是详细解析:

doGet vs doPost 的区别

特性 doGet() doPost()
HTTP 方法 处理 GET 请求 处理 POST 请求
参数传递方式 参数附加在 URL 后(?key=value) 参数在请求体(Body)中传输
数据可见性 参数暴露在地址栏(不安全) 参数不可见(相对安全)
数据大小限制 受 URL 长度限制(通常 ≤2048 字符) 无限制(适合大文件上传)
幂等性 是(多次执行结果相同) 否(可能修改服务器状态)
浏览器缓存 可被缓存 不可缓存
典型用途 查询数据、页面跳转 提交表单、修改数据

为什么 doGet 也能获取请求参数?

虽然 GET 和 POST 传递参数的方式不同,但 Servlet 规范对参数提取进行了统一封装,因此无论是 doGet() 还是 doPost(),都可以通过以下方法获取参数:

(1) 获取单个参数

String username = request.getParameter("username");

(2) 获取多个同名参数(如复选框)

String[] hobbies = request.getParameterValues("hobby");

(3) 获取所有参数名

Enumeration<String> params = request.getParameterNames();

底层原理

GET 请求参数:

  • 参数从 URL 中解析(如 ?name=John&age=20),存储在 request 对象的参数集合中。
    POST 请求参数:
  • 参数从请求体(Body)中解析(如表单提交的 application/x-www-form-urlencoded 数据),同样存入 request 对象的参数集合。

关键点:

Servlet 容器(如 Tomcat)会自动解析这两种类型的参数,开发者无需关心参数来源,统一通过 request.getParameter() 访问。

如何选择 doGet 或 doPost?

用 doGet 当:

请求是幂等的(如搜索、分页查询)。

参数简单且非敏感(如 ?page=2)。

用 doPost 当:

修改服务器状态(如用户注册、支付)。

传递敏感数据(如密码、信用卡号)。

数据量大(如文件上传)。

注意事项

安全性:

GET 参数会出现在浏览器历史、服务器日志中,切勿用 GET 传递密码。

涉及数据修改的操作(如删除)应使用 POST,避免被爬虫或浏览器预加载触发。
编码问题:

GET 参数需手动处理 URL 编码:

      String keyword = new String(request.getParameter("q").getBytes("ISO-8859-1"), "UTF-8");

POST 参数可通过 request.setCharacterEncoding(“UTF-8”) 解决。
RESTful 设计:

现代 API 设计中,GET 仅用于查询,POST 用于创建,其他方法(PUT、DELETE)用于更新和删除。

总结
区别:doGet 和 doPost 对应不同的 HTTP 方法,语义和安全性不同。

共同点:均可通过 request.getParameter() 获取参数,Servlet 容器已屏蔽底层差异。

最佳实践:严格遵循 HTTP 方法的语义设计接口,避免混用或滥用。