JavaWeb概述

什么是javaweb?

  • JavaWeb是指,通过java语言编写可以通过浏览器访问的程序的总称,叫做javaweb。
  • javaweb是基于请求和响应来开发的

什么是请求?

  • 请求是指客户端给服务器发送数据,叫做Request

什么是响应?

  • 响应实质服务器给客户端传回数据,叫做响应Response

请求和响应的关系?

  • 请求和响应是成对出现的,有请求就有响应

Web资源的分类

  • web资源按照实现的技术和呈现的效果不同,分为静态资源和动态资源
  • 静态资源:html,css,js,txt,mp4,jpg图片等
  • 动态资源:jsp页面,servlet程序

Servlet技术

1.什么是Servlet

Servlet是一种运行在服务器端(一般指的是 Web 服务器)的 Java 应用程序,可以生成动态的 Web 页面,它是属于客户与服务器响应的中间层。因此,可以说,JSP就是Servlet。两者可以实现同样的页面效果,不过,编写 JSP 和编写 Servlet 相比,前者成本低得多

  • Servlet是JavaEE规范之一,规范就是接口
  • Servlet就是JavaWeb的三大组件之一:Servlet程序,Filter过滤器,Listener监听器
  • Servlet就是运行在服务器上的一个java小程序,它可以接收客户端发过来的请求,并响应数据给客户端

2.Servlet实现

  • 编写一个类去实现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
25
26
27
28
29
30
31
32
33
package com.me.servlet;

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {

}

@Override
public ServletConfig getServletConfig() {
return null;
}
//Service方法是专门处理请求和响应的
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet 被访问了!");
}

@Override
public String getServletInfo() {
return null;
}

@Override
public void destroy() {

}

}

  • 到web.xml去配置servlet程序的访问地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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">

<servlet>
<!--name 给servlet程序取别名-->
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.me.servlet.HelloServlet</servlet-class>
<!--class是servlet程序的全类名-->
</servlet>

<servlet-mapping>
<!--name 告诉服务器我要调用哪个servlet程序-->
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
<!--url 自定义访问地址-->
<!--/ 表示为 http://ip:port/工程路径-->
</servlet-mapping>


</web-app>

或者使用@WebServlet注解

  • 工程地址

  • 访问配置的地址

qq0UeO.png

  • 显示被访问了

qq0DfA.png

3.继承Httpservlet实现Servlet程序

  • 编写一个类去继承HttpServlet类

  • 根据业务需求重写doGet和doPost方法

  • 到web.xml中配置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
package com.me.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet2 extends HttpServlet {


@Override
//在Get请求中调用
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("调用了doGet方法");
}

@Override
//在Post请求中调用
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("调用了doPost方法");
}
}

  • IDEA快速生成Servlet
    • 自动继承HttpServlet
    • 自动重写get和post
    • 自动配置到xml的servlet
    • 我们只需要配置servletmap和写get和post方法

请求与与响应

HttpServletRequest

  • 每次有请求传入Tomcat服务器,tomcat服务器就会把请求过来的http协议信息解析好封装到Requst对象内之后传递到service方法中的doget和dopost中给我们使用

  • 常用方法

    • getParameter()传入key返回值
    • getParameterValues() 传入key 返回值 数组

请求转发

请求重定向

1
resp.sendRedirect("重定向地址");

HttpServletResponse

  • 与Request类似,Response表示所有响应信息,我们如果需要设置返回给客户端的信息可以通过HttpServletResponse设置相应的信息返回
  • 两个输出流
    • 字节流 常用于下载,传输二进制数据
    • 字符流 返回字符串
    • 两种流只能使用一个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ResponseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
resp.setCharacterEncoding("UTF-8");
writer.write("世界你好");

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}

4.ServletConfig类

  • 是Servlet程序的配置信息类
  • 作用
    1. 可以获取Servlet程序的别名Servlet-name的值
    2. 获取初始化参数 Init-param
    3. 获取ServletContext对象

5.ServletContext

1.介绍

ServletContext官方叫Servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。

  • ServletContext对象是一个域对象
  • 域对象是指可以像map一样存取数据的对象,叫做域对象,域是指存取数据的操作范围
