javaWeb
在java中,动态web资源开发的技术统称为JavaWeb
一些默认
tomcat:8080
mysql:3306
http:80
https:443
默认的主机名:loaclhost->127.0.0.1
默认网站应用存放的位置:webapps
网站时如何进行访问的
- 输入一个域名,回车
- 检查本机的hosts配置文件下有没有这个域名映射
- 有:直接返回对应的ip地址
- 无:去DNS服务器(全世界的域名都在这里管理)找
发布一个web网站
- 将自己写的网站放到服务器中指定的文件夹(webapps)下就可以访问了
--webapps:Tomcat服务器的web目录
-ROOT
-网站的目录名
-WEB-INF
-classes:java程序
-lib:web应用所依赖的jar包
-web.xml:网站配置文件
-index.html默认的首页
-static
-css
-js
-img
HTTP
超文本传输协议,是一个简单的请求-响应协议,通常运行在TCP上
HTTPS
S代表安全
http请求
客户端----发请求(request)-----服务器
请求行
- 请求行中的请求方式:GET
- 请求方式:GET/POST/HEAD/DELETE/PUT/TRACT.....
- GET:一次请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- POST: 一次请求能够携带的参数没有限制 ,大小没有限制,不会显示数据内容,安全,但是不高效
消息头
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码类型 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:浏览器的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机
http相应
服务器----响应-----客服端
Cache-Control:private 缓存控制
Connection:Keep-Alive 连接
Content-Encoding:gzip 编码
Content-Type:text/html 类型
响应体
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码类型 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:浏览器的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机
Refrush:多久刷新一次
Location:让网页重新定位:
相应状态码
200:请求相应成功
4xx:找不到资源 404
3xx:请求重定向
- 重定向:重新到新的位置去
5xx:服务器代码错误 500 502(网关错误)
Maven
核心思想:约定大于配置
pom.xml是maven的核心配置文件
Servlet
sun公司开发动态web的一门技术
sun在这些API中提供了一个接口叫Servlet
开发Servlet程序只需要完成
- 编写一个类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
把实现了Servlet接口的Java程序叫做servlet
Servlet接口在sun公司有两个默认的实现类:HttpServlet
Servlet接口-->GenericServlet-->HttpServlet
HelloServlet
-
创建一个普通的maven项目,删掉src目录,以后就在这个项目里创建module;这个空的工程就是maven的主工程
-
通过1形成了父子项目
-
Maven环境优化
- 修改web.xml为最新的
<?xml version="1.0" encoding="UTF-8"?> <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" metadata-complete="true"> </web-app>
- 将maven的结构搭建完整(java,resources)
-
编写一个Servlet程序
- 编写一个普通类
- 实现Servlet接口
-
编写Servlet映射(在web.xml中)
- 需要映射的原因:我们写的是一个java程序,但是通过浏览器访问,而浏览器需要web服务器,所以我们需要在web服务器中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径
<servlet>
<servlet-name>hello</servlet-name>//自定义名字
<servlet-class>com.zaughter.servlet.HelloServlet</servlet-class>//java文件路径(从java文件夹开始写)
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>//上面的自定义名字
<url-pattern>/hello</url-pattern>//访问请求的路径(注意加/)
</servlet-mapping>
- 配置tomcat
mapping问题
- 一个servlet可以指定一个映射路径,也可以指定多个(多写几个mapping),可以以指定通用映射路径(通配符*),也可以用通配符指定路径的前缀与后缀(*前面不能加映射的路径)
- mapping有优先级,固有的映射路径优先级最高,找不到就会走默认的路径
ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
共享数据
(一般用其他方法)
servlet可以得到另一个servlet的数据
ServletContext context = this.getServletContext();
String username = "赵浩恒";
context.setAttribute("username",username);//通过键值对,将username上传到servletcontext中
System.out.println("hello");
ServletContext servletContext = this.getServletContext();
String username = (String) servletContext.getAttribute("username");
resp.setContentType("text/html");//设置中文
resp.setCharacterEncoding("utf-8");//设置中文
resp.getWriter().print("名字" + username);//得到并输出username,这里是一个连用
}
得到初始化的参数
(几乎不用)
//web.xml中
<context-param>
<param-name>url</param-name>//参数名字
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>//参数内容
</context-param>
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
请求传递
(一般用request)
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/gp").forward(req,resp);
//当请求s4的时候,会通过getREquestDispatcher把请求转发到/gp页面,
/gp页面
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
读取资源文件
(也可以用类加载或者反射实现)
Properties
- 在java目录下新建(可能无法导出,需要在build中配置resources,防止资源导出失败)
- 在resources目录下新建
都被打包到了classes路径下,俗称classpath
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//从target/module名开始写路径,把它转化为一个文件流
Properties properties = new Properties();
properties.load(is);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
resp.getWriter().print(username+":"+password);
HttpServletResponse
web服务器接收到客户端的http请求,会针对这个请求,分别创建一个代表请求的HttpServletRequest,一个代表相应的HttpServletResponse
- 如果要获取客户端请求过来的参数,找request
- 如果要给客户端响应一些信息,找response
简单分类
负责向浏览器发送数据的方法
ServletOutputStream getoutputStream()
PrintWriter getWriter()
负责向浏览器发送响应头的方法
void setCharacterEncoding
void setContentLength
void setContentLengthLong
void setContentType
void setDateHeader
void setHeader
void addHeaader
void setIntHeader
void addIntHeader
所有状态码常量
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;
常见应用
1.向浏览器输出消息
2.下载文件
- 要获取下载文件的路径
- 下载的文件名?
- 设置想办法让浏览器支持(Content-disposition)下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutPutStream对象
- 将FileOutPutStream(例子)流写入到buffer缓冲区,使用OutPutStream将缓冲区的数据输出到客户端
- 关流
//1. 要获取下载文件的路径
ServletContext servletContext = this.getServletContext();
String realPath = "D:\\study files\\java files\\javaweb-onelastchance\\response\\target\\classes\\1.png";
//2. 下载的文件名?
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
//3. 设置想办法让浏览器支持下载我们需要的东西
resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));//使用URLEncoder方式保证中文文件名能正常显示
//4. 获取下载文件的输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
//5. 创建缓冲区
int len=0;
byte[] buffer = new byte[1024];
//6. 获取OutPutStream对象
ServletOutputStream outputStream = resp.getOutputStream();
//7. 将FileOutPutStream(例子)流写入到buffer缓冲区,使用OutPutStream将缓冲区的数据输出到客户端
while((len=fileInputStream.read(buffer))>0){
outputStream.write(buffer,0,len);
}
//8. 关流
fileInputStream.close();
outputStream.close();
3.验证码功能
//如何让浏览器5秒自动刷新一次
resp.setHeader("refresh","3");
//在内存中创建一个图片
BufferedImage bufferedImage = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics =(Graphics2D) bufferedImage.getGraphics();//一支笔
//设置图片的背景颜色
graphics.setColor(Color.white);
graphics.fillRect(0,0,80,20);
//给图片写数据
graphics.setColor(Color.blue);
graphics.setFont(new Font(null,Font.BOLD,20));
graphics.drawString(makeNum(),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());
makeNum方法
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999)+"";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 7-num.length(); i++) {
stringBuffer.append(0);
}
String s = stringBuffer.toString()+num;
return num;
}
4.实现重定向sendRedirect
一个web资源收到客户端请求后,他会通知客户端去访问另外一个web资源,这个过程叫重定向
重定向与转发的区别:
- 相同点:页面都会跳转
- 不同点: 请求转发时,url不会产生变化。重定向时,url地址栏会发生变化。
resp.sendRedirect("/response/success.jsp");//一般路径开头写上这个module在Tomcat注册的地址
HttpServletRequest
1.获取前端传递的参数
主要用req.getParameter
和req.getParameterValues
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println("================================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
System.out.println("================================");
req.getRequestDispatcher("/success.jsp").forward(req,resp);
Cookie,Session
会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器。这个过程可以称之为会话
有状态会话:有记录的会话。保存记录的技术:cookie或session
Cookie
- 客户端技术(响应,请求)
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- cookie大小有限制
- 300个cookie为浏览器上限
- cookie的值为中文时需要转码。转码用
URLEncoder.encode
,解码用URLDecode.decode()
- 删除cookie
- 不设置有效期,关闭浏览器自动失效
- 设置有效期为0
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();
if(cookies!=null){
out.write("上次访问的时间是:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if(cookie.getName().equals("lastLoginTime")){
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else{
out.write("第一次访问");
}
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
resp.addCookie(cookie);
Session(重点)
- 服务器技术,利用这个技术可以保存用户的会话信息。
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
- 用户登录之后,整个网站都可以访问
得到并创建
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = req.getSession();
//给session存东西
session.setAttribute("name",new Person("赵浩衡",18));
//获取session的ID
String id = session.getId();
//判断session是不是新创建的
if(session.isNew()){
resp.getWriter().write("session创建成功,ID:"+id);
}else{
resp.getWriter().write("session已经在服务器中存在了,ID:"+id);
}
得到并获取内容
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = req.getSession();
//得到session的内容
Person person = (Person) session.getAttribute("name");
resp.getWriter().write(person.toString());
得到并删除
HttpSession session = req.getSession();
session.removeAttribute("name");//移除某个键
session.invalidate();//手动删除整个session
<!--web.xml可以设置保存时间-->
<session-config>
<!--15分钟后session自动失效-->
<session-timeout>15</session-timeout>
</session-config>
JSP
java server pages
写jsp就像写HTML,但是HTML只给用户提供静态的数据,JSP页面可以镶入JAVA代码,为用户提供动态数据
jsp最后也会被转换为java类
JavaBean
实体类
特定写法:
- 必须有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM
ORM:对象关系映射
- 表----->类
- 字段--->属性
- 行记录---->对象
MVC三层架构
MVC:Model View Controller 模型/视图/控制器
Model
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(Dao)
View
- 展示数据
- 提供链接发起Servlet请求(a,form,img....)
Controller(Servlet)
- 接收用户的请求:(req:请求参数,Session信息)
- 交给业务层处理对应的代码
- 控制视图的跳转
Filter过滤器
用来过滤网站的数据
- 处理中文乱码
- 登录验证。。。。
写类继承Filter,注意这个Filter要是再javax.servlet下的那个Filter
//初始化:web服务器启动,就已经初始化了,随时等待过滤对象出现!
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//Chain:链
/*
1. 过滤中的所有代码,在过滤特定请求的时候都会执行
2. 必须要让过滤器继续通行
*/
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");
System.out.println("CharacterEncodingFilter执行前");
filterChain.doFilter(servletRequest,servletResponse);//让请求继续走,如果不写,程序到这里就会被拦截停止
System.out.println("CharacterEncodingFilter执行后");
}
//销毁:web服务器关闭的时候,过滤会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
web.xml中配置
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.zaughter.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是/servlet的任何请求,都会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
监听器
实现一个监听器的接口:
//创建Session监听,看你的一举一动
//一旦创建一个Session就会触发一次这个事件
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else{
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
//销毁Session监听
//一旦销毁一个Session就会触发一次这个事件
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else{
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
web.xml中配置
<listener>
<listener-class>com.zaughter.listener.OnlineCountListener</listener-class>
</listener>
JDBC复习
//配置信息
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-
String username="root";
String password="zhehe2004";
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL的对象:CRUD
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from users";
//5.执行查询SQL,返回一个结果集
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("name="+resultSet.getObject("name"));
System.out.println("password="+resultSet.getObject("password"));
System.out.println("birthday="+resultSet.getObject("birthday"));
}
//6.关闭连接,释放资源
resultSet.close();
statement.close();
connection.close();