前言

简单学了一下jsp和servlet,记录为主

javaWeb核心的三大组件

Servlet、Listener、Filter 由 javax.servlet.ServletContext 去加载,无论是使用 xml 配置文件还是使用 Annotation 注解配置,均由 Web 容器进行初始化,读取其中的配置属性,然后向容器中进行注册。
启动顺序为Listener -> Filter -> Servlet

Servlet

Servlet是Java EE的核心,也是所有的MVC框架的实现的根本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
//Servlet容器调用HttpServlet的init()方法
private int total = 0;
//Servlet容器接收到请求,根据请求信息,封装成HttpServletRequest和HttpServletResponse对象。
//Servlet容器调用service()方法。service()方法根据请求类型,分别调用doGet或者doPost方法,这里调用doGet方法。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");//这里的request实际为RequestFacade包装器
String password = request.getParameter("password");

response.setContentType("text/html;charset=UTF-8");

}
//容器关闭时候,会调用destory方法(该方面默认为空)
}

配置路由

1
2
3
4
5
6
7
8
9
10
11
12
//利用注解
@WebServlet(name="Hello", urlPatterns={"/Hello"})

//web.xml
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>com.mayylu.servlet.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/Hello</url-pattern>
</servlet-mapping>

Filter

当 Servlet 容器开始调用某个 Servlet 程序时,如果发现已经注册了一个 Filter 程序来对该 Servlet 进行拦截,那么容器不再直接调用 Servlet 的 service 方法,而是调用 Filter 的 doFilter 方法,再由 doFilter 方法决定是否去激活 service 方法

Filter 链中 Filter 的执行顺序通过 web.xml 配置的 Filter 过滤器,在同一路由下<url-pattern>,执行顺序由<filter-mapping>标签的配置顺序决定。<filter-mapping> 靠前,则 Filter 先执行,靠后则后执行。最后送到Servlet实现类中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class LogFilter implements Filter  {
//调用其init方法,读取web.xml配置,完成对象的初始化功能
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。
}
public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {
//如果在 Filter.doFilter 方法中没有调用 FilterChain.doFilter 方法,则目标 Servlet 的 service 方法不会被执行,这样通过 Filter 就可以阻止某些非法的访问请求
String name = req.getParameter("password");
if("123".equals(password)){password
// 把请求传送下一个Filter接口类
chain.doFilter(req, resp);
}else{
resp.setContentType("text/html;charset=GBK");
PrintWriter out = resp.getWriter();
out.print("<b>name不正确,请求被拦截,不能访问web资源</b>");
System.out.println("name不正确,请求被拦截,不能访问web资源");
}
}
// Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。
public void destroy( ){
/* 在 Filter 实例被 Web 容器从服务移除之前调用 */
}
}

一般来说Filter通常配置在MVC、Servlet和JSP请求前面,常用于后端权限控制、统一的Http请求参数过滤(统一的XSS、SQL注入、Struts2命令执行等攻击检测处理)处理,其核心主要体现在请求过滤上,而Servlet更多的是用来处理后端业务请求上。

Listener

Listener (监听器)用来监听Application、Session和Request三大对象的创建与销毁,通过 Listener,可以自动触发一些操作,如监听在线的用户数量,统计网站访问量、网站访问监控

1
2
3
4
5
6
7
8
9
10
11
public class TestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();//通过getServletRequest方法获得HttpServletRequest 对象
}

@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("initial TestListener");
}
}
1
2
3
<listener>
<listener-class>com.yyds.TestListener</listener-class>
</listener>
ServletContextListener 用于监听整个 Servlet 上下文(创建、销毁)
ServletContextAttributeListener 对 Servlet 上下文属性进行监听(增删改属性)

ServletRequestListener   对 Request 请求进行监听(创建、销毁)
ServletRequestAttributeListener 对 Request 属性进行监听(增删改属性)

javax.servlet.http.HttpSessionListener 对 Session 整体状态的监听
javax.servlet.http.HttpSessionAttributeListener:对 Session 属性的监听

javaweb基础操作

java文件操作

文件操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.File" %>
<%
File file = new File(request.getParameter("file"));
file.delete();//文件删除

File f = new File(request.getParameter("s"));
File d = new File(request.getParameter("d"));
f.renameTo(d);//重命名文件,如果目标路径已经存在同名文件,则操作失败

String[] files = new File(request.getParameter("dir")).list();//getParameter("dir")为文件夹地址,files为文件名组成的数组
for (String file : files) {
out.println(file);
}
%>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.nio.file.Files" %>
<%@ page import="java.nio.file.Path" %>
<%@ page import="java.nio.file.Paths" %>
<pre>
<%
try {
//文件复制,成功后返回复制后的目标路径 Path 对象,如果目标文件已经存在,则会抛出异常
Path path = Files.copy(Paths.get(request.getParameter("source")), Paths.get(request.getParameter("dest")));
} catch (IOException e) {
e.printStackTrace();
}
%>
</pre>