Map put() get() remove()
域对象 setAttribute() getAttribute() removeAttribute()

img

2.具体实现

  • 创建一个放数据的类
1
2
3
4
5
6
7
8
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String name="King";
context.setAttribute("name",name);

}
  • 创建一个读取它的类
1
2
3
4
5
6
7
8
9
10
11
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String name= (String) context.getAttribute("name");


resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字"+name);
}
  • 配置.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>getname</servlet-name>
<servlet-class>GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getname</servlet-name>
<url-pattern>/getname</url-pattern>
</servlet-mapping>

3.测试结果

  • 没有访问/hello时访问getname

  • 访问/hello后访问getname

6.servlet生命周期

1.当客户端向 Web 服务器提出第一次 Servlet 请求时,Web 服务器会实例化一个 Servlet,并且调用 init()方法;如果 Web 服务器中已经存在了一个 Servlet 实例,将直接使用此实例;

2.然后调用 service()方法,service()方法将根据客户端的请求方式来决定调用对应的 doXXX()方法;

3.当 Servlet 从 Web 服务器中消亡时,Web 服务器将会调用 Servlet的destroy()方法

Listener监听器

1.什么是Listener监听器

  • Listener 监听器它是Javaweb的三大组件之一。JavaWeb的三大组件分别是:servlet程序、Fiter过滤器、Listener监听器。
  • Listener它是JavaEE的规范,就是接口
  • 监听器的作用是,监听某种事物的变化。然后通过回调函数,反馈给客户(程序)去做一些相应的处理。

Filter过滤器

1.什么是Fliter过滤器

  • Filter过滤器它是JavaWeb的三大组件之一。三大组件分是:Servlet程序、Listener监听器、Filter过滤器。

  • Filter过滤器它是JavaEE的规范。也就是接口

  • Filter过滤器它的作用是:拦截请求,过滤响应。

  • 常见的拦截请求

    • 权限检查
    • 日记操作
    • 事务管理
    • ……等等

Filter的实现

  1. 写一个类实现Filter接口

    • 初始化方法:表示的是过滤器初始化时的动作。 public void init(FilterConfig config) ;
    • 消亡方法:表示的是过滤器消亡时候的动作。 public void destroy() ;
    • 过滤函数:表示的是过滤器过滤时的动作。 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) ;
  2. 在web.xml配置Filter

    • 与Servlet类似
    1
    2
    3
    4
    5
    6
    7
    8
    <filter>
    <filter-name>myfilter</filter-name>
    <filter-class>filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>myfilter</filter-name>
    <url-pattern>/</url-pattern>
    </filter-mapping>

或者使用@WebFilter注解

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
package com.atguigu.web;

import com.atguigu.pojo.User;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import java.io.IOException;

public class DoFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest= (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession();
Object user=session.getAttribute("name");
//获取session,检查是否登录

if (user==null){
//未登录进行拦截
servletRequest.getRequestDispatcher("/pages/user/login.html").forward(servletRequest, servletResponse);

}
else {
//登录后继续执行()
filterChain.doFilter(servletRequest, servletResponse);
}

}
}

  • 配置xml
1
2
3
4
5
6
7
<filter>
<filter-name>DoFilter</filter-name>
<filter-class>com.atguigu.web.DoFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>DoFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
  • 在login页面中设置session
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
package com.atguigu.web;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
private UserService userService=new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//2.调用
User loginUser = userService.login(new User(null, username, password, null));
if(loginUser==null){
System.out.println("登录失败");
req.getRequestDispatcher("/pages/user/login.html").forward(req, resp);
//登录失败
}
else {
req.getSession().setAttribute("name", username);
req.getRequestDispatcher("/pages/user/login_success.html").forward(req, resp);
//登录成功
}

}
}

  • 效果是,没有登录前无法访问admin目录下后的文件
  • 登录后即可访问

JavaEE三层架构

分层的目的就是为了解耦,解耦就是为了降低代码的耦合度,方便后期的维护

