在前面我们介绍了网络与Java相关的问题, 最近在调研的时候发现这块内容其实非常复杂,涉及的内容多而且零碎,想短时间梳理出整个体系是不太可能的,所以我们还是继续看Tomcat的问题,后面有网络的内容继续补充吧。
目录
1 搭建一个本地web服务
2 Java web是如何工作的
Servlet是Java Web的核心机制,而实现Servlet最好的服务器无疑就是Tomcat。在前面我们介绍了如何用Java实现网络通信,这个与自己实现一个Servlet服务器,比如Tomcat 还差多少呢?差十万八千里,有一个挺好玩的图:
目前各类Spring的材料实在太多了,我们用的也多。那么Spring到底是什么?又有什么用呢?我们可以找到一堆的标准答案,但是貌似对Spring的理解总是感觉没有学透,那么Spring的作用到底体现在哪里呢?要理解这个问题,我们需要先看一下没有Spring的世界是什么样的,然后再看看有了Spring之后是什么样子的,这样自然理解更加透彻。
史前时代
假如没有Spring框架,要开发一个java web程序该怎么做呢?很多人马上想到了Java web里的Servlet、JSP以及Tomcat这些技术,是的,这是用Java做web应用基础技术。接触Java 有些年头了,相信很多人已经忘记了怎么创建一个不使用构建工具和任何Java Web框架的原始JavaWeb。本节我们看一下如何搭建一个没有高级框架的web应用。这个工作使用idea还挺麻烦,我们记录一下:
1 搭建一个本地web服务
1.打开idea,选择file->New->Project
2.点击Java,点击下一步.
3.修改项目名
这里根据你的计划,设置到一个相对稳定的目录即可。为了防止异常问题,建立路径里不要有空格或者中文字符。
4.右键项目,选择add framework support
5.完成之后,项目结构变成了这样,然后我们在WEB-INF下创建classes和lib文件夹,如下所示:
6.接下来,编辑项目结构, 将output path的路径改成classes文件夹的路径,如下所示:
7.点击dependencies,选择加号,选择jars or directories, 点击后,他会弹出一个文件选择框,这里选择lib文件所在位置,如图所示:
然后此时单击西方的“+”号,会出现中间位置的弹窗,单击之后会在中间位置出现一个小窗口:
这里将web-INF下的lib目录添加进来。此时还会出现一个弹窗,就是询问这个lib是干什么的,这就是我们后面会手动添加的lib:
之后选中退出即可,效果如下:
接下来要配置tomcat,我们使用的是8.5。这个需要先下载到本地,然后执行一下看看是否正常。之后再在idea中配置。
单击idea的“Run”,然后选择“edit setting”,进入下面的界面:
此时我们要首先选择左上方的“+”,在列表中找到“tomcat server”(注意不要和TomEE server混了)。
然后配置右侧的相关内容。这里图中标记处默认的端口号是8080,但是8080经常会和其他服务冲突,因此这里改成了9091。
这里还要注意deployment下的这个配置:
保持与全面访问路径一致。
最后我们打开index.jsp页面,增加如下内容:
<html><head><title>Hello world</title></head><body>
Hello world</body>
</html>
之后启动tomcat,在浏览器输入:http://localhost:9091/webtest/就可以看到一个“Hello world"的信息。
2 Java web是如何工作的
有了上面的环境之后,那如何实现展示的内容与后台Java交互呢?我们知道有两种常用的技术,一种是JSP,一个是直接写Servlet。JSP其实就是在静态页面里嵌入Java代码,而Servlet则是在Java代码里嵌入静态代码,例如常见的JSP页面一般是这样的:
<%@ page import="com.lqc.pojo.Person" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %><%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body><%Person person = new Person();person.setName("哥好帅!");person.setPhones(new String[]{"11111111111","13333333333","13666666666"});List<String> cities = new ArrayList<String>();cities.add("北京");cities.add("上海");person.setCities(cities);Map<String,Object>map = new HashMap<>();map.put("key1","value1");map.put("key2","value2");person.setMap(map);pageContext.setAttribute("p", person);%>输出Person:${ p }<br/>输出Person的name属性:${p.name} <br>输出Person的pnones数组属性值:${p.phones[2]} <br>
</body>
</html>
而典型的Servlet代码是这样的:
public class HelloServlet extends HttpServlet {public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {// 设置响应内容类型response.setContentType("text/html");// 实际的逻辑是在这里PrintWriter out = response.getWriter();out.println("<h1> servlet Hello World </h1>");}protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}public void destroy() {// ....}
}
此时还要在web.xml中增加相关的配置信息:
<servlet><servlet-name>helloServlet</servlet-name><servlet-class>com.lqc.webtest.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>helloServlet</servlet-name><url-pattern>/helloServlet</url-pattern></servlet-mapping>
这时候,然后重启tomat,输入地址http://localhost:9091/webtest/helloServlet,就可以看到页面展示了“servlet Hello World”。
上面的代码不管是在JSP中嵌套Java代码,还是在Servlet中嵌套静态代码,如果到工程里这么干,肯定都是灾难,虽然可以使用EL等优化,但是对于变成来说仍然非常不友好。典型的情况有:
1.前端必须会后台的技术,后台也必须会前端的技术,不利用不同技术栈的人相互合作。
2.即使懂相关技术非常容易错,即使错了也无法很好的定位。
3.很难扩展和维护。
为了解决这个问题 ,必须要实现前后端代码的分离,该如何分离呢?其实思路非常简单,我们上面输入的请求地址即使不用浏览器也能请求的,例如可以使用curl命令:
这里同样返回了结果“<h1> servlet Hello World </h1>”。既然这样,那我前端工程只要能发送和接收http请求就可以了?入参和出参可以双方协定, 只要规则一致就可以正确相互解析了?其实前后端分离,或者动静分离,都是这个原理。之后前端和后端就分道扬镳了,前端有VUE等框架,而后台则更多。
动静分离之后就没问题了吗?当然不是,后台要干的事情其实非常多,要处理用户请求,要执行很多业务处理、要负责数据库管理等等,还是太多了,那怎么办呢?这时候MVC模式就开始大量应用了,Java中最为典型的就是Struts2和SpringMVC,这个曾经被使用了很多年,估计现在很多公司的老项目还有其身影,使用MVC框架的的好处有:
- 允许更改视图层代码而不用重新编译模型和控制器代码;
- 允许使用各种不同样式的视图来访问同一个服务器端的代码;
- 使降低开发和维护用户接口的技术含量成为可能;
- 使开发时间得到相当大的缩减等。
与此同时,为了处理数据库管理的麻烦,就诞生了专门的框架,这就是持久化框架(ORM),最为典型的就是Hibernate、Mybatis和SpringJDBC Tempalte。由于Hibernate封装过度,导致框架过重,很多优化等不方便,所以逐步被Mybatis等取代。
有了MVC框架和ORM框架,就够了吗?还不是,问题还有很多,其中最典型的问题是其配置问题,例如你要在Struts.xml中配置每个对象和实现类的映射关系,例如:
<!--配置package,必须继承Struts-default-->
<struts><package name="struts2" extends="struts-default"><!--配置按action,名字hello是访问URL使用的:hello.action--><action name="hello" class="org.yangjq.HelloAction"><result name="success">/success.jsp</result><result name="error">/error.jsp</result></action></package>
</struts>
Spring是如何管理用户的类的,这是一个很常见的面试题。其实管理的就是类似上面的Struts.xml里的配置,随着Spring的不断完善,衍生出来的功能越来越多,功能越来越强,甚至很多人“只知Spring,不知Java Web”。
不过呢,Spring管理我们的类也需要一大堆的配置文件,这个过程仍然是非常痛苦,所以后面就逐步有了SpringBoot,SpringBoot使用自动装载等机制帮助我们省去了大量而繁琐的配置问题,很多时候我们只要加一个注解或者包扫描就可以使用了,这个我们后面再说。