JavaWeb
1.基本概念
1.前言
- web,网页
- 静态web
- 动态web
- 提供给所有人看的数据始终会变化
- 技术栈:JSP/Servlet,ASP,PHP
动态web资源技术开发技术统称为javaweb
2.web应用程序
应用程序编写完成之后,想给外界访问,需要一个服务器统一管理
3.动态web

2.web服务器
1.JSP/Servlet
- sun公司主推B/S架构
- 基于java
- 可以承载三高问题带来的影响
- 语法像ASP
2.web服务器
服务器是被动操作,用来处理用户的请求和返回响应信息
3.HTTP
HTTP(超文本传输协议),通常运行在TCP上
1.两个时代
==HTTP格式==
4.Servlet
1.开发流程
本质:一个接口,一个统一的web应用规范,一个协议
- 编写一个类,实现Servlet接口
- 把开发好的java类部署到web服务器中
把实现了Servlet接口的java程序叫做Servlet
2.HelloServlet
开发流程
-
构建普通Maven工程,删掉src目录,以后学习就在这个项目中建立Moudel,这个空的工程就是Maven主工程
-
关于Maven父子工程的理解:
<modules>
<module>study</module>
</modules>
<parent>
<artifactId>com.hznu.ch</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的依赖子项目都可以使用,相当于继承父类
-
Maven结构图
-
编写Servlet程序
- 编写普通类,实现Servlet接口,这里继承HttpServlet,并重写方法

public class ServletTest extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置字符编码
request.setCharacterEncoding("utf8");
//从 request 对象中获取username,password
String username = request.getParameter("username");
String password = request.getParameter("password");
request.setAttribute("username", username);
request.setAttribute("password", password);
request.getRequestDispatcher("/new.jsp").forward(request, response);
}
}
- 编写jsp页面
<html>
<body>
<h2>This is new Page</h2>
username: <%=request.getParameter("username") %>
<br>
password: <%=request.getParameter("password") %>
</body>
</html>
-
编写Servlet映射(web.xml)
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<!--映射名-->
<servlet-name>ServletTest</servlet-name>
<!--对应的类-->
<servlet-class>com.hznu.ch.servlet.ServletTest</servlet-class>
</servlet>
<servlet-mapping>
<!--映射名-->
<servlet-name>ServletTest</servlet-name>
<!--url-->
<url-pattern>/ServletTest</url-pattern>
</servlet-mapping>
</web-app>

- 配置Tomcat


- 访问资源文件