1.Web层/视图展现层

  • 获取请求的参数,封装成为Bean对象
  • 调用Service层处理业务
  • 回传,响应数据给客户端
    • 请求重定向
    • 请求转发

2.Service 业务层

  • 处理业务逻辑
  • 调用持久层保存到数据库

3.DAO 持久层

  • 只负责跟数据库交互
  • CRUD
    • Create 增
    • Read 查
    • Update 改
    • Delete 删

Cookie与Session

1.什么是Cookie与Session

  • Cookie

Cookie是保存在客户端的纯文本文件。比如txt文件。所谓的客户端就是我们自己的本地电脑。当我们使用自己的电脑通过浏览器进行访问网页的时候,服务器就会生成一个证书并返回给我的浏览器并写入我们的本地电脑。这个证书就是cookie。通俗点讲就是我们在浏览网页的时候,服务器给的我们一个身份令牌,而且这个身份是唯一的,没有人和你一样,你拥有了这个身份,服务器才能认识你。但是呢Cookie具有不可跨域名性,就是假如我们现在在访问百度,那么我们不会带上谷歌的cookie。

  • Session

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。每个用户访问服务器都会建立一个session,那服务器是怎么标识用户的唯一身份呢?事实上,用户与服务器建立连接的同时,服务器会自动为其分配一个SessionId。

  • Cookie和Session的关系

Session的使用需要Cookie的支持,因为单独的Session还是无法知道当前访问服务器的是否是同一个客户端,它要根据存储在Cookie中的JSESSIONID来进行判断[这个Cookie是客户端自动创建的],如果客户端关闭了Cookie,那么Session是没有什么效果的。这个时候,需要使用URL重写的方式,将JSESSIONID直接放置在URL中,访问服务器的时候可以直接进行解析。

2.Cookie与Session的实现

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
//Cookie
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器告诉你上次来的时间
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
//设置编码
PrintWriter out = resp.getWriter();
//1.通过请求获取cookie
Cookie[] cookies = req.getCookies();
//2.判断cookie是否存在
if(cookies!=null){
out.write("您上一次访问的时间为:");
for (int i = 0; i < cookies.length; i++) {
if(cookies[i].getName().equals("LastLoginTime")){
long timeStamp = Long.parseLong(cookies[i].getValue());
Date date=new Date(timeStamp);
out.print(date.toLocaleString());
}
}
}
else{
out.write("这是你第一次访问本站");
}
//3.服务器给一个cookie,或更新cookie
Cookie cookie=new Cookie("LastLoginTime",String.valueOf(System.currentTimeMillis()));
//cookie值存中文如果出现乱码可以使用urlEncoding进行编码
//Cookie cookie1=new Cookie("name", URLEncoder.encode("中文试一试?","utf-8"));
cookie.setMaxAge(20*60*60);
resp.addCookie(cookie);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Session
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
//1.获得session
HttpSession session = req.getSession();
//2.向session中存东西
session.setAttribute("name","未来");
if(session.isNew()){
resp.getWriter().write("session创建成功为"+session.getId());
}
else{
resp.getWriter().write("session在服务器中存在了,为"+session.getId());
}
}

3.总结

1,session 在服务器端,cookie 在客户端(浏览器)
2,session 默认被存在在服务器的一个文件里(不是内存)
3,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)
4,session 可以放在 文件、数据库、或内存中都可以。
5,用户验证这种场合一般会用 session

文件传输

文件上传

1.为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

2.为防止文件覆盖的现象发生,要为上传文件产生—个唯一的文件名

3.要限制上传文件的最大值。

4.可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

  • 需求:
  1. 要有一个form标签,method=post
  2. form标签的enctype必须为 multipart/form-data
  3. 在标签中使用input type=file添加上传的文件
  4. 编写服务器接收,处理上传的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/SggWeb/uploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"/><br>
头像:<input type="file" name="photo"> <br>
<input type="submit" value="上传">
</form>
</body>
</html>

1.导包

  • commons-io

Commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率,Commons-io提供了很多有关IO操作的类

  • commons-fileupload

commons-fileupload为apache出品的文件上传组件,用来接收浏览器上传的组件,该组件有多个类组成

