JavaEE
搞过 Java Web 开发的多少会知道 JavaEE。从字面上来看,它的意思是 Java Platform, Enterprise Edition,即 Java 平台企业版。实际上 Java EE 包含了一系列标准,这些标准主要用来为企业级应用提供分布式计算、Web 服务等的统一定义和接口。
Servlet
从实现上来说,Servlet 是一个实现了特定接口的 Web 组件,由 Servlet 容器去加载并运行。容器本身并不一定是 Web 服务器,但容器需要至少支持 HTTP 请求,并将请求的内容封装成 Servlet 接口的参数;目前常见的 Servlet 容器有如 Tomcat、GlassFish、JBoss 等
基础的接口如下
package javax.servlet;
import java.io.IOException;
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
service
方法,用于处理客户端的请求,并填充所需的返回结果。init
和 destory
是生命周期方法,在 Servlet 被加载和销毁时只执行一次。 getServletConfig
返回的对象是类似 name/value 格式的配置信息,由用户配置文件中进行传入。
基础使用
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
@WebServlet(name = "helloServlet", value = "/hello")
public class HelloServlet extends HttpServlet {
private String message;
public void init() {
message = "Hello World!";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>" + message + "</h1>");
out.println("</body></html>");
}
public void destroy() {
}
}
正常情况下定义好 HelloServlet 类之后,容器并不知道这个类的存在,也不知道应该将什么 HTTP 路径映射到这个 Servlet,传统上需要用户自己修改 web.xml 配置文件(这也是 Servlet 标准的一部分),添加 <servlet>
和 <servlet-mapping>
标签来指定这些信息。在 Servlet 3.0 之后,就可以使用注解的方式配置 Servlet 了,如上面的 WebServlet 注解。
Filter
用于为所有 Servlet 添加全局性的鉴权和过滤,一个简单的示例如下:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.io.PrintWriter;
@WebFilter(filterName = "HelloFilter", urlPatterns = {"/*"})
public class HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String passwd = servletRequest.getParameter("passwd");
if (passwd != null && passwd.equals("123456")) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
try (PrintWriter out = servletResponse.getWriter()) {
out.println("passwd error!");
}
}
}
@Override
public void destroy() {
}
}
JSP
JSP 的全称是 Java Server Pages,包含一系列技术的组合,既表示动态网页的框架,也表示一种文件类型。JSP 的标准为 JSR 245,其中包含两个主要文档,分别是 JSP 的标准文档和 JSP EL 表达式的标准。
我们可以用 Servlet 来生成网页中的动态内容。但存在一个问题,就是即使我们只做出微小的修改,也需要对源码进行重新编译和部署。JSP 解决了 Servlet 的这些问题,它是 Servlet 很好的补充,可以专门用作为用户呈现视图(View),而 Servlet 作为控制器(Controller)专门负责处理用户请求并转发或重定向到某个页面。
底层原理
SP 作为一个脚本引擎,其本质上也是通过 Servlet 实现的,即 JSP 会被容器编译为对应的 Servlet 并加载。该类在第一次访问的时候才会生成、编译、加载,因此对于没访问过的页面是没有对应文件的。另外,在 jspService 方法中为了方便 JSP 的代码编写,定义了几个常用的对象。
request,对应客户端请求的 HttpServletRequest 对象;
response,对应返回的 HttpServletResponse 对象;
session,对应 HttpSession,存储当前请求会话信息;
application,对应 ServletContext,用于全局共享数据;
config,对应 ServletConfig 即 Servlet 的配置对象;
page,为 Object 类型,指向当前 Servlet 对象;
out,即控制页面输出的 JspWriter;
pageContext,当前页面共享数据对象;
这几个对象通常称为 JSP 的 “八大对象”,或者 “九大对象” (算上 exception 对象)。
Java 表达式语言
上节中我们说到 JSP 的标准中包含了两份文档,一份是 JSP 语言本身的标准,另一份则是表达式语言的标准。Java 表达式语言即 Expression Language,简称为 EL,虽然 JSP 中可以写 Java 代码,但这一方面对不懂 Java 语言的人不太友好,另一方面很多时候我们仅需要在 JSP 中执行比较、循环、加减乘除等简单操作,而引入完整的 Java 引擎显得有点 overkill 了。
public class ELTestServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
List list = new ArrayList<>();
list.add(Double.valueOf(1.0));
list.add(Double.valueOf(2.0));
list.add(Double.valueOf(3.0));
ELProcessor elp = new ELProcessor();
elp.defineBean("data", list);
Object message = (Double)elp.eval(
"n = data.stream().count(); s = data.stream().sum(); sq = data.stream().map(i -> i*i).sum(); Math.sqrt(sq/n - Math.pow(s/n, 2))");
res.getWriter().println(message);
message = (Double)elp.eval(
"n = 0; s = 0; sq = 0; data.stream().forEach(d -> (n = n + 1; s = s + d; sq = sq + d*d)); Math.sqrt(sq/n - Math.pow(s/n, 2))");
res.getWriter().println(message);
message = (Double)elp.eval(
"n = 0; s = 0; sq = data.stream().reduce(0, (a, i) -> (n = n + 1; s = s + i; a + i*i)); Math.sqrt(sq/n - Math.pow(s/n, 2))");
res.getWriter().println(message);
}
}
这类表达式语言通常作为模版语言在 Web 页面中使用,如果其中的表达式能够被恶意输入所控制,就可能出现任意代码执行的危害。历史上出现过许多由于 EL 表达式注入导致的远程代码执行,因此这算是 Java 中高危的攻击面之一
JDBC
在传统 MVC 架构中,将内容呈现的过程分成模型(Model),视图(View),控制器(Controller)三个部分,现在我们已经介绍了控制器部分的 Servlet,视图层的 JSP,为了使得一个网页能够真正有价值,还缺少其中关键的模型部分,即数据来源。
JDBC (Java Database Connectivity) 就是 Java 访问数据库的一个标准。
使用方法
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws Exception {
// Class.forName("com.mysql.jdbc.Driver");
// 1. Establishing the connection with the database
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb?useSSL=false", "root", "rxhtemp");
// 2. Creating a statement object to execute a query
Statement stmt = conn.createStatement();
// 3. Executing the query and getting the ResultSet
ResultSet rs = stmt.executeQuery("SELECT * FROM user");
// 4. Processing the ResultSet
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println("ID: " + id + ", Name: " + name);
}
// 5. Closing the database resources
rs.close();
stmt.close();
conn.close();
}
}
JMX
JMX 全称为 Java Management Extensions,即 Java 管理拓展,主要用于管理和监控 Java 程序。
组成部分
MBean:
全称是 Managed Bean,类似于 Java Bean,主要用来进行消息传递。与 Java Bean 的区别是 JMX 中对这些 Bean 进行了额外的定义,兼容 JMX 标准的 MBean 才可以被加载。
MBeanServer,主要用于 MBean 的管理,同名接口定义在 javax.management 中,包含 MBean 创建、注册以及删除等操作相关的接口。
Connector/Adaptor:
这是直接面对客户端的组件,负责具体协议的连接或者转换。在 JMX 标准中提到,RMI Connector 是在 JMX 标准实现中唯一强制实现的协议。RMI (Remove Method Invocation) 是 Java 中的远程调用接口,其具体的传输协议可以不同,常见有以下两种:
JRMP (Java Remote Method Protocol),这是 RMI 的默认传输协议,专为 Java 而开发,因此性能较好;
IIOP (Internet Inter-ORB Protocol),CORBA 标准的一部分,依赖于 CORBA 类库,因此可以实现多语言传输 RMI 远程对象,更适用于跨平台开发;
Adaptor :
称为适配器,和连接器类似,主要将客户端对服务器中 MBean 的操作适配为其他协议,比如 SNMP 或者 HTTP 等。例如,Jolokia 就是一个常用的开源 JMX-HTTP 适配器,可以使远程的 JMX 客户端通过 HTTP/HTTPS 协议访问 JMX MBean。
使用示例
JMX 要求 MBean 首先需要是一个接口,且接口名字以 MBean 结尾,例如:
public interface DemoMBean {
String getName();
String getPassword();
void say(String what);
}
一个具体的 MBean 需要实现上述接口:
class Demo implements DemoMBean {
@Override
public String getName() { return "evilpan"; }
@Override
public String getPassword() { return "jmxdemo"; }
@Override
public void say(String what) {
System.out.println(getName() + " say: " + what);
}
}
为了能够被客户端访问,需要将该 MBean 的实例注册到 MBeanServer:
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName userName = new ObjectName("com.evilpan:type=Foo,name=bar");
server.registerMBean(new Demo(), userName);
客户端连接设置
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
// Register MBean ...
LocateRegistry.createRegistry(7890);
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:7890/jmxrmi");
JMXConnectorServer jcs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
jcs.start();
参考链接
https://evilpan.com/2023/04/01/java-ee/
标签:Java,void,基础,安全,JSP,MBean,Servlet,public From: https://www.cnblogs.com/Ho1dF0rward/p/18364739