参考文献
idea搭建可运行Servlet的Web项目[maven]
3.Mapping
<servlet>
<servlet-name>ServletTest</servlet-name>
<servlet-class>com.hznu.ch.servlet.ServletTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletTest</servlet-name>
<url-pattern>/ServletTest</url-pattern>
</servlet-mapping>
*.ch
将ch后缀名的url映射到某个Servlet
4.优先级问题
- 精确匹配,servlet-mapping1:/user/users.html,servlet-mapping2:/*。当一个请求http: //localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配
- 路径匹配,先最长路径匹配,再最短路径匹配servlet-mapping1:/user/,servlet-mapping2:/。当一个请求http: //localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配
- 扩展名匹配,servlet-mapping1:/user/,servlet-mapping2:.action。当一个请求http: //localhost:8080/appDemo/user/addUser.action来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配
- 缺省匹配,以上都找不到servlet,就用默认的servlet,配置为/
5.原理
明确几件事:Tomcat的作用是将Socket传来的数据变成ServletRequest
类,交给Servlet处理
具体可以查看知乎大佬,里面有一个例子可以明白Tomcat做的最基本的事情,我来总结一下哈
Tomcat对Socket数据进行封装,请求包装成ServletRequest类,响应包装成ServletResponse类,然后都传给我们实现了Servlet接口的类,对这两个数据进行处理,再由Tomcat返回给客户端
Tomcat和Servlet的协同关系以及Servlet的生命周期

6.ServletContext

1.Servlet通信
//存入数据到ServletContext
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.setAttribute("username", "陈恒");
}
}
//读取ServletContext数据
public class GetNameServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext context = this.getServletContext();
resp.getWriter().print("姓名:" + context.getAttribute("username").toString());
}
}
2.获取初始化参数
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
resp.getWriter().print("参数:" + context.getInitParameter("url"));
}
}
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306?username=123&password=hhh</param-value>
</context-param>
3.请求转发

请求转发的url不会变,区别于重定向
简单解释:
浏览器A请求服务器B,B无法完成A所有的请求任务,所以直接将请求发送给服务器C了,这里不再经过A了,B发送给C的同时带着A给B的数据,然后再由C回传给A它之前请求的资源
实际整个转发过程:
客户浏览器发送http请求—>web服务器接受此请求—>调用内部的一个方法在容器内部完成请求处理和转发动作—>将目标资源发送给客户。在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的
public class RequestForward extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/first.jsp").forward(req, resp);
}
}
4.读取资源文件
1.防止maven导出资源失败
就比如说在java文件夹下的*.properties文件(ch.properties)无法被maven加载到target包中

在pom.xml文件中的<build></build>中添加这一段来要求maven添加java文件夹中的xml和properties文件
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>

同时我们也可以发现被maven打包的项目会自动生成一个classes目录(类路径),db.properties和com都在它的目录下面
2.maven生成的项目结构

3.读取配置文件
进入正题,怎么读取配置文件的源码
public class GetResourceServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
resp.getWriter().print(prop.getProperty("username"));
}
}
/*资源文件db.properties
username=ch
password=123
*/
7.HttpServletResponse
观察这个类的时候发现HttpServletResponse是装饰者模式,因为有ServletResponseWrapper类和HttpServletResponseWrapper类负责对ServletResponse和HttpServletResponse进行装饰
public class ServletResponseWrapper implements ServletResponse {
private ServletResponse response;//内置了一个被装饰者对象
......
}
ServletResponse源码
//这个类是响应报文的接口
public interface ServletResponse {
String getCharacterEncoding();
String getContentType();
ServletOutputStream getOutputStream() throws IOException;//输出字节流
PrintWriter getWriter() throws IOException;//输出字符流
void setCharacterEncoding(String var1);//设置编码格式
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);//设置文件格式 text/html...
void setBufferSize(int var1);
int getBufferSize();
void flushBuffer() throws IOException;
void resetBuffer();
boolean isCommitted();
void reset();
void setLocale(Locale var1);
Locale getLocale();
}
HttpServletResponse部分源码
//HttpServletResponse在ServletResponse上封装了关于HTTP的一些内容
public interface HttpServletResponse extends ServletResponse {
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
......
}
主要看一波状态码,以后不知道可以到这个类查了
- 200——成功状态码
- 3xx——请求重定向
- 4xx——找不到资源
- 5xx——服务器代码错误
基本应用
1.下载文件
public class DownloadServlet extends HttpServlet {
/**
* 1.文件路径
* 2.获取文件名
* 3.设置HTTP头部可以提供下载,并就中文文件名转码
* 4.获取文件输入流
* 5.输入到HTTP响应报文的输出流中
* */
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String realPath = "xxx/xxx/xxx/xxx.png";
String fileName = realPath.substring(realPath.lastIndexOf('/'));
resp.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
FileInputStream fis = new FileInputStream(realPath);
int len = 0;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes)) > 0) {
resp.getOutputStream().write(bytes);
}
}
}
2.验证码的实现
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//浏览器自动刷新
resp.setHeader("refresh", "3");
//内存中创建一个图片
BufferedImage bufferedImage = new BufferedImage(140, 20, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
//设置图片背景颜色
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, 100, 20);
//给图片写数据
graphics.setColor(Color.BLUE);
graphics.setFont(new Font(null, Font.BOLD, 20));
String str = productRandomNumber();
System.out.println("str=" + str);
graphics.drawString(str, 0, 20);
//请求用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires", -1);
resp.setHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "no-cache");
//把图片写给浏览器
ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}
private String productRandomNumber() {
Random random = new Random();
String ans = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7 - ans.length(); i++)
sb.append('0');
return sb.toString() + ans;
}
}
3.实现重定向
重定向url会改变

简单解释过程:
如图,浏览器A发送请求服务器B,B不能完全完成A想要的任务,所以B返回告诉A,让A去找服务器C完成接下来的任务,此时浏览器A重新发送新的请求给C,直到完成任务,这是一种直白的重定向解释。
实际整个重定向过程:
客户浏览器发送http请求—>web服务器接受后发送302状态码响应及对应新的location给客户浏览器—>客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址—>服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的
resp.sendRedirect("/s2/image");
//在这里等价于下面两句
//resp.setHeader("Location", "/s2/image");
//resp.setStatus(302);

