JavaWeb-1
- 1、Tomacat
- 1.1、配置文件:server.xml,配置启动的端口号,默认8080
- 1.2、配置主机名称,默认localhost->127.0.0.1
- 1.3、发布一个网站
- 1.4、 网站项目结构
- 2、HTTP
- http请求:
- http响应:
- 3、Maven
- 4、Servlet
- 5、cookie-session
- 5.1、cookie
- 5.2、session
- 6、JavaBean
- 7、MVC三层架构
- 8、过滤器Filter
- 9、监听器listener
- 10、JDBC
- JDBC事务
1、Tomacat
1.1、配置文件:server.xml,配置启动的端口号,默认8080
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
1.2、配置主机名称,默认localhost->127.0.0.1
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
webapps是默认网站应用存放位置
1.3、发布一个网站
将写好的网站放入到webapps下的文件夹,文件夹就是项目名称
1.4、 网站项目结构
-webapps
-ROOT
-QIU
-WEB-INF
-class:java应用程序
-lib:依赖的包
-web.xml网站配置文件
-index.html默认的首页
2、HTTP
超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出。
http1.0:客户端与web服务器连接后只能获得一个资源
http1.1:可以获得多个
http请求:
请求 URL: https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/footer/aria-3006e33cce.png
请求方法: GET
状态代码: 200 (来自内存缓存)
远程地址: 112.16.240.33:443
引用站点策略: unsafe-url
- 请求行:包含请求方式(get、post、put等)、URL,Http协议版本
请求方式:
get:可携带参数少,大小有限制,在浏览器URL地址栏不安全
post:没有限制,不显示,安全 - 请求头:包含主机host,请求时间,客户端类型、指定客户端接收的数据格式,客户端支持的语言等
- 请求体:包含post方法提交的数据,也可以为空
http响应:
- 响应行:包含状态码、响应信息、Http协议版本;
① 报文协议及版本;
② 状态码及状态描述;
200 OK 处理成功!
303 See Other 我把你 redirect 到其它的页面,目标的 URL 通过响应报文头的 Location 告诉你。
304 Not Modified 告诉客户端,你请求的这个资源至你上次取得后,并没有更改,你直接用你本地的缓存吧,我很忙哦,你能不能少来烦我啊!
404 Not Found 你最不希望看到的,即找不到页面。如你在 google 上找到一个页面,点击这个链接返回 404,表示这个页面已经被网站删除了。
500 Internal Server Error 看到这个错误,你就应该查查服务端的日志了,肯定抛出了一堆异常。
- 响应头: 包含响应时间,响应数据的长度、类型、字符编码等;
- 响应体: 包含页面源码;
3、Maven
一个帮我们导入和配置jar包的java开发工具Maven核心思想:
约束我们的代码规范
<dependencies>
<!-- Servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
4、Servlet
用于开发动态Web,是一个API接口
servlet的本质,它是如何工作的?
Servlet有两个实现类:HttpServlet,GenericServlet,GenericServlet本身是一个抽象类,有一个抽象方法service,HttpServlet继承了GenericServlet,但是没有抽象方法,因为它不希望被实例化,子类必须重写doGet、doPost方法
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行doGet()方法");
PrintWriter writer=resp.getWriter();
writer.println("Hello Servlet ");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
- 3. Mapping映射问题
为什么创建了Servlet类之后,需要到配置文件(或部署描述符文件)web.xml中配置Servlet的映射,不能像JSP、HTML文件可以直接根据路径名?例如http://localhost:8080/helloworld/index.jsp进行访问,那么为什么.class文件(类的字节码文件)不能像http://localhost:8080/helloworld/WEB-INF/classes/com/company/app/HelloWorld.class这样去访问呢?
Oracle公司的Servlet规范定义了Java web应用的目录结构,自定义的Servlet类及其他类文件编译后必须放在项目根目录\WEB-INF\classes\,而WEB-INF目录下的文件浏览器无法直接访问,因此需要建立映射,使得浏览器可以通过该映射(本质是统一资源标识符)访问该类。
<!--浏览器请求路径/h1时Tomcat调用mi.qiu.servlet.HelloServlet并返回响应 -->
<!-- 注册servlet映射 -->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>mi.qiu.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet请求路径 -->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/h1</url-pattern>
</servlet-mapping>
- 4、ServletContext
ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表了这个Web应用,WEB应用中的所有Servlet对象之间可以通过ServletContext对象来实现通讯 - 共享信息
public class HelloServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("hello servlet1");
//获取servlet上下文
ServletContext servletContext=this.getServletContext();
String username="邱灏";
//将一个名为un值为username的数据保存到servletContext中
servletContext.setAttribute("un",username);
PrintWriter writer=resp.getWriter();
writer.println("Hello Servlet1 ");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
public class HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext=this.getServletContext();
//获取一个名为un的值
String username=(String) servletContext.getAttribute("un");
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer=resp.getWriter();
writer.println("名字:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
}
}
- 获取初始化参数
public class GetPara extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext=this.getServletContext();
String urL=servletContext.getInitParameter("url");
resp.setContentType("text/html;charset=utf-8");
PrintWriter printWriter=resp.getWriter();
printWriter.println("Mysql的初始化参数="+urL);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
- 转发请求,中继服务
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext=this.getServletContext();
//转发的请求路径
RequestDispatcher requestDispatcher=servletContext.getRequestDispatcher("/g2");
//调用forward()实现请求转发
requestDispatcher.forward(req,resp);
//这样获取了g2路径下的文件并转发执行
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
- 读取资源类文件
/* 读取资源类文件
*/
public class ServletDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context=this.getServletContext();
//以流的形式获取资源
InputStream inputStream=context.getResourceAsStream("/WEB-INF/classes/mi/qiu/servlet/db2.properties");
Properties prop=new Properties();
prop.load(inputStream);
String username=prop.getProperty("username");
String password=prop.getProperty("password");
resp.getWriter().println(username+":"+password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
- 5、HttpServletResponse
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对 象。我们要获取客户机提交过来的数据,只需要找request对象就行。要向客户机输出数据,只需要找response对象就行。 - Response下载文件
public class FileResponse extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取需要下载的文件的路径
// String path=this.getServletContext().getRealPath("/1.JPG");D:\Project\JavaWeb\servlet-01\response-1\src\main\resources
String path="D:\\Project\\JavaWeb\\servlet-01\\response-1\\src\\main\\resources\\头像6.JPG";
System.out.println("文件的下载路径是:"+path);
//2、文件名是,获取path最后一个/后面的内容
String fileName=path.substring(path.lastIndexOf("\\")+1);
//文件名转码
fileName = URLEncoder.encode(fileName, "UTF-8");
//3、设置使得浏览器支持下载我们需要的东西
resp.setHeader("Content-Disposition","attachment;filename="+fileName);
//4、获取文件输入流
FileInputStream fileIn=new FileInputStream(path);
//5、创建缓冲区
int len=0;
byte[] buffer=new byte[1024];
//6、获取输出流对象
ServletOutputStream servletOut=resp.getOutputStream();
//7、输出流写到缓冲区
while ((len=fileIn.read(buffer))>0){
servletOut.write(buffer,0,len);
}
servletOut.close();
fileIn.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
- Response验证码实现
- ServletResponse重定向
当客户端访问废弃的旧地址时,服务器返回新地址,然后客户端跳转到新地址
5、cookie-session
5.1、cookie
Cookie是服务端在HTTP响应中附带给浏览器的一个小文本文件,客户端首次访问一个Web服务器,服务器以键值对(key-value)形式生成cookie并通过响应发送给客户端(浏览器),然后浏览器会保存这些cookie;当浏览器再次登入,在发送HTTP请求时,浏览器将我们的cookie携带,把它们原样发送给服务器。服务端也会在HTTP响应中更新cookie。
//保存用户上一次访问的时间
public class CookieDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("GBK");
resp.setContentType("text/html;charset=GBK");
PrintWriter out=resp.getWriter();
Cookie[] cookies=req.getCookies();
if(cookies!=null){
out.write("上次访问时间是:");
for (Cookie cookie:cookies){
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 cookie=new Cookie("lastLoginTime",System.currentTimeMillis()+"");
//设置有效期1天,最多保留一天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
5.2、session
记录一系列状态
解释session:当浏览器访问服务器的时候,会在服务器端的内存里开辟一块内存,这块内存就叫做session,而这个内存是跟浏览器关联在一起的。这个浏览器指的是浏览器窗口,或者是浏览器的子窗口,意思就是,只允许当前这个session对应的浏览器访问,就算是在同一个机器上新启的浏览器也是无法访问的。而另外一个浏览器也需要记录session的话,就会再启一个属于自己的session。
当服务器需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 (session id)。Session与Cookie的区别在于Session是记录在服务端的,而Cookie是记录在客户端的。
public class SessionDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("GBK");
resp.setCharacterEncoding("GBK");
resp.setContentType("text/html;charset=GBK");
PrintWriter writer=resp.getWriter();
//得到session
HttpSession session=req.getSession();
session.setAttribute("person",new Person("邱灏",25));
String id=session.getId();
if(session.isNew()){
writer.write("会话创建成功,id是:"+id);
}else {
writer.write("会话 ["+id+"] 已经在服务器中");
}
//移除
session.removeAttribute("person");
//自动注销
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
public class SessionDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("GBK");
resp.setCharacterEncoding("GBK");
resp.setContentType("text/html;charset=GBK");
PrintWriter writer = resp.getWriter();
//得到session
HttpSession session = req.getSession();
Person person= (Person) session.getAttribute("person");
System.out.println(person.toString());
writer.write("person:"+person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
6、JavaBean
一个实体类
- 必须有一个无参构造
- 属性必须私有化
一般用来和数据库字段做映射:
表-类;字段-属性;每一行数据-一个对象
7、MVC三层架构
模型-视图-控制器
- 早期结构:控制层直接操作数据库
弊端:程序臃肿,维护困难
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为):Value Object(数据Dao) 和 服务层(行为Service)
View(视图):负责进行模型的展示,一般就是我们见到的用户界面
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示
8、过滤器Filter
- 过滤网站数据,作格式转换;实现权限拦截等
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setCharacterEncoding("utf-8");
resp.getWriter().write("晚上好!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
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("CharacterEncoding执行前");
//经过过滤器之后,请求和响应必须继续转交传递,否则程序到此截至
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("CharacterEncoding执行后");
}
@Override
//服务器关闭时执行
public void destroy() {
System.out.println("CharacterEncoding销毁");
}
}
- 配置过滤器映射
<filter>
<filter-name>filter2</filter-name>
<filter-class>mi.qiu.filter.FilterDemo1</filter-class>
</filter>
<!--只要是s1/下面的所有请求/响应都会经过过滤器-->
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/s1/*</url-pattern>
</filter-mapping>
9、监听器listener
1.是一个实现了特定接口的Java类;
2.用来监听另一个 Java类的方法调用或者属性的改变;
3.当被监听对象发生了上述事件后,监听器某个方法将会立即被执行。
public class OnlineCountListener implements HttpSessionListener {
//每创建一个Session就会触发一次sessionCreated()方法!
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
//每销毁一个Session就会触发一次sessionDestroyed()方法!
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
/*
Session销毁:
1. 手动销毁 getSession().invalidate();
2. 自动销毁
*/
}
<!--注册监听器-->
<listener>
<listener-class>mi.qiu.listener.OnlineCountListener</listener-class>
</listener>
10、JDBC
public class JdbcDemo2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username="root";
String password="123456";
Class.forName("com.mysql.jdbc.Driver");
Connection connection= DriverManager.getConnection(url,username,password);
String sql2="insert into users(id,name,password,email,birthday)values (?,?,?,?,?)";
//预编译
PreparedStatement prepareStatement= connection.prepareStatement(sql2);
prepareStatement.setInt(1,6);
prepareStatement.setString(2,"Jerry");
prepareStatement.setString(3,"7756");
prepareStatement.setString(4,"777@163.com");
prepareStatement.setDate(5,new Date(new java.util.Date().getTime()));
//执行SQL
int i=prepareStatement.executeUpdate();
if(i>0){
System.out.println("插入成功");
}
prepareStatement.close();
connection.close();
}
}
JDBC事务
//更改数据库的默认字符集为utf8,更改表的字符集为utf8
alter database jdbcstudy default character set utf8 collate utf8_general_ci;
alter table jdbcstudy.users convert to character set utf8 collate utf8_general_ci;
ACID原则