2.文件上传

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
package com.me.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.判断上传的数据是否为多段数据(只有多段的数据才是文件上传)
if(ServletFileUpload.isMultipartContent(req)){
//创建FileItemFactory工厂实现类
FileItemFactory fileItemFactory=new DiskFileItemFactory();
//创建用于解析上传数据的解析工具类servletFileUpload
ServletFileUpload servletFileUpload=new ServletFileUpload(fileItemFactory);

//解析上传的数据,得到每个表单项FileItem

try {
List<FileItem> list = servletFileUpload.parseRequest(req);

for (FileItem fileItem : list) {
//循环判断每一个表单项是普通类型还是上传的类型
if(fileItem.isFormField()){
//普通表单
System.out.println("表单的name"+fileItem.getFieldName());
System.out.println("表单的value"+fileItem.getString("UTF-8"));
}
else {
System.out.println("表单的name"+fileItem.getFieldName());
System.out.println("上传的文件名"+fileItem.getName());

fileItem.write(new File("d:\\"+fileItem.getName()));
//文件表单
}
}
} catch (Exception e) {
e.printStackTrace();
}
}


}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}

文件下载

1.实现代码

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
package com.me.servlet;

import org.apache.commons.io.IOUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取文件名
String filename="11.png";
//2.获取要下载的文件内容(通过ServletContext对象)
ServletContext servletContext = getServletContext();
//在服务器 斜杠被服务器解析为工程地址http://ip:port/工程名/ 映射到web目录下

//3.告诉客户端回传的类型
String mimeType = servletContext.getMimeType("/file/" + filename);
System.out.println("下载的文件类型为"+mimeType);
resp.setContentType(mimeType);

resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"UTF-8"));
//4.把下载内传给客户端
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + filename);
//之前使用字节数值实现,现在可以使用io包实现,直接用

//获取响应的输出流
OutputStream outputStream=resp.getOutputStream();
IOUtils.copy(resourceAsStream, outputStream);
}
}

  • 不使用IO包,实现下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取文件位置
String filePath="D:\\JavaSE\\JavaWeb\\JavaWeb\\WebDownload\\src\\main\\resources\\奥日.jpg";
//2.获取文件名称
String fileName=filePath.substring(filePath.lastIndexOf("\\")+1);
//3.设置响应头,支持下载文件
//response.setHeader("Content-Disposition", "attachment;filename="+fileName)//中文名使用URL/encode防止乱码
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
//4.获取文件下载输入流
FileInputStream in =new FileInputStream(filePath);
//5.创建缓冲区
int len=0;
byte[] buffer=new byte[1024];
//6.获取对象
ServletOutputStream out = resp.getOutputStream();
//7.写入数据
while ((len=in.read(buffer))!=-1){
out.write(buffer,0,len);
}
out.close();
in.close();
}

JSON

1.什么是JSON