这张图验证了重定向的操作流程,响应的状态码302——重定向,重定向的Location是/s2/image也没错
8.HttpServletRequest
基本应用
1.获取请求的参数
String getParameter(String var1);//获取单个参数
Enumeration<String> getParameterNames();//获取所有的name属性的值
String[] getParameterValues(String var1);//获取参数数组
2.请求转发
RequestDispatcher getRequestDispatcher(String var1);
3.注意点
resp.sendRedirect("/s2/success.jsp");//重定向因为需要浏览器再发送一次请求,所以需要包括上下文的url
req.getRequestDispatcher("/success.jsp").forward(req, resp);//请求转发是在Tomcat里面完成的,处在同一个上下文,所以不需要包括上下文
5.Cookie&Session
1.保存会话的两种技术
cookie
- 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了
- 客户端技术(响应,请求)
session
- 服务器登记你来过,下次来的时候匹配你
- 服务器技术(把信息存放到session中)
2.Cookie
- 从请求中拿到cookie信息
- 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies();//获得cookie数组
cookie.getName()//获得cookie的key
cookie.getValue()//获得cookie的value
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");//新建一个cookie
cookie.setMaxAge(24 * 60 * 60);//设置cookie1的有效期
resp.addCookie(cookie);//响应给客户端一个cookie
一个浏览器可以有多个cookie
3.Session
HttpSession session = req.getSession();//获取session
session.setAttribute("name", "陈恒");//设置键值对
String id = session.getId();//获取sessionid
session.isNew()//判断session是不是新创建的
String name = (String) session.getAttribute("name");//根据key获取value
session.removeAttribute("name");//移除session中某个键值对
session.invalidate();//清除session
配置web.xml自动失效的时限
<!--设置session默认的失效时间,这里以分钟作为单位-->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
cookie和session的区别
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session是把用户的数据写到用户独占Session中,服务端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器创建,某一时刻一个浏览器只能有一个Session
Cookie是把用户的数据写给浏览器,每次用户访问的时候会携带Cookie中用户信息,从而完成响应的操作
Seesion是把用户的数据存放在服务器中,把SessionId以Cookie的形式保存在浏览器中,用户每次访问的时候携带SessionId,服务器根据SessionId找到对应用户信息,从而完成响应操作

从上面这张图我们也可以看出来,我们并没有存储JSESESSION这个Cookie值,所以我们有理由相信服务器帮我们把SessionId写进客户端的Cookie里,以便我们下次访问服务器的时候可以根据这个SessionId找到对应的用户信息
使用场景:
- 保存一个登录用户的信息
- 购物车信息
- 在整个网站中经常使用的数据
6.JSP
1.什么是JSP
Java Server Pages:java服务器端页面,也和Servlet一样,用于动态Web技术
JSP像在写HTML
区别:HTML只给用户提供静态数据,JSP嵌入java代码,为用户提供动态数据
2.JSP原理

