Java Web
HTTP协议
网络传输协议,称为:超文本传输协议
处理流程:
1,客户端向服务端发送请求
2, 服务器接收客户端的请求
3, 处理客户端的请求数据,做出响应
4,客户端获取响应后做出页面的展示(只能是静态页面)
整个请求过程处于无连接状态
Java实现动态网站的技术
servlet
就是一个java类,继承至HttpServlet
主要作用:
获取客户端的请求(请求数据)
进行处理
发送响应给客户端(也有一些数据,文件,图片)
jsp
其本身也是servlet
Web 容器
负责管理和运行servlet
常见的web容器由:
tomcat
Jboss
weblogic
…
Tomcat
Tomcat的目录结构:
bin: 可以开启和关闭服务器
conf:存放的是各种配置文件
server.xml:可以修改端口号,可以修改请求的编码格式,还可以进行项目部署
tomcat_users.xml:配置管理界面的用户信息
web.xml:可以修改session的有效时间
context.xml:可以进行项目部署
Catalina\localhost: 进行项目部署
lib:第三方jar依赖
logs:记录服务器在运行时产生的日志
temp:临时文件夹
webapps:所部署的web app
work:工作空间
创建web项目
不同的开发工具创建的项目方式不同
但最终运行时所需要的目录结构是相同的
WEB-INF 对用户是隐藏的,无法通过路径直接访问资源
classes
lib
web.xml
静态资源 或者是jsp
项目部署
第一种:直接将web下的资源拷贝到tomcat webapps下
第二种:通过工具生成war文件,打war包(适用于开发完成的时候)
第三种: 通过配置文件进行项目部署
修改server.xml
在节点中添加
<Context path="/项目名(访问时需要的名字)" docBase=" 指向项目中的工作空间 C:\Users\Administrator\IdeaProjects\JavaWeb\web0908\web " />
第四种:在apache-tomcat-8.5.41\conf\Catalina\localhost路径下创建 xxx.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<Context path="无效的" docBase="C:\Users\Administrator\IdeaProjects\JavaWeb\web0908\web" />
xxx:指的是项目访问的路径
如果xxx.xml 是ROOT.xml 则通过tomcat的根路径就能访问此项目
第五种:
用开发工具部署项目
Servlet
是运行在web服务器中Java程序,是动态网站的实现技术
由web容器(Tomcat)负责管理和运行servlet
Servlet的生命周期
从创建到销毁的整个过程
1,创建 (默认在servlet第一次被访问时创建) 只执行一次
2, 初始化 init()
3,运行(服务)调用service方法,根据请求进行服务分发
4, 销毁 destroy 通常是用来保存一些数据或者关闭一些资源,会由垃圾回收器进行对象的销毁
运行在多线程环境下,建议不要在servlet中使用成员变量
servlet中进行初始化参数配置
配置serlvet init
@WebServlet(name = "InitParmServlet",value="/initParmServlet", initParams = {@WebInitParam(name="driver",value="com.mysql.jdbc.Driver")})
<servlet>
<servlet-name>InitParmServlet</servlet-name>
<servlet-class>com.gxa.day0910.InitParmServlet</servlet-class>
<!-- -->
<init-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
</servlet>
配置全局参数
<!--全局参数-->
<context-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver.ContextParam</param-value>
</context-param>
//获取全局上下文对象
ServletContext application = config.getServletContext();
String value = application.getInitParameter("driver");
System.out.println(value);
ServletContex 在整个应用程序中可以共享数据
将数据存放在attribute setAttribute可添加或修改数据
application.setAttribute("count",count);
如果其他地方想要使用这个数据 getAttribute获取
application.getAttribute("count")
如果数据不存在,返回null
web项目中的路径
request.getRequestURI() //返回的是请求的路径 不含ip地址和端口号
result:getRequestURI:/url
request.getRequestURL() //获取的客户端浏览器访问的地址
result:getRequestURL:http://localhost:8888/url
String path = request.getServletContext().getRealPath(“upload”) //物理路径 磁盘路径
获取请求参数:
String userName = req.getParameter("userName");
String userPwd = req.getParameter("userPwd");
String userAge = req.getParameter("userAge");
// String fav = req.getParameter("fav");
String[] fav = req.getParameterValues("fav");
如果参数不存在,返回null,如果参数存在无值则为空字符串
GET和POST请求的区别:
GET:会将参数跟在url地址后面 ?name=value&xxx
get传递的数据类型只能是字符串 有大小限制 查询效率比较高
POST: 则参数不会出现在url地址中,相对安全
可以传递文件数据 无大小限制 一般只在上传文件时要求使用post请求
文件上传:
页面三要素:
1,提交方式必须为post
2,enctype="multipart/form-data" 复合表单数据
3,file必须有name
处理文件的Servlet
@WebServlet("/upload")
@MultipartConfig //此注解表示当前可处理文件类型数据 servlet3.0的用法
public class UploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Part part = req.getPart("photo");
//
// Part part1 = req.getPart("idCardZheng");
//
// Part part2 =req.getPart("idCardFan");
// req.getPart()
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
String path = req.getServletContext().getRealPath("upload");
//获取上传后的文件名
String fileName = uploadFile(part,path);
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>");
out.println("上传成功:<img src='upload/"+fileName+"'/>");
out.println("</body></html>");
}
public String uploadFile(Part part,String path) throws IOException{
System.out.println(part.getSubmittedFileName());//获取上传后的文件名
InputStream inputStream = part.getInputStream();
//文件拷贝的过程
byte[] bytes = new byte[1024];
int length = 0;
System.out.println(path);
File file = new File(path);
if(!file.exists()){
file.mkdir();
}
UUID uuid = UUID.randomUUID();
String fileName = uuid.toString()+part.getSubmittedFileName();
OutputStream outputStream = new FileOutputStream(file+"/"+fileName);
while((length = inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,length);
}
outputStream.close();
inputStream.close();
return fileName;
}
}
乱码处理:
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
注意定位乱码的位置
可能出现乱码的地方:
1, 数据库读取中出现乱码(解决方式:数据库连接的url地址中加上编码处理)
2,响应结果中 (解决方式:response.setCharacterEncoding(“UTF-8”))
3, 网页显示中 (解决方式,设置网页的编码格式)
Response响应
默认是以text/html的格式进行响应
页面跳转
重定向: 客户端发起两次请求,url地址会发生变化,重定向之后不能再重定向或请求转发
resp.sendRedirect("/myServlet");
请求转发:客户端只发起了一次请求,是在服务器完成的跳转,url地址不会变,可以访问WEN-INF下的资源
req.getRequestDispatcher("myServlet").forward(req,resp);
通过请求转发,可在一次完整的请求中共享数据
req.setAttribute("request","requestValue");
用servlet生成一个登录页面,登录成功,进入个人中心(重定向 ),登录失败,继续回到登录页面(请求转发),并显示(用户名或密码错误)存放在request的作用域中
以图片形式进行响应(验证码)
response.setContentType("image/jpg");//设置响应类型,告诉浏览器输出的内容为图片
以文件下载形式进行响应
String fileName = request.getParameter("fileName");
resp.setContentType("application/octet-stream"); //octet-stream支持所有的文件类型
//解决 以文件形式下载 而不会被浏览器打开
resp.setHeader("Content-Disposition", "attachment;filename="+fileName);
PrintWriter os = resp.getWriter();
String path = this.getServletContext().getRealPath("/download");
File file = new File(path+"//"+fileName);
if(file.exists()){
InputStream is = new BufferedInputStream(new FileInputStream(file));
int len=0;
byte[] buffer = new byte[200];
while((len=is.read(buffer))!=-1){
os.print(new String(buffer,0,len));
}
is.close();
os.close();
}
}
web会话技术
HTTP属于无状态的超文本传输协议
Cookie
客户端的会话技术,数据是存放在浏览器中的
cookie是以键值对的形式存放到客户端中,并且key和value都是字符串
默认有效时间:浏览器关闭cookie就会失效
实现步骤:
1,客户端向服务器第一次发送请求
2,服务器将cookie添加到客户端中 response.addCookie(cookie);
3,客户端在本站点中再次发送请求
4,服务器可在请求中获取到来自客户端的cookie数据 request.getCookies
request.getCookies(); //从请求中获取cookies信息
向浏览器添加cookie数据
Cookie cookie1 = new Cookie("olduser","true");//key不能是中文,value可以为中文,但是需要转码
response.addCookie(cookie1);
key不能是中文,value可以为中文,但是需要转码,但不推荐使用中文作为值
设置有效时间
//单位:秒
cookie1.setMaxAge(60*60*24);
cookie2.setMaxAge(60*60*24);
想要删除某个cookie,设置有效时间为0,还需添加到客户端去
cookie是存放在客户端中的,只能存字符串,并且每个站点对cookie的个数是有限制
cookie优点:将数据存放在客户端,可减轻服务端的压力
缺点:只能存字符串,并且每个站点对cookie的个数是有限制
作业:
使用cookie实现记住用户密码一周的功能
Session
基于服务端的会话技术,将数据存放在服务端
基于的cookie的技术实现的
// request.getSession() 实现原理
// 初次访问时,没有cookie JSESSIONID new Session() 会产生一个sessionId 并将此Id添加到cookie中 Map("id",session)
//再次访问时,JSESSIONID就有了 而是根据id 去查找session
getSession() 和getSession(Boolean flag)
flag为false时,会先从cookie中获取jsessionId,如果有,则根据jsessionId去查找session,如果没有,则返回null
flag为true时,会先从cookie中获取jsessionId,如果有,则根据jsessionId去查找session,如果没有,则会新建一个session
默认浏览器关闭,当前会话就结束,并不是session失效了,只是因为cookie不存在
在session中共享数据:
session.setAttribute("user",userName);//添加或修改数据
session.getAttribute("user")//根据key获取数据,如果数据不存在,返回null
使session失效的方法:
session.removeAttribute("user");//将数据从session中移除 推荐
session.invalidate();//让整个session失效 当然也就无法共享数据
session默认的最大非活动间隔时间为30分钟,在tomcat 的web.xml中可配置,只能是整数,单位:分钟
<session-config>
<session-timeout>30</session-timeout>
</session-config>
在程序中设置session的最大非活动间隔时间
//最大非活动间隔时间 秒
session.setMaxInactiveInterval(3);
利用session实现购物车功能
作业:
1,完善购物车的删除和清空购物车功能
2,实现验证码的验证功能
URL重写
当客户端中cookie被禁用时,每次拿到的session都是新的,不代表session失效了
//当cookie被禁用时,使用url重写技术(目的是为了把session传入getSession方法)
String url = response.encodeRedirectURL("personal");// 进行url编码
System.out.println(url);
response.sendRedirect(url);
response.encodeRedirectURL()会检测浏览器是否禁用cookie,如果禁用了就把sessionId作为参数传递过去,如果没有禁用,则此方法不做任何处理
response.encodeURL() 和encodeRedirectURL是一样的,会在请求后面添加;jsessionId=XXXXX ?参数
ServletContext HttpSession HttpServletRequest 的作用域分别是什么?
ServletContext:应用上下文 (整个应用程序中,只有一个application对象存在,可以在整个应用程序中共享此对象以及对象中的数据)
只要服务器不重启,数据就可以一直共享
HttpSession : request.getSession() 一个完整的会话过程中 只要浏览器不关,只要session不失效 可以共享数据
HttpServletRequest : 一次完整的请求中 体现在请求转发中
pageContext:当前页面中
过滤器和监听器
过滤器
一个中间组件,用于拦截源数据和目的数据之间的消息
过滤器的作用:在真正到达请求之前做前置处理
编写过滤器:
实现filter接口 init doFilter(request,response,filterChian)
@WebFilter(filterName = "LoginFilter",value = "*.do") //注解注册过滤器
public class LoginFilter implements Filter {
<filter>
<filter-name>encodeFilter</filter-name>
<filter-class>com.gxa.filter.EncodeFilter</filter-class>
<!-- <init-param>-->
<!-- <param-name></param-name>-->
<!-- <param-value></param-value>-->
<!-- </init-param>-->
</filter>
<filter-mapping>
<filter-name>encodeFilter</filter-name>
<url-pattern>/aa</url-pattern>
</filter-mapping>
web.xml
url-pattern: 可以直接配置某个路径 也可以使用通配符*
常用:/* (所有请求,包含静态资源) 不推荐使用
*.do *.action *.jsp
过滤器的生命周期:
创建并初始化 init():服务器启动时
运行:doFilter方法
销毁 destory(): 服务器关闭时
filterChain.doFilter(servletRequest,servletResponse);//放行
可以放行到下一个过滤器中,或者到真正的请求中
FilterConfig对象
可获取初始化参数,或者应用上下文对象
监听器:
程序运行过程中检测是否发生了某种状态,从而做出相应的处理
Servlet监听器主要目的是给Web应用增加事件处理机制,以便更好地监视和控制Web应用的状态变化
到底监听哪些东西呢?
主要是对作用域对象进行监听(ServletContext,HttpSession,HttpServletRequest)
监听器类需要实现某个监听接口
web.xml
<listener>
<listener-class>com.gxa.listner.ApplicationListner</listener-class>
</listener>
注解配置:
@WebListener
public class ApplicationListner implements ServletContextListener {
可以同时对某一个监听器类实现多个监听接口
对其生命周期进行监听
ServletContextListener HttpSessionListener ServletRequestListener
对其属性进行监听
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
String name = httpSessionBindingEvent.getName();
String value = String.valueOf(httpSessionBindingEvent.getValue());
if(name.equals("user")){
System.out.println(value+"登录了"+new Date());
}
System.out.println(name+"属性添加了"+value);
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("属性删除了 ");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("属性修改了 ");
}
(根据老师上课笔记整理的,有不完整的地方请大家理解)