文件读写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.File" %>
<%@ page import="java.io.FileInputStream" %>
<%@ page import="java.io.FileOutputStream" %>
<pre>
<%
//request.getRealPath("/")获取当前所在
File file = new File(request.getRealPath("/") + request.getParameter("name"));//根据文件路径创造文件类
//读文件
FileInputStream is = new FileInputStream(file);//创建文件输入流
int len;
ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((len = is.read()) != -1) {
out.write(len);//输出
}
is.close();
//写文件
FileOutputStream fos = new FileOutputStream(file);
fos.write(request.getParameter("c").getBytes());
fos.flush();
fos.close();
%>
</pre>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.nio.file.Files" %>
<%@ page import="java.nio.file.Paths" %>
<pre>
<%
//读文件
try {
byte[] bytes = Files.readAllBytes(Paths.get(request.getParameter("file")));
out.println(new String(bytes));
} catch (IOException e) {
e.printStackTrace();
}
//写文件
Path path = Paths.get("/tmp/test.txt");
String content = "Hello World.";
try {
// 写入内容二进制到文件
Files.write(path, content.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
%>

文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.commons.io.IOUtils" %>
<%@ page import="java.util.Collection" %>
<%@ page import="java.io.File" %>
<%
String contentType = request.getContentType();
// 检测是否是multipart请求
if (contentType != null && contentType.startsWith("multipart/")) {
String dir = request.getSession().getServletContext().getRealPath("/uploads/");//文件上传路径
File uploadDir = new File(dir);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}

Collection<Part> parts = request.getParts();//获取所有上传的文件
for (Part part : parts) {
String fileName = part.getSubmittedFileName();// 获取文件名

if (fileName != null) {
File uploadFile = new File(uploadDir, fileName);// 创建本地文件;
part.write(uploadFile.getAbsolutePath()); // 将 Part 的输入流写入文件
} else {
out.println(part.getName() + ": " + IOUtils.toString(part.getInputStream()) + "<br/>");
}
}
}
%>
1
2
3
4
5
6
7
8
9
10
11
12
Collection<Part> parts = request.getParts();

for (Part part : parts) {
String fileName = part.getSubmittedFileName();

if (fileName != null) {
File uploadFile = new File(uploadDir, fileName);
FileUtils.write(uploadFile, IOUtils.toString(part.getInputStream(), "UTF-8"));//将字符串写入文件
} else {
out.println(part.getName() + ": " + IOUtils.toString(part.getInputStream()));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.commons.fileupload.FileItemIterator" %>
<%@ page import="org.apache.commons.fileupload.FileItemStream" %>
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>
<%@ page import="org.apache.commons.fileupload.util.Streams" %>
<%@ page import="java.io.File" %>
<%@ page import="java.io.FileOutputStream" %>
<%
// 检测是否为多媒体上传
if (ServletFileUpload.isMultipartContent(request)) {
ServletFileUpload fileUpload = new ServletFileUpload();
FileItemIterator fileItemIterator = fileUpload.getItemIterator(request);

String dir = request.getServletContext().getRealPath("/uploads/");// 获取上传目录
File uploadDir = new File(dir);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}

while (fileItemIterator.hasNext()) { // 遍历上传的文件
FileItemStream fileItemStream = fileItemIterator.next(); // 获取当前的 Part 对象
String fieldName = fileItemStream.getFieldName();// 字段名称

if (fileItemStream.isFormField()) {// 如果是普通表单字段
String fieldValue = Streams.asString(fileItemStream.openStream());// 字段值
out.println(fieldName + "=" + fieldValue);
} else {
String fileName = fileItemStream.getName(); // 获取文件名
File uploadFile = new File(uploadDir, fileName); // 创建本地文件
FileOutputStream fos = new FileOutputStream(uploadFile);

// 将 Part 的输入流写入文件
Streams.copy(fileItemStream.openStream(), fos, true);
out.println("文件上传成功:" + uploadFile.getAbsolutePath());
}
}
}

java数据库操作

传统的Web应用的数据库配置信息一般都是存放在WEB-INF目录下的*.properties*.yml*.xml中的,常见的存储数据库配置信息的文件路径如:WEB-INF/applicationContext.xml、WEB-INF/hibernate.cfg.xml、WEB-INF/jdbc/jdbc.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%
String sessionKey = "USER_INFO";
Object sessionUser = session.getAttribute(sessionKey);//返回类型为Object,Object 是 Java 中所有类的根类
Map<String, String> userInfo = null;

// 该属性值存在且属于 Map 类型
if (sessionUser instanceof Map) {
userInfo = (Map<String, String>) sessionUser;//Map为接口, HashMap为实现类
out.println("<p>欢迎回来:" + userInfo.get("username") + ",ID:" + userInfo.get("id") + " \r<a href='?action=exit'>退出登陆</a></p>");
return;
}

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

// 处理用户登陆逻辑
if (username != null && password != null) {
userInfo = new HashMap<String, String>();
ResultSet rs = null;
Connection connection = null;

try {
Class.forName("com.mysql.jdbc.Driver"); // 加载 MySQL JDBC 驱动程序
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaweb-bbs", "root", "root");// 建立数据库连接
String id = request.getParameter("id");
String sql = "select id, username, email from sys_user where id =? ";
PreparedStatement pstt = connection.prepareStatement(sql); // 创建预编译对象
pstt.setObject(1, id);// 设置预编译查询的第一个参数值
ResultSet rs = pstt.executeQuery();// 执行SQL语句并获取返回结果对象
while (rs.next()) {
userInfo.put("id", rs.getString("id"));
userInfo.put("username", rs.getString("username"));
userInfo.put("password", rs.getString("password"));
}

// 检查是否登陆成功
if (userInfo.size() > 0) {
// 设置用户登陆信息
session.setAttribute(sessionKey, userInfo);
// 跳转到登陆成功页面
response.sendRedirect(request.getServletPath());
} else {
out.println("<script>alert('登陆失败,账号或密码错误!');history.back(-1)</script>");
}
} catch (Exception e) {
out.println("<script>alert('登陆失败,服务器异常!');history.back(-1)</script>");
} finally {
// 关闭数据库连接
if (rs != null)
rs.close();
if (connection != null)
connection.close();
}
return;
}
%>

HIbernate常用的三种查询

  1. Criteria

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        public void SelectLike() {
    // 获取session
    Session session = HibernateUtil.openSession();
    // 查询主表信息:
    Criteria criteria = session.createCriteria(ZJ.class);
    //设置查询条件:查询姓名=‘赵小花’字的记录
    criteria.add(Restrictions.eq("name" ,"赵小花"));
    //返回查询结果并返回给集合
    List list = criteria.list();
    //打印信息
    System.out.println(list);
    }
  2. Hql

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public void findUserByLikeName1() {
    //实用工具类获取session
    Session session = HibernateUtil.openSession();
    String name ="张";
    //描写hql语句
    String hql = "FROM User WHERE name like '%" + name + "%' ";
    //创建查询对象
    Query createQuery = session.createQuery(hql);
    //获取结果集
    List list = createQuery.list();
    //打印结果集
    System.out.println(list);
    }
  3. sql

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public void findAllUserBySql1() {
    //实用工具类获取session
    Session session = HibernateUtil.openSession();
    //描写sql语句
    String sql = "select * from t_users7 WHERE user_name = ? ";
    //创建查询对象
    SQLQuery createSQLQuery = session.createSQLQuery(sql);
    //链式查询(将条件全部添加到一条语句上)
    createSQLQuery.addEntity(User.class)
    .setString(0, "张三");

    //获取唯一结果并进行强制转换
    List list = createSQLQuery.list();
    //打印结果集
    System.out.println(list);
    }

    Mybatis

    Mybatis中提供的参数占位符有两种:${…} 、#{…}

    #{…}

     执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
     使用时机:参数传递,都使用#{…}
    

    ${…}

     拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
     使用时机:如果对表名、列表进行动态设置时使用
    

JSP

从本质上说 JSP 就是一个Servlet ,因为 jsp 文件最终会被编译成 class 文件,而这个 class 文件实际上就是一个特殊的Servlet

JSP是以 Java 语言作为脚本语言的,JSP 网页为整个服务器端的 Java 库单元提供了一个接口来服务于HTTP的应用程序,特点是前后端不分离,嵌套在html中、

基础语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!--定义网页依赖属性,比如脚本语言、error页面、缓存需求等等-->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.io.*,java.util.*" %>
<!--文件包含-->
<%@include file="demo.jsp"%>
<!--引入标签库的定义-->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">

<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<%! private int total = 0; %>
<!-- jsp声明,其中写的内容将来会直接翻译在Servlet类中-->
<p>
<%
//脚本程序,写的内容会翻译在Servlet的Service方法(例如dopost或doget)中
%>
<% total++; %>
<p>当前进入次数:<%= total %></p>
<% total++; %>
<p>当前进入次数:<%= total %></p>
</p>
<p>
<!-- jsp表达式,用于将已经声明的变量或者表达式输出到网页上面-->
今天的日期是: <%= (new java.util.Date()).toLocaleString()%>
</p>
</body>
</html>
<%--隐藏注释的内容,不会显示在客户端的任何位置--%>

request对象

RequestFacade类实现了HttpServletRequest接口,request对象是javax.servlet.http.HttpServletRequest 类的实例。每当客户端请求一个JSP页面时,JSP引擎就会制造一个新的request对象来代表这个请求。
Facade类(封装类)充当了一个简化的门面,隐藏了底层子系统的复杂性,并将其封装在一个更高级的接口之下。

request对象提供了一系列方法来获取HTTP头信息,cookies,HTTP方法等等。

EL表达式

EL(Expression Language) 是为了使JSP写起来更加简单。