目录 | 描述 |
---|---|
/test1_war_exploded | Web应用根目录,存储 jsp 或 html 文件 |
/test1_war_exploded/WEB-INF | 存放配置文件,不能直接访问 |
/test1_war_exploded/WEB-INF/classes | 存放编译后的 class 文件 |
/test1_war_exploded/WEB-INF/lib | 存放所需 jar 文件,如 JDBC 驱动的 jar 文件 |
web.xml:servlet 、servlet mapping 以及其他配置
编译 servlet 命令:
javac -sourcepath src -classpath D:\soft\server\apache-tomcat-9.0.37\lib\servlet-api.jar -d WEB-INF\classes src\mypack\DispatcherServlet.java
Servlet API 主要由两个 Java 包组成:javax.servlet
和 javax.servlet.http
。在 javax.servlet
中定义了 Servlet 接口以及相关通用接口和类。在 javax.servlet.http
主要定义了与 HTTP 协议相关的 HttpServlet 类、HttpServletRequest 接口和 HttpServletResponse 接口。
javax.servlet.Servlet
接口主要定义了servlet
基础生命周期方法:init(初始化)
、getServletConfig(配置)
、service(服务)
、destroy(销毁)
。
javax.servlet.http.HttpServlet
类继承于javax.servlet.GenericServlet
,而GenericServlet
又实现了javax.servlet.Servlet
和javax.servlet.ServletConfig
。而HttpServlet
不仅实现了servlet
的生命周期并通过封装service
方法抽象出了doGet/doPost/doDelete/doHead/doPut/doOptions/doTrace
方法用于处理来自客户端的不一样的请求方式,我们的Servlet只需要重写其中的请求方法或者重写service
方法即可实现servlet
请求处理。
TestServlet示例代码:
package com.anbai.sec.servlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Creator: yz
* Date: 2019/12/14
*/
// 如果使用注解方式请取消@WebServlet注释并注释掉web.xml中TestServlet相关配置
//@WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet"})
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
out.println("Hello World~");
out.flush();
out.close();
}
}
(1)web.xml
dispatcher
mypack.DispatcherServlet
dispatcher
/dispatcher
(2)使用 Annotation 标注
在 Servlet3.0 之后( Tomcat7+)可以使用注解方式配置 Servlet 了,在任意的Java类添加javax.servlet.annotation.WebServlet
注解即可。
……
import javax.servlet.annotation.*;
@WebServlet(name="FontServlet1", urlPatterns={"/font1"}, initParams={@WebInitParam(name="color",value="blue"),@WebInitParam(name="size",value="15")})
public class FontServlet1 extends HttpServlet{……}
HttpServletRequest 常用方法
方法 | 说明 |
---|---|
getParameter(String name) | 获取请求中的参数,该参数是由name指定的 |
getParameterValues(String name) | 返回请求中的参数值,该参数值是由name指定的 |
getRealPath(String path) | 获取Web资源目录 |
getAttribute(String name) | 返回name指定的属性值 |
getAttributeNames() | 返回当前请求的所有属性的名字集合 |
getCookies() | 返回客户端发送的Cookie |
getSession() | 获取session回话对象 |
getInputStream() | 获取请求主题的输入流 |
getReader() | 获取请求主体的数据流 |
getMethod() | 获取发送请求的方式,如GET、POST |
getParameterNames() | 获取请求中所有参数的名称 |
getRemoteAddr() | 获取客户端的IP地址 |
getRemoteHost() | 获取客户端名称 |
getServerPath() | 获取请求的文件的路径 |
HttpServletResponse 常用方法
方法 | 说明 |
---|---|
getWriter() | 获取响应打印流对象 |
getOutputStream() | 获取响应流对象 |
addCookie(Cookie cookie) | 将指定的Cookie加入到当前的响应中 |
addHeader(String name,String value) | 将指定的名字和值加入到响应的头信息中 |
sendError(int sc) | 使用指定状态码发送一个错误到客户端 |
sendRedirect(String location) | 发送一个临时的响应到客户端 |
setDateHeader(String name,long date) | 将给出的名字和日期设置响应的头部 |
setHeader(String name,String value) | 将给出的名字和值设置响应的头部 |
setStatus(int sc) | 给当前响应设置状态码 |
setContentType(String ContentType) | 设置响应的MIME类型 |
JSP 指令用来设置和整个网页相关的属性,如编码方式和脚本语言等
一般语法:
<%@ 指令名 属性="值"%>
指定所用的编程语言,与 JSP 对应的 servlet 接口,所拓展的类以及导入的软件包等
常用属性:https://www.cnblogs.com/sharpest/p/10068832.html
include 指令<%@ include file="filename" %>
包含其他文件(静态包含)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
引入标签库的定义
用于声明成员变量和方法
语法:<%! declaration;[declaration;]……%>
example:
<%! int v1=0;%>
<%! String v5="hello";
static int v6;
%>
<%!
public String amethod(int i){
return i+1;
}
%>
在 JSP 文件中,可以在 <%
和 %>
标记间嵌入任何有效的 Java 程序代码。
传统 Java 表达式:<%=
和 %>
之间
https://www.jb51.net/article/105314.htm
变量名 | 类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其他8个内置对象 |
request | HttpServletRequest | 客户端请求对象,包含了所有客户端请求信息 |
session | HttpSession | 请求会话 |
application | ServletContext | 全局对象,所有用户间共享数据 |
response | HttpServletResponse | 响应对象,主要用于服务器端设置响应信息 |
page | Object | 当前Servlet对象,this |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 异常对象 |
JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。
JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。
https://www.runoob.com/jsp/jsp-jstl.html
JDBC连接数据库的一般步骤:
Class.forName("数据库驱动的类名")
。DriverManager.getConnection(xxx)
。<!--首先导入一些必要的packages-->
<%@ page import="java.io.*"%>
<%@ page import="java.util.*"%>
<!--告诉编译器使用SQL包-->
<%@ page import="java.sql.*"%>
<!--设置中文输出-->
<%@ page contentType="text/html; charset=GB2312" %>
<html>
<head>
<title>dbaccess.jsp</title>
</head>
<body>
<%
try{
Connection con;
Statement stmt;
ResultSet rs;
//加载驱动程序,下面的代码加载MySQL驱动程序
Class.forName("com.mysql.jdbc.Driver");
//注册MySQL驱动程序
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//用适当的驱动程序连接到数据库
String dbUrl = "jdbc:mysql://localhost:3306/BookDB?useUnicode=true&characterEncoding=GB2312&useSSL=false";
String dbUser="root";
String dbPwd="root";
//建立数据库连接
con = java.sql.DriverManager.getConnection(dbUrl,dbUser,dbPwd);
//创建一个SQL声明
stmt = con.createStatement();
//增加新记录
stmt.executeUpdate("insert into BOOKS (ID,NAME,TITLE,PRICE) values('999','Tom','Tomcat Bible',44.5)");
//查询记录
rs = stmt.executeQuery("select ID,NAME,TITLE,PRICE from BOOKS");
//输出查询结果
out.println("");
while (rs.next()){
String col1 = rs.getString(1);
String col2 = rs.getString(2);
String col3 = rs.getString(3);
float col4 = rs.getFloat(4);
//打印所显示的数据
out.println(""+col1+" "+col2+" "+col3+" "+col4+" ");
}
out.println("
");
//删除新增加的记录
stmt.executeUpdate("delete from BOOKS where ID='999'");
//关闭数据库连接
rs.close();
stmt.close();
con.close();
//注销 JDBC Driver
Enumeration<Driver> drivers = DriverManager.getDrivers();
while(drivers.hasMoreElements()) {
DriverManager.deregisterDriver(drivers.nextElement());
}
}catch(Exception e){out.println(e.getMessage());}
%>
</body>
</html>
在真实的Java项目中通常不会使用原生的JDBC
的DriverManager
去连接数据库,而是使用数据源(javax.sql.DataSource
)来代替DriverManager
管理数据库的连接。一般情况下在Web服务启动时候会预先定义好数据源,有了数据源程序就不再需要编写任何数据库连接相关的代码了,直接引用DataSource
对象即可获取数据库连接了。
在 META-INF
目录下创建一个 content.xml
文件,在里面定义数据源
<Context reloadable="true" >
<Resource name="jdbc/BookDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="root" password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/BookDB?autoReconnect=true&useUnicode=true&characterEncoding=GB2312&useSSL=false"/>
Context>
web.xml
中加入
元素
<resource-ref>
<description>DB Connectiondescription>
<res-ref-name>jdbc/BookDBres-ref-name>
<res-type>javax.sql.DataSourceres-type>
<res-auth>Containerres-auth>
resource-ref>
获取 jdbc/BookDB 数据源引用,并获取连接对象
Connection con;
Context ctx = new InitialContext();
DataSource ds =(DataSource)ctx.lookup("java:comp/env/jdbc/BookDB");
con = ds.getConnection();
example
<%@ page import="java.io.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.sql.*"%>
<%@ page import="javax.sql.*"%>
<%@ page import="javax.naming.*"%>
<%@ page contentType="text/html; charset=GB2312" %>
dbaccess1.jsp
<%
try{
Connection con;
Statement stmt;
ResultSet rs;
//建立数据库连接
Context ctx = new InitialContext();
DataSource ds =(DataSource)ctx.lookup("java:comp/env/jdbc/BookDB");
con = ds.getConnection();
//创建一个SQL声明
stmt = con.createStatement();
//增加新记录
stmt.executeUpdate("insert into BOOKS(ID,NAME,TITLE,PRICE) values ('999','Tom','Tomcat Bible',44.5)");
//查询记录
rs = stmt.executeQuery("select ID,NAME,TITLE,PRICE from BOOKS");
//输出查询结果
out.println("");
while (rs.next()){
String col1 = rs.getString(1);
String col2 = rs.getString(2);
String col3 = rs.getString(3);
float col4 = rs.getFloat(4);
//打印所显示的数据
out.println(""+col1+" "+col2+" "+col3+" "+col4+" ");
}
out.println("
");
//删除新增加的记录
stmt.executeUpdate("delete from BOOKS where ID='999'");
//关闭结果集、SQL声明、数据库连接
rs.close();
stmt.close();
con.close();
}catch (Exception e) {out.println(e.getMessage());e.printStackTrace();}
%>
JavaBean 是特殊的 Java 类,使用 Java 语言书写,并且遵守 JavaBean API 规范,是一种可重复使用、且跨平台的软件组件。
JavaBean 示例
package mypack;
public class StudentsBean implements java.io.Serializable
{
private String firstName = null;
private String lastName = null;
private int age = 0;
public StudentsBean() {
}
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
public int getAge(){
return age;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
public void setAge(int age) {
this.age = age;
}
}
编译后的 .class 文件存放在 /WEB_INF/classes/mypack/
中
要想访问,首先需要导入:<%@ page import="mypack.StudentsBean"%>
使用
来声明:
属性:
id: 命名引用该Bean的变量。如果能够找到id和scope相同的Bean实例,jsp:useBean动作将使用已有的Bean实例而不是创建新的实例。
class: 指定Bean的完整包名
scope: 指定Bean在哪种上下文内可用,可以取下面的四个值之一:page,request,session和application
1. 默认值是page,表示该Bean只在当前页面内可用(保存在当前页面的PageContext内)。
2. request表示该Bean在当前的客户请求内有效(保存在ServletRequest对象内)。
3. session表示该Bean对当前HttpSession内的所有页面都有效。
4. application则表示该Bean对所有具有相同ServletContext的页面都有效。
type: 指定引用该对象的变量的类型,它必须是Bean类的名字、超类名字、该类所实现的接口名字之一。请记住变量的名字是由id属性指定的。
beanName: 指定Bean的名字。如果提供了type属性和beanName属性,允许省略class属性。
1)使用
标签
2)Java表达式
<%=myBean.getCount() %>
3)EL 表达式
${myBean.count}
给 JavaBean 属性赋值:
或
<% myBean.setCount(1);%>
javax.servlet.Filter
是Servlet2.3
新增的一个特性,主要用于过滤URL请求,通过Filter我们可以实现URL请求资源权限验证、用户登陆检测等功能。
Filter是一个接口,实现一个Filter只需要重写init
、doFilter
、destroy
方法即可,其中过滤逻辑都在doFilter
方法中实现。
package mypack;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
/*
@WebFilter( //用@WebFilter标注配置NoteFilter
filterName = "NoteFilter",
urlPatterns = "/note",
initParams = {
@WebInitParam(name = "ipblock", value = "221.45"),
@WebInitParam(name = "blacklist", value = "捣蛋鬼")}
)
*/
public class NoteFilter implements Filter {
private FilterConfig config = null;
private String blackList=null;
private String ipblock=null;
public void init(FilterConfig config) throws ServletException {
System.out.println("NoteFilter: init()");
this.config = config;
//读取拒绝IP地址
ipblock=config.getInitParameter("ipblock");
//读取blacklist初始化参数
blackList=config.getInitParameter("blacklist");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("NoteFilter: doFilter()");
if(!checkRemoteIP(request,response))return;
if(!checkUsername(request,response))return;
//记录响应客户请求前的时间
long before = System.currentTimeMillis();
config.getServletContext().log("NoteFilter:before call chain.doFilter()");
//把请求转发给后续的过滤器或者Web组件
chain.doFilter(request, response);
//记录响应客户请求后的时间
config.getServletContext().log("NoteFilter:after call chain.doFilter()");
long after = System.currentTimeMillis();
String name = "";
if (request instanceof HttpServletRequest) {
name = ((HttpServletRequest)request).getRequestURI();
}
//记录响应客户请求所花的时间
config.getServletContext().log("NoteFilter:"+name + ": " + (after - before) + "ms");
}
private boolean checkRemoteIP(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
//读取客户的IP地址
String addr=request.getRemoteAddr();
if(addr.indexOf(ipblock)==0){
response.setContentType("text/html;charset=GB2312");
PrintWriter out = response.getWriter();
out.println("对不起,服务器无法为你提供服务。
");
out.flush();
return false;
}else{
return true;
}
}
private boolean checkUsername(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
String username =((HttpServletRequest) request).getParameter("username");
if(username!=null)
username=new String(username.getBytes("ISO-8859-1"),"GB2312");
if (username!=null && username.indexOf(blackList) != -1 ) {
//生成拒绝用户留言的网页
response.setContentType("text/html;charset=GB2312");
PrintWriter out = response.getWriter();
out.println("对不起,"
+username + ",你没有权限留言 ");
out.flush();
return false;
}else{
return true;
}
}
public void destroy() {
System.out.println("NoteFilter: destroy()");
config = null;
}
}
Filter
的配置类似于Servlet
,由
和
两组标签组成,如果Servlet版本大于3.0同样可以使用注解的方式配置Filter
web.xml
<filter>
<filter-name>NoteFilterfilter-name>
<filter-class>mypack.NoteFilterfilter-class>
<init-param>
<param-name>ipblockparam-name>
<param-value>221.45param-value>
init-param>
<init-param>
<param-name>blacklistparam-name>
<param-value>捣蛋鬼param-value>
init-param>
filter>
使用 @WebFilter
标注
@WebFilter( //用@WebFilter标注配置NoteFilter
filterName = "NoteFilter",
urlPatterns = "/note",
initParams = {
@WebInitParam(name = "ipblock", value = "221.45"),
@WebInitParam(name = "blacklist", value = "捣蛋鬼")}
)
public class NoteFilter implements Filter {
Filter和Servlet的总结:https://javasec.org/javaweb/Filter&Servlet/
spring MVC 工作流程
lib 文件夹中必须包含 Spring 软件包的依赖
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0" >
<display-name>Spring MVC Sampledisplay-name>
<servlet>
<servlet-name>HelloWebservlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
servlet-class>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>HelloWebservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
为 DispatcherServlet 映射的URL为"/",所有访问应用的用户都会由 DispatcherServlet 来预处理,然后再由它转发给后续组件。为 DispatcherServlet 设置的 Servlet 名字为 “HelloWeb”,即必须为 Spring MVC 提供一个名为 HelloWeb-servlet.xml 的配置文件。
HelloWeb-servlet.xml
bean>
beans>
指定解析视图组件的为 InternalResourceViewResolver ,prefix 和 suffix 属性分别设定了视图文件的前缀和后缀。