进入IDEA的Tomcat工作目录,我们发现jsp变成了java代码

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
JSP本质就是Servlet,因为HttpBase继承HttpServlet(我这里源码查看不了,但我看到网课上有的!!!)
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
......
//初始化jsp
public void _jspInit() {
}
//销毁jsp
public void _jspDestroy() {
}
//jsp服务
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
final java.lang.String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
return;
}
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("<html>\n");
out.write("<body>\n");
out.write("<h2>Hello World!</h2>\n");
out.write("</body>\n");
out.write("</html>\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
源码分析:
- 先做判断,查看请求方式
- 内置对象
final javax.servlet.jsp.PageContext pageContext;//页面上下文
javax.servlet.http.HttpSession session = null;//session
final javax.servlet.ServletContext application;//applicationcontext
final javax.servlet.ServletConfig config;//config
javax.servlet.jsp.JspWriter out = null;//输出
final java.lang.Object page = this;//当前页
HttpServletRequest req;//请求
HttpServletResponse resp;//响应
- 输出页面前增加的代码
response.setContentType("text/html");//设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
- 输出页面
out.write("<html>\n");
out.write("<body>\n");
out.write("<h2>Hello World!</h2>\n");
out.write("</body>\n");
out.write("</html>\n");
3.JSP转化流程

4.JSP基本语法
JSP表达式
<%--JSP表达式
作用:用来将程序输出,输出到客户端
<%= 变量或表达式%>
--%>
<%=new Date()%>
JSP脚本语言
<%--JSP脚本语言--%>
<%
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
out.println(sum);
%>
JSP声明
jsp声明会被编译到JSP生成的Java类中,其他的则会被生成到_jspService方法中
<%!
static {
System.out.println("陈恒");
}
private int globalVar = 0;
public void ch() {
System.out.println("进入ch方法");
}
%>
<%%>
<%=%>
<%!%>
<%----%>
5. 9大内置对象
- PageContext:页面上下文:存储数据
- Request:请求:存储数据
- Response:响应
- Session:session:存储数据
- Application【ServletContext】:存储数据
- config【ServletConfig】
- out
- page,几乎不用,可以不用了解
- exception
pageContext.setAttribute("name1", "1");//保存的数据只在一个页面中有效
request.setAttribute("name2", "2");//一次请求有效
session.setAttribute("name3", "3");//一次会话有效,从SessionID生成到Cookie中的Session失效
application.setAttribute("name4", "4");//在服务器中有效,从打开服务器到关闭服务器,主要用于用户共同访问的数据,如仓库中的数据,或者用于统计人数(就好像有个全局变量去存储人数一样,而不是每一次查询都一个人一个人的数过来)等等
底层到高层(作用域):page->request->session->application
page1
<%
pageContext.setAttribute("name1", "1");//保存的数据只在一个页面中有效
request.setAttribute("name2", "2");//一次请求有效
session.setAttribute("name3", "3");//一次会话有效,从打开浏览器到关闭
application.setAttribute("name4", "4");//在服务器中有效,从打开服务器到关闭服务器
%>
<%
//底层到高层(作用域):page->request->session->application
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5");
%>
<h1>${name1}</h1>
<h1>${name2}</h1>
<h1>${name3}</h1>
<h1>${name4}</h1>
<h1>${name5}</h1>

page2
<%
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5");
%>
<h1>${name1}</h1>
<h1>${name2}</h1>
<h1>${name3}</h1>
<h1>${name4}</h1>
<h1>${name5}</h1>

当跨页面时,pageContext和request就失效了
7.JavaBean
特定写法:
- 无参构造函数
- 属性private
- 必须有get/set方法
- 实现serializable接口
一般用来做和数据库的字段映射——ORM:对象关系映射
8.MVC三层架构

9.Filter
这里只是简写,详见SpringBoot篇
下面是最基本的过滤器用法,将请求和响应的编码格式改为UTF-8以解决中文乱码问题
还有就是filter的配置(和servlet没多少差别)
public class FilterTest implements Filter {
//随项目启动初始化
public void init(FilterConfig filterConfig) throws ServletException {
}
//过滤请求
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
filterChain.doFilter(servletRequest, servletResponse);
}
//随项目关闭销毁
public void destroy() {
}
}
<filter>
<filter-name>FilterTest</filter-name>
<filter-class>com.hznu.ch.servlet.FilterTest</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTest</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
10.Listener
实现一个监听器的接口
public class ListenerTest implements HttpSessionListener {
private static final String ONLINE = "online";
//创建session的监听
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer online = (Integer) ctx.getAttribute(ONLINE);
if (online == null)
ctx.setAttribute(ONLINE, 1);
else
ctx.setAttribute(ONLINE, (Integer) ctx.getAttribute(ONLINE) + 1);
}
//销毁session的监听
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer online = (Integer) ctx.getAttribute(ONLINE);
if (online == null)
ctx.setAttribute(ONLINE, 0);
else
ctx.setAttribute(ONLINE, (Integer) ctx.getAttribute(ONLINE) - 1);
}
}
级别update classes and resources最低,restart最高
- update resources ---- 更新静态的资源,比如html,js,css等 运行模式和调试模式都是立即生效;
- update classes and resources ---- 更新java,jsp和静态资源(编写了jsp等静态资源)
- redeploy ----- 重新部署,发布到tomcat里,不重启tomcat,而是把原来的删掉,然后重新发布(编写了Java代码)
- restart server ----- 重启tomcat(编写了配置文件,重启服务)

11.JDBC
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的

1.JDBC固定套路
public class JDBCTest {
public static void main(String[] args) throws Exception {
String url = "jdbc:mysql://localhost:3306/m_test?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "XXXX";
//1.加载mysql的驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.数据库对象Statement,用于CURD
Statement statement = connection.createStatement();
//4.编写sql语句
String sql = "select * from user";
//5.查询出结果集
ResultSet rs = statement.executeQuery(sql);
//6.编写业务逻辑
while (rs.next()) {
System.out.println("id=" + rs.getObject("id"));
System.out.println("username=" + rs.getObject("username"));
System.out.println("password=" + rs.getObject("password"));
}
//7.关闭连接
rs.close();
statement.close();
connection.close();
}
}
2.事务
ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库,必须要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求
原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节
一致性:一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性
隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作,如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据
持久性:在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚
connection.setAutoCommit(false);//开启事务,false是开启
connection.commit();//事务提交
connection.rollback();//事务回滚