JSON (JavaScr ipt Object Notaticn)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式,而且很多语言都提供了对json的支持(包括C,C++,C#,Java,JavaScript,Perl,Python等)。这样就使得JSON成为理想的数据交换。

  • 轻量级指的是跟xml做比较。

  • 数据交换指的是客户端和服务器之间业务数据的传递格式。

定义:

  • json是由键值对组成。
  • 由花括号包围。
  • 每个键由引号引起来。
  • 键和值之间使用冒号进行分隔。
  • 多组键值对之间进行逗号进行分隔。
  • json就是个对象

2. JSON在JS中的使用

1
2
3
4
5
6
7
8
9
var jsonOBJ{
"key1":"string",
"key2":123,
"key3":[1,"str",false],
"key4":{
"key5":"445"
"key":1231
}
}
  • 获取值
1
jsonOBJ.key

json对象和json字符串

  • 对象和字符串是json的两种存在方式
    • JSON.stringify() 把json对象转换成为 json字符串
    • JSON.parse() 把json字符串转换成为 json对象

3.JSON在JAVA中的使用

  • 导入gson.jar包
  • 或者fastjson

Google Gson是一个简单的基于Java的库,用于将Java对象序列化为JSON,反之亦然。 它是由Google开发的一个开源库。

  • JSON与JAVABean对象转换
1
2
3
4
5
6
7
8
9
10
11
12
public static void test1(){
User user1=new User(1, "hah", "100234s");

Gson gson =new Gson();
//javaBean和json的互转
String userJson = gson.toJson(user1);
System.out.println(userJson);

User userString = gson.fromJson(userJson, User.class);
System.out.println(userString.toString());

}
  • JSON与List转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void test2(){
Gson gson=new Gson();
List<User> list=new ArrayList<>();
list.add(new User(1, "hah", "100234s"));
list.add(new User(2, "hah", "100234s"));
list.add(new User(3, "hah", "100234s"));
list.add(new User(4, "hah", "100234s"));

String userListString = gson.toJson(list);
System.out.println(userListString);

List<User> list2= gson.fromJson(userListString, new UserListType().getType());
System.out.println(list2.get(0));

}
  • JSON与Map相互转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void test3(){
Gson gson=new Gson();
Map<Integer,User> map1=new HashMap<>();

map1.put(4,new User(1, "hah", "100234s"));
map1.put(5,new User(2, "hah", "100234s"));
map1.put(6,new User(3, "hah", "100234s"));
map1.put(7,new User(4, "hah", "100234s"));

String userMapList = gson.toJson(map1);
System.out.println(userMapList);

Map<Integer,User> map2=gson.fromJson(userMapList, new UserMapType().getType());
System.out.println(map2.get(4));
}
  • List和Map 都需要写一个类去继承TypeToken并且使用相应泛型,否则无法转换成真正的Bean对象,而是map对象

AJAX

1.什么是AJAX

  • AJAX即“Asynchronous Javascript And XML””(异步JavaScript 和XML),是指一种创建交互式网页应用的网页开发技术。
  • ajax是一种浏览器通过js异步发起请求。局部更新页面的技术。

2.AJAX使用

  • 前端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function ajaxRequest() {
//1.创建xml对象
var xmlHttpRequest=new XMLHttpRequest();
//2.设置请求参数
xmlHttpRequest.open("get","http://ip:port//servlet",true);//true表示异步
//3.发送请求
xmlHttpRequest.send();
//4、在send方法前绑定onreadystatechange事件,处理请求完成后的操作。
if(xmlHttpRequest.readyState==4&&xmlHttpRequest.status==200){
//把响应回来的数据转为json对象显示在页面上
var obj=JSON.parse(xmlHttpRequest.responseText);
document.getElementById().innerText="编号"+obj.id+"姓名"+obj.name;
}
}
  • 后端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.me.servlet;

import com.google.gson.Gson;
import com.me.pojo.User;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JavaScriptAjax extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ajaxa请求过来了");
User user=new User(12, "66", "6854");
Gson gson=new Gson();
String personJson = gson.toJson(user);

resp.getWriter().write(personJson);

}
}

3.JQuery的AJAX

  • $ajax
    • url 表示请求的地址
    • type 表示请求的类型get或者post
    • data 表示发送给服务器的数据
      • 格式有两种
      • 1.name=value&name=value
      • 2.{key=value}
    • success 请求成功,响应的回调函数
    • dataType 响应的数据类型
1
2
3
4
5
6
7
8
9
10
$.ajax({
url:"http://ip:port//servlet",//地址
data:"action=JQueryAjax",//servlet的哪个函数
type:"GET",//类型
success:function (data//data就是传回来的对象
) {
$("#msg").html("编号"+data.id+"姓名"+data.name);
}
dataType:"json" //"表示响应的类型",也就是data 的类型
})
  • $.get和&.post是ajax的方法,少了type

    • url
    • data
    • callback
    • type
  • $getJson

    • 请求是get
    • 返回是json
    • url
    • data
    • callback
  • serialize()

serialize()可以把表单中所有表单项的内容都获取到,并以name=value&name=value的形式进行拼接。

1
$("#form").serialize

书城项目

1.环境搭建

在IDEA中建好相应的包,导入相关的页面资源

