javaweb详解
一.Tomcat
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求
1. javaWeb本体的目录
bin
:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat8.exe、tomcat8w.exe,前者是在控制台下启动Tomcat,后者是弹出UGI窗口启动Tomcat;如果是解压版,那么会有startup.bat和shutdown.bat文件,startup.bat用来启动Tomcat,但需要先配置JAVA_HOME环境变量才能启动,shutdawn.bat用来停止Tomcat;
conf
:这是一个非常重要的目录,这个目录下有四个最为重要的配置文件.
server.xml
:配置整个服务器信息。例如修改端口号,添加虚拟主机等;
tomcat-users.xml
:存储tomcat用户的文件,这里保存的是tomcat的用户名及密码,以及用户的角色信息。可以按着该文件中的注释信息添加tomcat用户,然后就可以在Tomcat主页中进入Tomcat Manager页面了;
web.xml
:部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。这些MIME类型是客户端与服务器之间说明文档类型的,如用户请求一个html网页,那么服务器还会告诉客户端浏览器响应的文档是text/html类型的,这就是一个MIME类型。客户端浏览器通过这个MIME类型就知道如何处理它了。当然是在浏览器中显示这个html文件了。但如果服务器响应的是一个exe文件,那么浏览器就不可能显示它,而是应该弹出下载窗口才对。MIME就是用来说明文档的内容是什么类型的!
context.xml
:对所有应用的统一配置,通常我们不会去配置它。
lib
:存放了Tomcat软件启动运行的依赖jar文件.logs
:这个目录中都是日志文件,记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,那么异常也会记录在日志文件中。temp
:存放Tomcat的临时文件,这个目录下的东西可以在停止Tomcat后删除!webapps
:存放web项目的目录,其中每个文件夹都是一个项目;如果这个目录下已经存在了目录,那么都是tomcat自带的项目。其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目
work
:工作目录,存放了jsp翻译成Servlet的java文件以及字节码文件.
1.将目标项目直接打成war包,然后放入webapp中.Tomcat会将war包自动解开.
i 将一个项目打成zip文件.
ii 移动到webapp中
我们可以看到已经自动解压缩了.
2.在config
目录下的server.xml
中设置
进入其中,在里面加入这样一个句子
-
docBase
:你 项目所在的地点. -
path
:你项目的外部访问路径,即从浏览器中输入什么内容,可以访问到. -
ex:
这个就是就是因为配置了初始页面,所以会是这个样子.这个到后面再说.你只要知道设path的内容被添加到localh0st:8080之后.
3.在conf\Catalina\localhost创建任意名称的xml文件
i. 在文件中编写 比如 bbb.xml
此时的path虚拟目录就为xml文件的名称
Tomcat和idea融合
1.我们需要创建javaEE项目
2.有红色标记部分,都可以达成下一步目标.
3.打开Template
4.进行进一步配置(里面的内容可以没用前后顺序)
5.配置完后开始加入模块
6.对于模块进行配置
一顿继续就ok了.
配置完成.
有可能出现一个小BUG,就是在更改完
如上的URL之后,会导致一启动,就报404错误.
其主要原因就在于没有配置另一个部分.
如下.这个就是上面我们手动配置时候,输入的那个path
,如果他对不上,前面怎么访问都访问不到.
以上的内容就是配置阶段的内容.比较简略,照着做可能会出现bug.但是不要担心,作为初学阶段,这些BUG大多不会太难.
可以靠手动重启Tomcat(到bin文件夹中点击start_up
和shutdowm
来完成目标)
下面这个部分就是关于Servlet
的操作.
Servlet
入门案例
servlet实际上是一个接口.
sun公司定义了一套专门用于开发Servlet程序的类和接口,统称为ServletAPI
所有的Servlet类都必须实现Servlet接口.
即如下情况所示.
import javax.servlet.*;
import java.io.IOException;
public class MyServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init()执行");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service执行");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("销毁");
}
}
因为Servlet函数实际上是由服务器(实际上是Servlet引擎(容器))调用的,光写一个类可没什么效果,我们还要进行配置.
如下内容:
如下的内容再WEB.XML
中进行配置.
要是你没配置WEB.XML,那么就去WEB-INF下面配置一个
//这个部分配置的是servlet程序得名字和相对路径
//一个名字,用来再WEB.XML中使用.他将在WEB.XML代表中的内容
Myservlet
//相对路径
MyServlet
//servlet映射部分.将servlet映射到一个URL地址上.
//servlet在上面那个部分设置得名字,
Myservlet
//url地址
/Myservlet
这是一个具体的原理.
从这里引用
当然,本着操作和实践分离得原则.这里不会具体讲解.
另外可以用一个
对servlet程序进行设置.
负数
第一次访问时创建
正数
服务器启动时创建
当然,默认得话还是第一次访问的时候才创建得.
ServletConfig类
首先一个ServletConfig类对应着一段web.xml中配置的Servlet信息;也就是说我们配置的Servlet信息都会被Tomcat解析后,将配置信息的数据保存在ServletConfig类中.
所以一个ServletConfig类只对应一段Servlet信息
.
因为只传入init()方法中,所以也只能在init()方法中使用.
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//这个再服务器启动的过程中只会执行一次
System.out.println("init()执行");
//servletConfig对象会在Tomcat调用service时被传入.这个里面时各种各样的内容
//得到
String servletName = servletConfig.getServletName();
System.out.println(servletName);
//得到初始化配置,按照值获取
String namespace = servletConfig.getInitParameter("namespace");
System.out.println("servletConfig.getInitParameter(\"namespace\");"+namespace);
//得到初始化配置,全部获取
Enumeration initParameterNames = servletConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements())
System.out.println(initParameterNames.nextElement());
//
}
这是整个句子.
另外我们再WEB.XML中的代码也有了一部分改变.
Myservlet
MyServlet
//增加的部分
namespace
1234
Myservlet
/Myservlet
执行结果如下
init()执行 <---init方法部分
MyServlet <---getServletName();
1234 <--getInitParameter("namespace")
namespace <---getInitParameterNames();
----------------------------service方法部分
service执行 <--service
当然这么配置明显太过于费事,我们可以用简单一点的方式解决这个问题
注解
@WebServlet(value = "/Myservlet",initParams = {
//value等同于 中配置的东西.
//类名可以直接获取...不必映射,所以这个配置就可以了
@WebInitParam(name="namespace",value = "1234")
//WebInitParam等同于内容,里面的name和value必须写
})
public class MyServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//这个再服务器启动的过程中只会执行一次
System.out.println("init()执行");
//servletConfig对象会在Tomcat调用service时被传入.这个里面时各种各样的内容
//得到
String servletName = servletConfig.getServletName();
System.out.println(servletName);
//得到初始化配置,按照值获取
String namespace = servletConfig.getInitParameter("namespace");
System.out.println("servletConfig.getInitParameter(\"namespace\");"+namespace);
//得到初始化配置,全部获取
Enumeration initParameterNames = servletConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements())
System.out.println(initParameterNames.nextElement());
//
}
有了注解之后XML文件就可以不用了.
当然,加入注解后要在XML文件中进行一个小设置,才会生效.
metadata-complete="false"
false的意思是不忽略注解
true的意思是忽略注解
>
ServletContext
ServletContext对象,tomcat为每一个web项目单独创建的一个(ServletContext)上下文(知上知下贯穿全文)对象。服务器启动的时候,为每个WEB应用创建一个单独的ServletContext对象,我们可以使用这个对象存取数据,用这个对象存取的数据,可以在整个WEB应用中获取.
服务器会为每个应用创建一个ServletContext对象:
ServletContext对象的创建是在服务器启动时完成的;
ServletContext对象的销毁是在服务器关闭时完成的。
版权声明:本文为CSDN博主「White Camel」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37989980/java/article/details/104088452
这样的话就可以在不同的Servelt之间进行传递操作.
1.多个servlet之间共享数据
setAttribute(String name,Object object) 向ServletContext中存数据
getAttribute(String name) 从ServletContext中取数据
removeAttribute(name) 从ServletContext中移除数据
这个例子会有两个Servlet程序,用来完成在两个Servlet之间传递的模拟.
发送的servlet程序
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//每次访问都会执行一次
System.out.println("service执行");
servletRequest.getServletContext().setAttribute("name",1);
}
接收的servlet程序
@WebServlet("/ScopeServlet")
public class ScopeServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
//获取ServletContext得到其中的name属性
int name =(Integer) req.getServletContext().getAttribute("name");
System.out.println(name);
//删除name属性
req.getServletContext().removeAttribute("name");
//再次寻找,看是否找得到
Object name1 = req.getServletContext().getAttribute("name");
System.out.println(name1);
}
}
返回的结果是
1 <--值就是1
null <--因为以前删掉了,所以找不到
二、获取当前WEB项目中的指定资源(文件)
既然 ServletContext 是 贯穿全文 的对象 ,所以项目中的资源 它都能访问到 , 主要用它获取web项目中文件.
文件保存的位置 :
1.src下 : 发布到 /WEB-INF/classes/文件名
2.web目录下 : 发布到/文件名
3.WEB-INF目录下 : 发布到 /WEB-INF/文件名
例子:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
ServletContext servletContext = req.getServletContext();
String realPath = servletContext.getRealPath("/MyServlet");//获取绝对路径
//在这里我们用的都是相对路径
System.out.println(realPath);
}
结果如下:
C:\Users\22643\Downloads\AAA\test\out\artifacts\test1_war_exploded\MyServlet
三、获取应用初始化参数
注意这个和上面我们配置的那个参数不是一码事.所以...
我们使用
来进行设置.这个是每个servlet都可以使用的一个属性
servletContext.getInitParameter
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
ServletContext servletContext = req.getServletContext();
String namespace = servletContext.getInitParameter("namespace");
System.out.println(namespace);
}
转发重定向
这里只讲解一下实现方式,对于其原理并不讲解.(将来会补上)
接收端
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("到了本页");
req.setAttribute("name","yan");
//req域,调用getRequestDispatcher("/目标地址").forward(req,resp);req是自己这个
req.getRequestDispatcher("/ScopeServlet").forward(req,resp);
}
发送端
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.service(req, resp);
String name = (String)req.getAttribute("name");
System.out.println(name);
}
还有就是重定向
发送端
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//可以跳转到另一个界面.
resp.sendRedirect("ScopeServlet");
}
接收端
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("到了本页");
String name = (String)req.getAttribute("name");//没效果
System.out.println(name);//null
}
request
request的方法个人认为分为两个部分
一个部分是是对于url?前的部分进行操作.
另一个是对url?后的部分进行操作
http://localhost:8080/Myservlet ? username=123&password=321
对于前面那个部分的操作 对于后面这个部分的操作
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String getMethod(): 返回请求方式(GET/POST)
String getRequestURI():返回请求行中资源名字部分: 如/test/index.html
StringBuffer getRequestURL():返回浏览器地址栏的内容
String getContextPath():获取上下文路径(虚拟目录),
String getRemoteAddr():返回请求服务器的客户端的IP地址
String getHeader(String headName):根据指定的请求头获取对应的请求头的值.
System.out.println(req.getMethod());
System.out.println(req.getRequestURL());
System.out.println(req.getRequestURL());
System.out.println(req.getContextPath());
System.out.println(req.getRemoteAddr());
System.out.println(req.getHeader("User-Agent"));
}
GET
http://localhost:8080/test1/Myservlet
http://localhost:8080/test1/Myservlet
/test1
0:0:0:0:0:0:0:1
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.
然后是后面那个部分
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String getParameter(String name):根据参数名称,获取对应参数的值.
String[] getParameterValues(String name):根据参数名称,获取该参数的多个值.
Enumeration<String> getParameterNames(): 获取所有请求参数的名字
Map getParameterMap():返回请求参数组成的Map集合.
key:参数名称
value:参数值,封装在String数组中.
//String getParameter(String name):根据参数名称,获取对应参数的值.
System.out.println(req.getParameter("username"));
//String[] getParameterValues(String name):根据参数名称,获取该参数的多个值.
String[] usernames = req.getParameterValues("username");
System.out.println(usernames[0]);
//Enumeration<String> getParameterNames(): 获取所有请求参数的名字
Enumeration parameterNames = req.getParameterNames();
while(parameterNames.hasMoreElements()){
String s = parameterNames.nextElement();
System.out.print(s+" ");
}
//Map getParameterMap():返回请求参数组成的Map集合.
Map parameterMap = req.getParameterMap();
String[] passwords = parameterMap.get("password");
System.out.println(passwords[0]);
}
其中如果使用post方法就会出现乱码错误.那么最好的办法就是
如下处理办法.
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//正常获取
String username = req.getParameter("username");
System.out.println(username);
//将其转换为"ISO-8859-1"的字节码.
byte[] bytes = username.getBytes("ISO-8859-1");
System.out.println(bytes);
//将其翻译成"UTF-8"的String类型
String username2=new String(bytes,"UTF-8");
System.out.println(username2);
}
还有更简单的
// 对于POST请求 可以设置请求的编码
req.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
System.out.println(username);