Java Web教程——检视阅读

参考

java web入门——概念理解、名词解释

Java Web 教程——w3school 蓝本

JavaWeb学习总结(一)——JavaWeb开发入门

小猴子monkey1024的Java教程

基本学习点:

HTML

CSS

JS

JQuery

XML

Tomcat

Servlet

略读

Java的Web框架虽然各不相同,但基本也都是遵循特定的路数的:使用Servlet或者Filter拦截请求,使用MVC的思想设计架构,使用约定,XML或 Annotation实现配置,运用Java面向对象的特点,面向对象实现请求和响应的流程,支持Jsp,Freemarker,Velocity等视图。

基本上所有的java web应用都是基于Servlet规范,哪些常用框架如Struts,Spring MVC只是对Servlet规范的封装而已。

web.xml节点加载顺序:

可以肯定的是,节点的加载顺序与它们在 web.xml 文件中的先后顺序无关。即不会因为 filter 写在 listener 的前面而会先加载 filter。 加载顺序是:[context-param -> listener -> filter -> servlet] ,而同类型节点之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。

Java Web简介

Java Web,是用Java技术来解决相关web互联网领域的技术总和。

理解HTTP

HTTP是基于TCP协议的。TCP负责数据传输,而HTTP只是规范了TCP传输的数据的格式。

HTTP服务的底层实现就是socket编程。

示例:基于socket编写一个简单的HTTP server。

这是一个实现HTTP 1.0的服务器,对于所有的HTTP请求,会把HTTP请求头响应回去。 这个程序说明了web服务器处理请求的基本流程,JSP、Servlet、Spring MVC等只是在 这个基础上嫁了许多方法,以让我们更方面的编写web应用。web服务器不仅可以基于多线程, 也可以基于多进程、Reactor模型等。

HTTP 1.1: HTTP 1.1也是在这个思路的基础上实现的,即多个HTTP请求都在一个TCP连接中传输。对于HTTP 1.1,如何区分出每个HTTP请求很重要, 比较简单的可以是用过Content-Length判断一条请求是否结束。如果一个HTTP请求数据较多,往往采用Chunked方式 。

public class MyHttpServer {

    private static transient final Logger logger = LoggerFactory.getLogger(MyHttpServer.class);

    public static void main(String[] args) throws IOException {
int port =9000;
ServerSocket socket = new ServerSocket(port);
logger.error("启动服务,绑定端口: " + port);
//使用带有ThreadFactory参数的ThreadPoolExecutor构造方法哦,这样你就可以方便的设置线程名字。
//创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。创建线程池的时候请使用带ThreadFactory的构造函数,并且提供自定义ThreadFactory实现或者使用第三方实现。
//ThreadFactoryBuilder需要guavay依赖
//线程池的标准创建方法
ThreadFactory socketThreadFactory = new ThreadFactoryBuilder().setNameFormat("socket-thread-%d").build();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(30,60,3000,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(50),socketThreadFactory,new ThreadPoolExecutor.AbortPolicy());
while (true){
Socket clientSocket = socket.accept();
logger.error("新的连接" + clientSocket.getInetAddress() + ":" + clientSocket.getPort());
threadPoolExecutor.execute(new SocketHandler(clientSocket));
}
}
} public class SocketHandler implements Runnable {
private static transient final Logger logger = LoggerFactory.getLogger(SocketHandler.class);
final static String CRLF = "\r\n"; private Socket clientSocket; public SocketHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
} public void handleSocket(Socket clientSocket) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())));
try {
String requestHeader = "";
String s = "";
//注意s = reader.readLine() 赋值
while ((s = reader.readLine()) != null) {
s += CRLF; // 2 很重要,默认情况下in.readLine的结果中`\r\n`被去掉了
requestHeader = requestHeader + s;
if (s.equals(CRLF)) {
break;
}
} String responseBody = "客户端的请求头是:\n" + requestHeader;
logger.error(responseBody);
String responseHeader = "HTTP/1.0 200 OK\r\n" +
"Content-Type: text/plain; charset=UTF-8\r\n" +
"Content-Length: " + responseBody.getBytes().length + "\r\n" +
"\r\n";
logger.error("响应头:" + responseHeader);
writer.write(responseHeader);
writer.write(responseBody);
writer.flush();
} finally {
writer.close();
reader.close();
clientSocket.close();
}
} @Override
public void run() {
try {
logger.error("当前线程名:"+Thread.currentThread().getName());
handleSocket(clientSocket);
} catch (IOException e) {
e.printStackTrace();
}
}
}

guava依赖用于线程池的 ThreadFactoryBuilder() 线程工厂的创建。

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>

运行:

#变更cmd运行窗口的编码格式为utf-8 ,否则会乱码
chcp 65001
#curl 是一种命令行工具,作用是发出网络请求,然后获取数据
curl -i http://127.0.0.1:9000

curl命令详解参考

或者浏览器执行:

http://127.0.0.1:9000/?happy=happy

命令行运行输出:

浏览器输出:

ERROR - 新的连接/127.0.0.1:59037
ERROR - 当前线程名:socket-thread-7
ERROR - 客户端的请求头是:
GET /?happy=happy HTTP/1.1
Host: 127.0.0.1:9000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 ERROR - 响应头:HTTP/1.0 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 457 ERROR - 新的连接/127.0.0.1:59038
ERROR - 当前线程名:socket-thread-8
ERROR - 客户端的请求头是:
GET /favicon.ico HTTP/1.1
Host: 127.0.0.1:9000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Referer: http://127.0.0.1:9000/?happy=happy
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 ERROR - 响应头:HTTP/1.0 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 442

注意:之所以后台会接收到2个请求,这是浏览器内置的请求方式,比如,除了我们想要的请求外,浏览器还请求了favicon.ico,即网站的图标,所以会有两个响应。

报错:

响应没有得到数据,只有一个响应头:

这是因为在读取流的每一行数据时没有把读到的数据赋值给s。(s = reader.readLine())

    while ((s = reader.readLine()) != null) {
s += CRLF; // 2 很重要,默认情况下in.readLine的结果中`\r\n`被去掉了
requestHeader = requestHeader + s;
if (s.equals(CRLF)) {
break;
}
}

从JSP开始

JSP最合适的用途是用作MVC中的视图,而不是和HTML一起混合编码 (例如把从数据库拉取数据也放入JSP中写)

待细学。

理解Servlet

待细学。

Servlet如何返回JSON数据

response.setContentType("text/html;charset=UTF-8");

修改为

response.setContentType("application/json;charset=UTF-8");

过滤器与监听器

过滤器与监听器

过滤器

过滤器(Filter),并非必须,但很实用。

过滤器是一种设计模式,主要用来封装Servlet中一些通用的代码。在web.xml中配置哪些URL对应哪些过滤器。

一个过滤器的写法如下:

public void doFilter(ServletRequest request , ServletResponse response , FilterChain chain) {
//处理 request
chain.doFilter(request, response);
//处理 response
}

假设针对一URL定义了3个过滤器,分别是MyFilter1、MyFilter2、MyFilter3,在web.xml中也是按照这个顺序设置的, 那么过滤器和Servlet的执行顺序如下:

  • MyFilter1中处理request的代码;
  • MyFilter2中处理request的代码;
  • MyFilter3中处理request的代码;
  • 相应的Servlet;
  • MyFilter3中处理response的代码;
  • MyFilter2中处理response的代码;
  • MyFilter1中处理response的代码;

之所以能达到这样的效果,chain.doFilter(request, response);起到了很大的作用。 值得注意的是,如果每个Filter没有到达chain.doFilter就返回了,那么后续的Filter或者Servlet也就不会执行。

监听器

当某个事件发生时候,监听器里的方法会被调用。例如Tomcat容器启动时、销毁时,session创建时、销毁时。

Tomcat的运行机制

Tomcat 的运行机制

在本手册“理解HTTP”中给出了一个简单的服务器代码,Tomcat的设计思路也是类似的。

Tomcat是一个servlet容器,其运行机制可参考如下:

先不去管技术细节,对一个servlet容器,它首先要做以下事情:

1:实现Servlet api规范。这是最基础的一个实现,servlet api大部分都是接口规范。如request、response、session、cookie。为了我们应用端能正常使用,容器必须有一套完整实现。

2:启动Socket监听端口,等待http请求。

3:获取http请求,分发请求给不同的协议处理器,如http和https在处理上是不一样的。

4:封装请求,构造HttpServletRequest。把socket获取的用户请求字节流转换成java对象httprequest。构造httpResponse。

5:调用(若未创建,则先加载)servlet,调用init初始化,执行servlet.service()方法。

6:为httpResponse添加header等头部信息。

7:socket回写流,返回满足http协议格式的数据给浏览器。

8:实现JSP语法分析器,JSP标记解释器。JSP servlet实现和渲染引擎。

9:JNDI、JMX等服务实现。容器一般额外提供命名空间服务管理。

10:线程池管理,创建线程池,并为每个请求分配线程。

Tomcat有自己的类加载机制。可以参考:

Java类加载原理解析

深入探讨 Java 类加载器

Tomcat类加载器体系结构

Tomcat 8 权威指南

Spring MVC

Spring与依赖注入

依赖注入是反转控制的一种。

什么是反转控制?

我们平常写程序,需要什么对象,就在代码里显式地new一个出来然后使用,这是我们自己去控制对象的生成。 而反转控制是让Spring(或者类似的其他工具)帮忙去生成我们需要的对象,也就是说对象的生成的控制权交给Spring了。

当然,Spring需要依据一定的规则去生成对象,这个规则就在我们写的xml配置文件、或者代码中添加的注解之中。 换句话说,我们不要生成对象,但是要去写配置。

反转控制的实现中应用了大量的反射。

依赖注入

声明依赖关系,Spring将对象A需要的对象B注入到对象A中。

Spring与面向切面编程

面向切面编程是一种编程模式。

使用动态代理可以实现面向切面编程。

这个教程一般,不继续了。

疑问

Q:过滤器与监听器?

Q:Servlet?

其他

 #basedir=你的mysql目录,datadir=数据存放目录
basedir="C:/Program Files/MySQL/MySQL Server 5.7/"
datadir=C:/ProgramData/MySQL/MySQL Server 5.7\Data

springMVC中文乱码问题

Java Web教程——检视阅读的更多相关文章

  1. Spring教程检视阅读

    Spring教程检视阅读 地址 可供参考的教程 <菜鸟学 SSH> <Spring Boot 那些事> <初识 Spring Security> <Sprin ...

  2. MySQL 教程--检视阅读

    MySQL 教程--检视阅读 准备:Windows 上安装 MySQL 教程地址,PHP语言基础 教程地址2 教程地址3,有讲数据库的备份和恢复 教程地址4,w3c.china,php基础,扩展阅读 ...

  3. MyBatis 教程 ——检视阅读

    MyBatis 教程 --检视阅读 准备 官网文档-中文 教程地址yiibai,质量很差 教程地址w3cschool,纯理论,还不如直接看官网文档 教程地址Mybatis框架入门教程,Oracle M ...

  4. AJAX教程——检视阅读

    AJAX教程--检视阅读 参考 AJAX 教程--菜鸟 AJAX 教程--w3cschool AJAX 教程--w3school.cn AJAX 教程--易百 AJAX = Asynchronous ...

  5. Servlet 教程——检视阅读

    Servlet 教程--检视阅读 参考 Servlet教程--菜鸟--蓝本 Servlet教程--w3cschool Servlet教程--易百 servlet依赖maven依赖: <!--se ...

  6. Spring MVC教程——检视阅读

    Spring MVC教程--检视阅读 参考 Spring MVC教程--一点--蓝本 Spring MVC教程--c语言中午网--3.0版本太老了 Spring MVC教程--易百--4.0版本不是通 ...

  7. SpringBoot教程——检视阅读

    SpringBoot教程--检视阅读 参考 SpringBoot教程--一点--蓝本--springboot2.1.1 SpringBoot教程--易百--springboo2.0.5.RELEASE ...

  8. NIO教程 ——检视阅读

    NIO教程 --检视阅读 参考 BIO,NIO,AIO 总结 Java NIO浅析 Java NIO 教程--极客,蓝本 Java NIO 系列教程 --并发编程网 BIO,NIO--知乎 NIO 入 ...

  9. JDBC教程——检视阅读

    JDBC教程--检视阅读 参考 JDBC教程--W3Cschool JDBC教程--一点教程,有高级部分 JDBC教程--易百 JDBC入门教程 – 终极指南 略读 三层架构详解,JDBC在数据访问层 ...

随机推荐

  1. Python python 五种数据类型--字符串

    # python 字符串的初始化 var1 = 'hello,world' # python 字符串为不可变类型 var2= var1* 2 print(var1) #hello,world prin ...

  2. JQuery主要内容

    一.什么是JQuery jquery全称javaScript Query,是js的一个框架,本质上仍然是js 二.jQuery的特点 支持各种主流浏览器 使用特别简单 拥有丰富的插件和边界的插件扩展机 ...

  3. 一夜搞懂 | Java 内存模型与线程

    前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习内存模型与线程? 并发处理的广泛应用是 Amdah1 定律代替摩尔定律成为计 ...

  4. UITextField - 为正文设置缩进

    实现思路: 把UITextField的leftView当做填充位置,这样就实现了文字偏移. 代码: UILabel *label = [[[UILabelalloc] initWithFrame:CG ...

  5. eclipse常用功能及快捷键

    1.更改默认字体 Window->Preferences->General->Appearance->Colorsand Fonts ->Basics->Text ...

  6. 手把手教你分析Mysql死锁问题

    前言 前几天跟一位朋友分析了一个死锁问题,所以有了这篇图文详细的博文,哈哈~ 发生死锁了,如何排查和解决呢?本文将跟你一起探讨这个问题 准备好数据环境 模拟死锁案发 分析死锁日志 分析死锁结果 环境准 ...

  7. 【视频+图文】Java经典基础练习题(六):猴子吃桃子问题

    目录 一.具体题目 二.视频讲解 三.思路分析(逆向思维) 四.代码+结果 代码: 结果: 五.彩蛋 一.具体题目 猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个  第二天 早上又将剩下 ...

  8. synchronized 与 volatile 区别 还有 volatile 的含义

    熟悉并发的同学一定知道在java中处理并发主要有两种方式: 1,synchronized关键字,这个大家应当都各种面试和笔试中经常遇到. 2,volatile修饰符的使用,相信这个修饰符大家平时在项目 ...

  9. thinkphp5.0远程执行漏洞

    0x01 漏洞简介 由于ThinkPHP5 框架控制器名 没有进行足够的安全监测,导致在没有开启强制路由的情况下,可以伪装特定的请求可以直接Getshell(可以控制服务器) 0x02 环境搭建 Ph ...

  10. DVWA渗透笔记

    Command Injection Low <?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $target = $_REQUEST[ ...