[LVf3xP.png

2.创建需要的数据库和表

  • id
  • 用户名
  • 密码
  • 邮箱
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE DATABASE `book`
USE `book`
CREATE TABLE t_user(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(30) NOT NULL UNIQUE,
`password` VARCHAR(32) NOT NULL,
`email` VARCHAR(200)
);

INSERT INTO t_user(`username`,`password`,`email`)
VALUES('admin','admin','admin@guigu.com');

SELECT * FROM t_user;

3.创建数据库表对于的JavaBean对象

  • 数据库的数据是可以为null的,所以基本数据类型要是用包装类进行==null比较
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
package com.atguigu.pojo;

public class User {
private Integer id;
private String username;
private String password;
private String email;

public User() {
}

public User(Integer id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}

}

4.编写工具类jdbcUtils

1.导入相关依赖的包

  • druid

Druid是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。Druid是阿里巴巴开发的号称为监控而生的数据库连接池!

  • mysql-connector

mysql-connector-java 是MySQL提供的JDBC驱动包,用JDBC连接MySQL数据库时必须使用该jar包,它的主要用途有三个:

  1. 与数据库建立连接
  2. 发送 SQL 语句
  3. 处理结果
  • junit

junit是一个Java语言的单元测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例

  • hamcrest-core

Hamcrest是一个书写匹配器对象时允许直接定义匹配规则的框架.有大量的匹配器是侵入式的,例如UI验证或者数据过滤,但是匹配对象在书写灵活的测试是最常用.使用Hamcrest进行单元测试.

2.编写jdbc配置文件

1
2
3
4
5
6
username=root
password=123456
url=jdbc:mysql://localhost:3306/book?characterEncoding=utf8&useSSL=false
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10

3.编写JdbcUtils

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
package com.atguigu.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtils {
private static DruidDataSource dataSource;
//静态代码块先加载
static {

try {
Properties properties =new Properties();
//读取jdbc.properties属性配置文件
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//从流中加载数据
properties.load(inputStream);
//创建数据库连接池
dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}

}


/**
* 获取数据库连接
* @return 如果返回null,说明连接失败
*/
public static Connection getConnection(){
Connection conn=null;

try {
conn=dataSource.getConnection();
} catch (Exception throwables) {
throwables.printStackTrace();
}
return conn;
}

/**
* 关闭连接,放回数据库连接池
* @param conn
*/
public static void closeConnection(Connection conn){
if (conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

4.编写JdbcUtils测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.atguigu.test;

import com.atguigu.utils.JdbcUtils;
import org.junit.Test;

import java.sql.Connection;

public class JdbcUtilsTest {
@Test
public void jdbcUtilsTest(){
//使用完后一定要关闭连接!!!
for (int i = 0; i < 100; i++) {
Connection connection = JdbcUtils.getConnection();
System.out.println(connection);
JdbcUtils.closeConnection(connection);
}
}
}

5.编写BaseDao

  • 使用BaseDao主要的作用是减少冗余代码,在对Dao的操作中CRUD可以说是最普通最常见的操作了,基本上面对不同的数据表都会有类似的CRUD操作,BaseDao的思想就是把这些冗余的操作抽取出来,作为一个抽象出来的类,使用这个BaseDao可以使我们的代码更优雅

1.导入相关的包

Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package com.atguigu.dao.impl;

import com.atguigu.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

public abstract class BaseDao {

private QueryRunner queryRunner=new QueryRunner();

/**
* update 用来执行增删改语句
* @return 返回-1表示失败,其他表示影响的行数
*/
public int update(String sql,Object... args){
Connection connection= JdbcUtils.getConnection();
try {
return queryRunner.update(connection,sql,args);
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.closeConnection(connection);
}
//关闭连接!!!
return -1;
}

/**
* 返回一个javaBean的语句
* @param type 返回的对象类型
* @param sql 执行的sql语句
* @param args 传入的参数
* @param <T> 泛型
* @return
*/
public <T> T queryForOne(Class<T>type,String sql,Object... args){
Connection connection=JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.closeConnection(connection);
}
return null;
}

/**
* 返回一个多个javaBean的语句
* @param type 返回的对象类型
* @param sql 执行的sql语句
* @param args 传入的参数
* @param <T> 泛型
* @return
*/
public <T> List<T> queryForList(Class<T>type,String sql,Object... args){
Connection connection=JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanListHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.closeConnection(connection);
}
return null;
}

/**
* 执行返回查询一行一列的情况
* @param sql
* @param args
* @return
*/
public Object queryForSingleValue(String sql,Object... args){
Connection connection=JdbcUtils.getConnection();

try {
return queryRunner.query(connection,sql,new ScalarHandler(),args);
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.closeConnection(connection);
}
return null;
}
}

6.编写UserDao和测试

1.编写UserDao接口

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
package com.atguigu.dao;

import com.atguigu.pojo.User;

public interface UserDao {

/**
* 通过用户名查询用户信息
* @param username 用户名
* @return 如果返回null,说明没有这个用户
*/
User queryUerByUsername(String username);

/**
* 根据用户名和密码查询用户
* @param username
* @param password
* @return 如果返回null,说明用户名或者密码错误
*/
User queryUerByUsernameAndPassword(String username,String password);
/**
* 保存用户信息到数据库
* @param user
* @return
*/
int saveUser(User user);


}

2.编写UserDao实现类

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
package com.atguigu.dao.impl;

import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;

public class UserDaoImpl extends BaseDao implements UserDao {
//继承BaseDao,并且实现UserDao接口
@Override
public User queryUerByUsername(String username) {
String sql="select `id`,`username`,`password`,`email` from t_user where username=?";
return queryForOne(User.class,sql,username);
}

@Override
public User queryUerByUsernameAndPassword(String username, String password) {
String sql="select `id`,`username`,`password`,`email` from t_user where username=? and password=?";
return queryForOne(User.class,sql,username,password);
}

@Override
public int saveUser(User user) {
String sql="INSERT INTO t_user(`username`,`password`,`email`) VALUES(?,?,?)";
return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
}
}

3.编写UserDao测试类

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
package com.atguigu.test;

import com.atguigu.dao.UserDao;
import com.atguigu.dao.impl.UserDaoImpl;
import com.atguigu.pojo.User;
import org.junit.Test;

import static org.junit.Assert.*;

public class UserDaoTest {
UserDao userDao=new UserDaoImpl();
@Test
public void queryUerByUsername() {
if(userDao.queryUerByUsername("admin")==null){
System.out.println("用户名可用!");
}
else {
System.out.println("用户名已存在!");
}
}

@Test
public void queryUerByUsernameAndPassword() {
if(userDao.queryUerByUsernameAndPassword("admin","admin")==null){
System.out.println("用户名或密码错误!");
}
else {
System.out.println("登录成功!");
}
}

@Test
public void saveUser() {
User user=new User(null,"hello","123456","1245@qq.com");
System.out.println(userDao.saveUser(user));
}
}

7.编写UserService和测试

1.UserService接口

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
package com.atguigu.service;

import com.atguigu.pojo.User;

public interface UserService {

/**
* 注册用户
* @param user
*/

public void registerUser(User user);

/**
* 用户登录
* @param user
* @return
*/
public User login(User user);

/**
* 检测用户名是否存在
* @param username
* @return 返回true表示用户名已经存在,返回false说明用户名可用
*/
public boolean existsUsername(String username);


}

2.UserServiceImpl

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
package com.atguigu.service.impl;

import com.atguigu.dao.UserDao;
import com.atguigu.dao.impl.UserDaoImpl;
import com.atguigu.pojo.User;
import com.atguigu.service.UserService;

public class UserServiceImpl implements UserService {
private UserDao userDao=new UserDaoImpl();

@Override
public void registerUser(User user) {
userDao.saveUser(user);
}

@Override
public User login(User user) {
return userDao.queryUerByUsernameAndPassword(user.getUsername(),user.getPassword());
}

@Override
public boolean existsUsername(String username) {
if(userDao.queryUerByUsername(username)==null){
return false;
}
return true;
}
}

3.UserService测试

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
package com.atguigu.test;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import org.junit.Test;

import static org.junit.Assert.*;

public class UserServiceTest {
UserService userService=new UserServiceImpl();
@Test
public void registerUser() {
userService.registerUser(new User(null,"bbj","666","1265@qq.com"));
userService.registerUser(new User(null,"asdbbj","666","124465@qq.com"));
}

@Test
public void login() {
System.out.println(userService.login(new User(null,"wzg","hhh","guug@qq.com")));
}

@Test
public void existsUsername() {
if(userService.existsUsername("bbj")){
System.out.println("用户名已存在");
}
else {
System.out.println("用户名可用");
}
}
}

8.实现注册登录功能

  • 注册
  1. 获取请求的参数

  2. 检查验证码是否正确

    • 正确
    1. 检查用户名是否存在
      • 存在则跳回注册页面
      • 不存在则保存到数据库并跳转到注册成功
    • 不正确
      • 跳转到注册页面
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
package com.atguigu.web;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RegisterServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
//2.验证码为=abcde
if ("abcde".equalsIgnoreCase(code)) {
//验证成功
if (userService.existsUsername(username)) {
System.out.println("用户名" + username + "已经存在");
req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp);
//存在,不可以
} else {
userService.registerUser(new User(null, username, password, email));
req.getRequestDispatcher("/pages/user/regist_success.html").forward(req, resp);
//可以
}
} else {
//验证失败
System.out.println("验证码错误");
req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp);
}

}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}

  • 登录
  1. 获取请求的参数
  2. 调用xxxService处理业务
  3. 根据login()判断是否成功
    • 成功,跳转到成功页面
    • 失败,回到登录页面
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
package com.atguigu.web;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
private UserService userService=new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//2.调用
User loginUser = userService.login(new User(null, username, password, null));
if(loginUser==null){
System.out.println("登录失败");
req.getRequestDispatcher("/pages/user/login.html").forward(req, resp);
//登录失败
}
else {
req.getRequestDispatcher("/pages/user/login_success.html").forward(req, resp);
//登录成功
}

}
}

