Web开发
Web应用
如果你统一的web资源放在同一个文件夹下,就是一个web应用程序了,但是这时外界访问不到,需要一个服务器:Tomcat,由它来统一管理。
Web应用包含哪些部分呢:
html,css,js,
jsp,servlet
java程序
jar包
配置文件
静态Web资源
*htm,*html,网页的后缀,由程序跳转的是没有后缀的,如果服务器上一直存在这些东西,我们就一直可以访问到。
>轮播图,点击特效,伪动态
>js[实际开发中用的多]
>无法与数据库交互
Web服务器
ASP:
微软:国内最早流行的就是ASP
html开发中嵌入了VB脚本,ASP+COM;
PHP开发速度很快,跨平台,代码很简单。无法承载大的访问量
JSP/Servlet:
B/S架构浏览器和服务器
sun公司主推B/S架构
给予Java语言(所有的大公司,一些开源的j架构都是Java写的)
语法像ASP->JSP,加强市场度
IIS:Windows中自带的
微软开发的服务器
Tomcat:
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。最新版本为9.0。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。
安装:解压
配置:
HTTP响应体
Accept:告诉浏览器,他所支持的数据类型
Accept-Encoding:告诉浏览器支持哪种编码格式
Accept-Language:告诉浏览器他的语言环境
Cache-Control:缓存控制
Connection:高速浏览器,请求完成后,是断开还是关闭
Host:主机
Refresh:告诉客户端多久刷新一次
Location:让网页重新定位。
响应状态码
200代表响应成功
3xx:请求重定向
404资源不存在
405方法错误
502网关错误
Maven
M2:是spring和springboot访问的自动依赖了M2的地址
项目架构管理工具
下载完成后没有maven-repo
config下的:settings.xml的mirror是镜像,方便在国内下载依赖包。用阿里云的镜像
<id>nexus-aliyun</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
本地仓库
在本地的仓库
远程的仓库
建立本地仓库:xml中localRepository
IDEA的maven
GAV:
GroupId:组Id
Artificate:项目
Version:
IDEA添加Tomcat时Warning的问题解决:
因为Web项目必须要指定一个文件夹作为存放Web资源的路径,因此必须有一个目录,这里只需要在Development中添加一个
Application context可以写也可以不写,如果不写,访问路径路径为
localhost:8080.如果写了xia,那访问路径是localhost:8080/xia,这个过程叫做虚拟路径映射。
右上角启动Tomcat
启动成功就访问的是默认的index.jsp中的内容。
Pom文件
版本和头文件
GAV
package打包类型
jar:对应Java应用
war:对应Web应用
properties:项目的默认构建编码
编码版本
build:项目构建用的东西
Servlet
Servlet就是sun公司开发动态web的一门技术
Sun在这些API中提供一个接口叫做: Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
编写一个类,实现Servlet接口
把开发好的Java类部署到web服务器中。把实现了Servlet接口的Java程序叫做,Servlet6.2、Helloservlet1.Servlet接口有两个实现类HttpServlet和GenericServlet
Maven中的项目
父项目
<modules>
<module>servlet-01</module>
</modules>
子项目
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.kuang</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
原理剖析:
父项目中 的Java子项目可以直接使用son extends father
编写Servlet的映射为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;
<web-app>
<!--新建一个servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/webxml</url-pattern>
</servlet-mapping>
</web-app>
配置Tomcat
项目的发布路径
启动测试
servlet访问的target下的war包。
Servlet原理
Servlet是由Web服务器调用,Web服务器在收到浏览器请求之后,会
引用狂神老师讲课图片:
在这里插入图片描述
Mapping问题
一个servlet可以指定多个容器
<!--可以自定义后缀或前缀-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/webxml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/xia/*</url-pattern>
</servlet-mapping>
<!--这样写是错误的。不能在匹配符前加/-->
<!--servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*.do</url-pattern>
</servlet-mapping-->
优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
WebContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象, 它代表了当前
的web应用;
ServletContext servletContext = this.getServletContext();
不同的Servlet可以通过 servletContext共享数据
首先定义一个HelloServlet类:
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//初始化参数
this.getInitParameterNames();
//servlet的配置
this.getServletConfig();
//上下文
ServletContext servletContext = this.getServletContext();
String username = "xia";
servletContext.setAttribute("username",username);
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.println("haahahaa");
}
}
再另外一个Servlet类中,访问我在HelloServlet中所定义的字符串
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String username = (String)servletContext.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("属性是"+username);
}
@Override
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
在web.xml中所定义的Servlet,映射关系,及请求路径如下
<web-app>
<servlet>
<servlet-name>servlet-02</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>getServlet</servlet-name>
<servlet-class>com.kuang.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet-02</servlet-name>
<url-pattern>/servlet02</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>getServlet</servlet-name>
<url-pattern>/getServlet</url-pattern>
</servlet-mapping>
</web-app>
测试结果,通过访问getServlet得到了HelloServlet中所定义的字符串
Servlet获取初始化参数
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().println(url);
}
}
xml配置
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>servlet03</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet03</servlet-name>
<url-pattern>/url</url-pattern>
</servlet-mapping>
验证结果,从浏览器中获取到了初始化参数
请求转发
读取资源
Properties
●在java目录下新建properties
●在resources目录 下新建properties
发现:都会被打包到了同一个个路径下: classes ,我们称这个路径为classpath;
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//读取相对路径下文件
InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("用户名:" + user);
resp.getWriter().println("/n");
resp.getWriter().println("密码:" + pwd);
}
}
<servlet>
<servlet-name>servlet05</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet05</servlet-name>
<url-pattern>/servlet05</url-pattern>
</servlet-mapping>
验证结果:
//中文用该方法
public ServletOutputStream getOutputStream() throws IOException;
//平常写内容
public PrintWriter getWriter() throws IOException;
下载文件
1.要获取下载文件的路径
2.下载的文件名是啥?
3.设置想办法让浏览器能够支持下载我们需要的东西
4.获取下载文件的输入流
5.创建缓冲区
6.获取OutputStream对象
7.将FileOutputStream流写入到buffer缓冲区
8.使用OutputStream将缓冲区中的数据输出到客户端!
ServletOutputStream outputStream = resp.getOutputStream();
// 1.要获取下载文件的路径
//servletContext()是由tomcat的创造的,当下运行的tomcat工程是运行项目寻找密码.txt,按照这个目录是找不到的,因为他的真正目录是:D:\A-Study\JavaWeb-Study\response\target\classes\密码.txt
String realPath = this.getServletContext().getRealPath("/密码.txt");
下载文件:
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletOutputStream outputStream = resp.getOutputStream();
// 1.要获取下载文件的路径
//String realPath = this.getServletContext().getRealPath("/密码.txt");
// 2.下载的文件名是啥?
String realPath = "D:\\A-Study\\JavaWeb-Study\\response\\target\\classes\\密码.txt";
System.out.println("下载文件路径:"+ realPath);
// 3.设置想办法让浏览器能够支持下载我们需要的东西
String filterName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 4.获取下载文件的输入流
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filterName,"utf-8"));
// 5.创建缓冲区
FileInputStream fileInputStream = new FileInputStream(realPath);
int len = 0;
byte[] buffer = new byte[1024];
// 6.获取OutputStream对象
ServletOutputStream outputStream1 = resp.getOutputStream();
// 7.将FileOutputStream流写入到buffer缓冲区
while((len = fileInputStream.read(buffer)) > 0){
outputStream.write(buffer,0,len);
}
// 8.使用OutputStream将缓冲区中的数据输出到客户端!
fileInputStream.close();
outputStream.close();
}
}
验证码功能
●前端实现
●后端实现,需要用到Java的图片类,生产- -个图片
public class ImageService extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("refresh","8");
//在内存中创建一个图片
BufferedImage image = new BufferedImage(80,30,BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics = (Graphics2D)image.getGraphics();//笔
graphics.setColor(Color.WHITE);
graphics.fillRect(0,0,80,30);
//给图片写数据
graphics.setColor(Color.BLACK);
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");
//把图片写给浏览器
boolean jpg = ImageIO.write(image, "jpg", resp.getOutputStream());
}
private String makeNum(){
Random random = new Random();
String s = random.nextInt(9999999) + "";
StringBuffer stringBuffer = new StringBuffer();
for(int i = 0;i<7-s.length();i++){
stringBuffer.append("0");
}
return s;
}
}
请求转发
概念:一个web资源收到客户端请求后,他会通知客户端去访问另外-一个web资源,这个过程叫重定向。
常见场景:
用户登录。
//resp.sendRedirect("/r/imageServlet");//重定向
resp.setHeader("Location","/r/imageServlet");
resp.setStatus(404);
面试题
重定向和转发的区别:
相同点:都会实现页面的跳转
不同点:重定向,请求的url发生了变化,状态码307。
转发:请求的url没有发生变化,状态码:302
Session与Cookie的区别
●Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
●Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息, 减少服务器资源的浪费)
●Session对象由服务创建;
使用场景
●保存一个登录用户的信息;
●购物车信息;
●在整个网站中经常会使用的数据,我们将它保存在Session中;
JSP(Java Server Pages)
1、首先,客户端发出请求(request ),请求访问JSP网页
2、接着,JSP Container将要访问的.JSP文件 转译成Servlet的源代码(.java文件)
3、然后,将产生的Servlet的源代码(.java文件)经过编译,生成.class文件,并加载到内存执行
4、最后把结果响应(response )给客户端
ORM
即:对象关系映射,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。
早期架构:
旧版:
用户直接访问控制层,控制层可以直接操作数据库:
1、Servlet–CRUD–数据库
弊端:程序十分臃肿,不利于维护
2、serv1et的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码,功能繁杂,耦合性高。
程序猿调用
JDBC
Mysq1 oracle sq1Server …
架构改进(MVC):
1、控制器Servlet不再直接操作entity层了
2、控制器Servlet不再响应客户端内容,把该职责转给了业务层了,view层负责展示用户模型提供用户操作。比如从数据库查询数据,只负责展示
3、控制器负责重定向或转发(视图跳转)
4、将原来的entity的职责交给Dao,与数据库交互。
5、增加了一个业务层,即model层,包含原来的service层与新增加的Dao层.负责控制业务操作,保存数据、修改数据、删除数据、查询数据。
6、entity的变得更为空旷,只是代表一个类。
Model
●业务处理:业务逻辑(Service)
●数据持久层: CRUD (Dao)
View
。展示数据
”提供链接发起Servlet请求(a, form, im…)
Controller (Servlet)
●接收用户的请求: (req: 请求参数、Session信…
●交给业务层处理对应的代码
●控制视图的跳转
过滤器
public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("跟Web服务器一起初始化了,为了监听所有的请求");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;character=UTF-8");
System.out.println("chain执行前");
//过滤中的所有代码,在过滤特定请求的时候都会执行
filterChain.doFilter(servletRequest,servletResponse);//
System.out.println("chain执行后");
}
public void destroy() {
System.out.println("web服务器关闭的时候,过滤器会被销毁");
}
public CharacterEncodingFilter() {
}
}
监听器
public class OnLineCountListener implements HttpSessionListener {
//创建session监听
//一个session创建后,就会触发这个事件
public void sessionCreated(HttpSessionEvent se) {
//获得网站上下文
ServletContext ctx = se.getSession().getServletContext();
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);
System.out.println( "OnLineCountListener重新刷新了网站访问量");
}
//创建session监听
//一个session销毁后,就会触发这个事件
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
}
}
配置:
<listener>
<listener-class>com.xia.OnLineCountListener</listener-class>
</listener>
总结:通过网站上下文获取一个属性。在监听器中写逻辑,完成网站访问数量的统计。
应用: