JAVAWEB基础
安装Tomcat 9
下载适合自己电脑架构的版本然后解压
下载地址:https://tomcat.apache.org/download-90.cgi
报错:Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
At least one of these environment variable is needed to run this program
未定义JAVA_HOME和JRE_HOME环境变量
运行此程序至少需要这些环境变量中的一个
解决方案:
https://blog.csdn.net/wxb141001yxx/article/details/96976380
因为我的环境变量是在path中写死的,我要修改tomcat的setclasspath.bat文件
添加JAVA_HOME和JRE_HOME的路径
set JAVA_HOME= D:\java\jdk-11
set JRE_HOME=D:\java\jdk-11
测试tomcat
运行startup.bat,访问http://localhost:8080/
能正常访问tomcat就是安装完成了
修改tomcat服务器默认端口
找到\conf\server.xml进行修改
比如把端口修改为8001
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
修改后重启服务可以看到访问8081端口能正常显示欢迎页
发布一个网站
先模仿自带的网站结构
\webapps\ROOT下就是默认自带的网站
复制一份吧文件夹名字改为baicha然后分析里面都是什么
可以看到有一些静态资源、还有一个index.jsp的jsp文件,WEB-INF下存放的是web.xml(网站配置文件)
我们把自带的页面和静态资源删除,只留下WEB-INF文件夹,新建一个index.html(tomcat会去找文件名为index的文件)
html中文乱码使用设置字符编码为utf-8
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<h1>欢迎使用tomcat</h1>
重启tomcat服务器访问http://localhost:8080/baicha/
会自动找到index.html文件进行解析显示出我们编写的代码,欢迎使用tomcat
一个网站常见的结构
-baicha :网站的目录名
- WEB-INF
-classes : java程序
-lib:web应用所依赖的jar包
-web.xml :网站配置文件
- index.html 默认的首页
- static :静态资源目录
-css
-style.css
-js
-img
-.....
安装maven
下载安装Maven
官网:https://maven.apache.org/
下载完成后解压到安装目录D:\maven-3.8.4
配置环境变量
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置%MAVEN_HOME%\bin
配置完成后在cmd中执行mvn -version可以看到maven home等信息就是安装完成了
配置阿里云镜像
在D:\maven-3.8.4\conf下找到settings.xml
添加阿里云镜像配置
<!--默认镜像
<mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>-->
<!--可以不注释上面的,直接添加即可-->
<!--阿里云镜像-->
<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>
配置maven本地仓库
查看配置
<!-- localRepository
maven将使用本地存储库的路径来存储工件。
| The path to the local repository maven will use to store artifacts.
|默认会在用户目录下生成/.m2/repository来存放本地仓库文件
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
修改maven仓库位置为D:\maven-3.8.4\maven-repo
D:\maven-3.8.4\maven-repo
maven在IDEA中的使用
新建maven模块,使用原型创建
设置maven的信息
创建后会自动导入依赖,需要等一会
把项目结构补全
配置项目tomcat
添加本地tomcat配置
设置tomcat服务器的文件位置并且配置项目工件
此处我把url设置为了/,端口号为默认8080
和应用程序上下文(就是你设置的这个工件的url/后面的访问路径)
项目工件把当前模块的war打包发布配置进去了
war模式:将WEB工程以包的形式上传到服务器 ;
war exploded模式:将WEB工程以当前文件夹的位置关系上传到服务器;
运行tomcat访问http://localhost:8080/ 就能显示出新建的web项目自带的index.jsp中的Hello World!
开始技术点学习了
Servlet
编写HelloServlet类,继承HttpServlet
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); //响应流 writer.print("Hello,Serlvet"); //向页面写入 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }}
编写servlet映射
在web.xml中配置servlet
<!--注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>Servlet.HelloServlet</servlet-class> </servlet> <!--Servlet的请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> <!--Servlet请求路径可以映射多个--> <url-pattern>/hello1</url-pattern> </servlet-mapping>
还可以使用通配符设置
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
重启服务器访问http://localhost:8080/hello
ServletContext()对象
使用this.getServletContext()往servlet中注入属性
servletContext.setAttribute(“name”,“baicha”);
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); servletContext.setAttribute("name","baicha"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }}
注册servlet
<!--注册Servlet--><servlet> <servlet-name>hello</servlet-name> <servlet-class>Servlet.HelloServlet</servlet-class></servlet><!--Servlet的请求路径--><servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern></servlet-mapping>
编写conServlet从servlet上下文中获取属性对象
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); String name = (String) servletContext.getAttribute("name"); //设置响应字符编码和格式 resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html"); PrintWriter writer = resp.getWriter(); //响应流 writer.print("名字为"+name); //向页面写入 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
注册conServlet
<!--注册Servlet--><servlet> <servlet-name>name</servlet-name> <servlet-class>Servlet.conServlet</servlet-class></servlet><!--Servlet的请求路径--><servlet-mapping> <servlet-name>name</servlet-name> <url-pattern>/name</url-pattern></servlet-mapping>
重启服务器
直接访问/name是没有名称的,会直接显示为名字为null,需要先访问/hello才能存入servlet上下文才能取出来数据
转发与重定向区别
HttpServletResponse响应
文件下载
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { // 1. 要获取下载文件的路径 String realPath = ""; System.out.println("下载文件的路径:"+realPath); // 2. 下载的文件名是啥? lastIndexOf最后一个\\后面+1位置的就是文件名 String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1); // 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码 resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); // 4. 获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); // 5. 创建缓冲区 int len = 0; byte[] buffer = new byte[1024]; // 6. 获取OutputStream对象 ServletOutputStream out = resp.getOutputStream(); // 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端! while ((len=in.read(buffer))>0){ //OutputStream吧缓冲区输出到客户端 out.write(buffer,0,len); } //关闭资源 in.close(); out.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
重定向
编写sendServlet,重定向到helloServlet
public class sendServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp. sendRedirect("/hello");//重定向
}
}
注册
<!--注册Servlet-->
<servlet>
<servlet-name>send</servlet-name>
<servlet-class>Servlet.sendServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>send</servlet-name>
<url-pattern>/send</url-pattern>
</servlet-mapping>
重定向访问时候url地址会变化,转发时候只有页面有变化
HttpServletRequest请求
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest,通过HttpServletRequest的方法,获得客户端的所有信息;
获取前端传回的信息
//获取单个参数 比如用户名密码等
req.getParameter("");
//获取多个参数 比如复选框参数,比如爱好
req.getParameterValues("");
Cookie
一个cookie只能存一个信息,一个cookie最大4KB
浏览器只能存三百个cookie,一个页面最多20个cookie
public class cookieServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//我浏览器是GBK编码的,根据情况设置
req.setCharacterEncoding("GBK");
resp.setCharacterEncoding("GBK");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies(); //获得浏览器响应的Cookie
if (cookies!=null){
out.write("上一次访问时间是:");
for (Cookie cookie : cookies) {
if (cookie.getName().equals("time")){
long t = Long.parseLong(cookie.getValue()); //吧string类型的时间戳转换为long
Date date = new Date(t);
//吧时间输出
out.write(date.toString());
}
}
}else{
out.write("第一次访问,无cooick");
}
//第一次没有cookie,但是只要访问就自动给客户端返回一个cookie
Cookie time = new Cookie("time", System.currentTimeMillis() + "");//+""吧long自动转换为string
//有效期为一天 设置后浏览器关闭也能继续存活
time.setMaxAge(24*60*60);
resp.addCookie(time);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
注册servlet
<!--注册Servlet-->
<servlet>
<servlet-name>coo</servlet-name>
<servlet-class>Servlet.cookieServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>coo</servlet-name>
<url-pattern>/coo</url-pattern>
</servlet-mapping>
删除了自带的默认cooick之后访问就是没有cooick的
服务端给客户端了一个time
刷新页面能显示出上一次的访问时间,并且服务端吧当前访问时间给了客户端
Session
session是独占浏览器的,关闭浏览器session失效
创建session
HttpSession session = req.getSession();
session.setAttribute("name","baicha");
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
//得到Session
HttpSession session = req.getSession();
//给Session中存东西
session.setAttribute("name","baicha");
//获取Session的ID
String sessionId = session.getId();
//判断Session是不是新创建
if (session.isNew()){
resp.getWriter().write("session创建成功,ID:"+sessionId);
}else {
resp.getWriter().write("session以及在服务器中存在了,ID:"+sessionId);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
创建person实体类,编写有参构造
public class person {
int age;
String name;
public person(int age, String name) {
this.age = age;
this.name = name;
}
}
往session中存入引用类型数据
//给Session中存东西
session.setAttribute("name",new person(1,"we"));
session删除数据和注销session
//删除id为name的session数据
session.removeAttribute("name");
//手动注销Session
session.invalidate();
web.xml中配置session失效时间
<!--设置Session默认的失效时间-->
<session-config>
<!--15分钟后Session自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
JSP
HTML只给用户提供静态的数据
JSP页面中可以嵌入JAVA代码,为用户提供动态数据;
在JSP页面中;
只要是 JAVA代码就会原封不动的输出;
如果是HTML代码,就会被转换为:out.write("\r\n");来输出给前端
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hello</title>
</head>
<body>
<%= new java.util.Date()%>
<%--jsp脚本片段--%>
<%
//计算1+2+...+100--
int sum = 0;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out.println("<h1>Sum="+sum+"</h1>");
%>
<%--在代码嵌入HTML元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1>Hello,World <%=i%> </h1>
<%
}
%>
<%!
static {
//会在第一次访问页面时候运行
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void kuang(){
System.out.println("进入了方法Kuang!");
}
%>
</body>
</html>
页面效果
JSP内置对象
- PageContext 存东西 保存的数据只在一个页面中有效
- Request 存东西 保存的数据只在一次请求中有效,请求转发会携带这个数据
- Response
- Session 存东西 保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
- Application 【SerlvetContext】 存东西 保存的数据只在服务器中有效,从打开服务器到关闭服务器
- config 【SerlvetConfig】
- out
- page ,不用了解
- exception
JAVA Bean
JavaBean就是一个实体类做了数据库的ORM映射
JavaBeen必须要有一个无参构造,要对数据库中的字段进行映射切属性私有,属性必须有相对应的set/get方法
ORM :对象关系映射
- 表—>类
- 字段–>属性
- 行记录---->对象
比如有一个person数据表,其中有id、name、age的属性,与数据库对应进行编写class
public class Person {
private int Id;
private String Name;
private int Age;
public Person() {
}
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
@Override
public String toString() { //非必须
return "Person{" +
"Id=" + Id +
", Name='" + Name + '\'' +
", Age=" + Age +
'}';
}
}
MVC三层架构
M Model 主要负责业务处理,比如Service层和Dao层就是Model层的东西
V View 视图层 主要做展示用户数据,给用户提供页面的交互操作的
C Controller 接口控制层 其中有Servlet层,给视图层提供调用的接口并吧视图层返回回来的操作提交给Service业务层操作
过滤器
导入import javax.servlet.*;下的Filter包
过滤器能在serclet层之前过滤一些数据和请求,还能对乱码进行处理
编写servlet往页面输出文字(必定乱码)
public class ceshiServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("这里是测试Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
注册
<!--注册Servlet-->
<servlet>
<servlet-name>ceshi</servlet-name>
<servlet-class>Servlet.ceshiServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>ceshi</servlet-name>
<url-pattern>/ceshi</url-pattern>
</servlet-mapping>
访问查看页面
编写过滤器对字符集进行编码
public class FilterDemo 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("CharacterEncodingFilter执行前....");
filterChain.doFilter(servletRequest,servletResponse); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
System.out.println("CharacterEncodingFilter执行后....");
}
@Override
//销毁
public void destroy() {
}
}
注册过滤器
<!--配置过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>Filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--任何请求,会经过这个过滤器-->
<url-pattern>/*</url-pattern>
</filter-mapping>
重启项目查看页面
监听器
可以实现的监听器接口非常多,当前使用session监听器去监控当前在线人数
注意:
Listener配置信息必须在Filter和Servlet配置之前,Listener的初始化(ServletContentListener初始化)比Servlet和Filter都优先,而销毁比Servlet和Filter都慢。
编写监听器
public class SessionListener implements HttpSessionListener {
//创建session监听: 看你的一举一动
//一旦创建Session就会触发一次这个事件!
public void sessionCreated(HttpSessionEvent se) {
//从上下文对象分钟获得session
ServletContext ctx = se.getSession().getServletContext();
//打印session对象id
System.out.println(se.getSession().getId());
//获取对象中sessionKey为OnlineCount的值为多少
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
//如果为null默认设置为1
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
//给session对象设置值
ctx.setAttribute("OnlineCount",onlineCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
//从上下文对象分钟获得session
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
//如果为空就设置为0
onlineCount = new Integer(0);
}else {
//如果不为空但是走了这个方法默认就是销毁session了,直接值减一
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
//设置session
ctx.setAttribute("OnlineCount",onlineCount);
}
}
注册监听器
<!--注册监听器-->
<listener>
<listener-class>Listener.SessionListener</listener-class>
</listener>
编写测试servlet
public class ceshiServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//防止出现直接访问此servlet会出现500等问题
HttpSession session = req.getSession();
ServletContext servletContext = req.getServletContext();
int onlineCount = (int) servletContext.getAttribute("OnlineCount");
System.out.println(onlineCount);
PrintWriter writer = resp.getWriter(); //响应流
writer.print("在线人数为"+onlineCount); //向页面写入
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
doGet(req,resp);
}
}
再打开一个浏览器访问页面
成功实现记录在线人数功能