9.验证码功能实现

谷歌kaptcha验证码

1.导入kaptcha包

Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项如:

  • 验证码的字体

  • 验证码字体的大小

  • 验证码字体的字体颜色

  • 验证码内容的范围(数字,字母,中文汉字!)

  • 验证码图片的大小,边框,边框粗细,边框颜色

  • 验证码的干扰线

  • 验证码的样式(鱼眼样式、3D、普通模糊)

kapacha依赖包

Maven Repository: com.jhlabs » filters » 2.0.235 (mvnrepository.com)

2.直接配置Servlet

  • 官方已经写好了类,直接配置
1
2
3
4
5
6
7
8
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
  • 访问/kapatcha.jpg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("调用了doGet方法");
//获取sessoin中的验证码- 从服务器中获取
String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
//马上删除,防止表单重复提交
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);

//从客户端获取验证码
String code = req.getParameter("code");

if(token!=null&&token.equalsIgnoreCase(code)){
System.out.println("保存到数据库");
}else {
System.out.println("请不要重复提交表单");
}
}

i18国际化

1.什么是i18n国际化

  • 国际化(Internationalization)指的是同一个网站可以支持多种不同的语言,以方便不同国家,不同语种的用户访问。关于国际化我们想到的最简单的方案就是为不同的国家创建不同的网站.
  • 苹果公司这种方案并不适合全部公司,而我们希望相同的一个网站,而不同人访问的时候可以根据用户所在的区域显示不同的语言文字,而网站的布局样式等不发生改变。
  • 于是就有了我们说的国际化,国际化总的来说就是同一个网站不同国家的人来访问可以显示出不同的语言。但实际上这
    种需求并不强烈,一般真的有国际化需求的公司,主流采用的依然是苹果公司的那种方案,为不同的国家创建不同的页面。
  • 国际化的英文Internationalization,但是由于拼写过长,老外想了一个简单的写法叫做l18N,代表的是Internationalization
    这个单词,以开头,以N结尾,而中间是18个字母,所以简写为18N。以后我们说18N和国际化是一个意思。

2.国际化要求