Java_web入门
Java_web概述
Java_web应用由一组Servlet、Html页、类以及其它可绑定的资源构成。它可以在各种供应商提供的Servlet规范的Servlet容器中运行。
Java_web包含以下内容:
-
Servlet
-
JSP
-
实体类
-
静态文档如HTML,图片等
-
描述web应用的信息web.xml
Servlet与Servlet容器
Java_web目录结构
Servlet
Servlet功能
-
创建并返回基于客户请求的动态HTML页面
-
创建可嵌入到现有HTML页面中的部分HTML页面
-
与其他服务器资源(如数据库或基于Java的应用程序)进行通信
Servlet容器响应客户请求
第一个servlet及其在web.xml中的配置
package com.why.study2.servlet;
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
<!-- 配置和映射Servlet-->
<servlet>
<!-- Servlet注册名-->
<servlet-name>helloServlet</servlet-name>
<!-- Servlet全类名-->
<servlet-class>com.why.study2.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<!-- 需要和某一节点的servlet-name保持一致-->
<servlet-name>helloServlet</servlet-name>
<!-- 映射具体的访问路径-->
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
同意Servlet可映射多个servletmapping,即多个servletmapping的<servlet-name>可相同
带扩展名/不能加*,带 *不能加扩展名,即/ *.html不合法
Servlet容器
-
创建Servlet,并调用Servlet的相关生命周期方法
-
运行Servlet,JSP,Filter,Listener,Tag等的软件环境
Servlet 生命周期的方法
以下方法都是由Servlet容器负责调用:
-
构造器:只有第一次请求Servlet时创建Servlet的实例,调用构造 器,Servlet是单实例的,非线程安全
-
init方法:对象只被调用一次,创建好实例后立即被调用,用于初 始化Servlet
-
service方法:每次请求都会调用service方法,实际用于响应请求
-
destroy方法:只被调用一次,web应用被卸载前调用,释放Servlet占用的资源
load-on-startup,指定Servlet被创建的时机
<!-- 配置和映射Servlet-->
<servlet>
<!-- Servlet注册名-->
<servlet-name>helloServlet</servlet-name>
<!-- Servlet全类名-->
<servlet-class>com.why.study2.servlet.HelloServlet</servlet-class>
<!-- 可以指定Servlet被创建的时机,数字越小越早该Servlet先被创建-->
<load-on-startup>1</load-on-startup>
</servlet>
ServletConfig对象
封装Servlet的配置信息,并且可以获取ServletContext对象
-
配置Servlet的初始化参数
<!-- 配置Servlet初始化参数,要放在<load-on-startup>之前-->
<init-param>
<!-- 初始化参数名-->
<param-name>password</param-name>
<!-- 初始化参数值-->
<param-value>1230</param-value>
</init-param>
<init-param>
<!-- 初始化参数名-->
<param-name>user</param-name>
<!-- 初始化参数值-->
<param-value>why</param-value>
</init-param> -
获取初始化参数
-
getInitParameter(String name):获取指定参数名的初始化参数
-
getInitParameterNames():获取参数名组成的Enumeration对象
String user = servletConfig.getInitParameter("user"); System.out.println("名字"+user); String password = servletConfig.getInitParameter("password"); System.out.println("密码"+password); Enumeration<String> initParameterNames = servletConfig.getInitParameterNames(); while (initParameterNames.hasMoreElements()){ String s = initParameterNames.nextElement(); System.out.println(s); }
-
-
获取Servlet配置名称
1. String servletName = servletConfig.getServletName(); System.out.println(servletName);
ServletContext接口
-
可由ServletConfig获取
-
该对象代表当前web应用,获取当前web应用的各种信息
-
获取当前web应用的初始化参数
配置当前web应用的初始化参数
<!-- 配置当前web应用的初始化参数--> <context-param> <param-name>driver</param-name> <param-value>com.mysql.jdbc.Driver</param-value> </context-param> <context-param> <param-name>jdbcUrl</param-name> <param-value>jdbc:mysql:///atguigu</param-value> </context-param>
获取参数
//获取ServletContext对象 ServletContext servletContext = servletConfig.getServletContext(); String driver = servletContext.getInitParameter("driver"); System.out.println(driver); Enumeration<String> initParameterNames1 = servletContext.getInitParameterNames(); while (initParameterNames1.hasMoreElements()){ String s = initParameterNames1.nextElement(); System.out.println(s);
-
获取当前某一web应用的服务器的绝对路径
//获取当前web应用服务器上发布的的绝对路径 String realPath = servletContext.getRealPath("HelloServlet.java"); System.out.println(realPath);
-
获取当前web应用的名称
//获取当前web应用服务器上发布的的绝对路径 String realPath = servletContext.getRealPath("HelloServlet.java"); System.out.println(realPath);
-
获取当前web应用对应的某一个文件的输入流
//获取文件输入流 InputStream resourceAsStream = servletContext.getResourceAsStream("WEB-INF/classes/a.properties"); System.out.println(resourceAsStream);
-
attribute相关的方法
HTTP协议 GET & POST 请求
-
GET请求
在浏览器输入某个url地址或点击一个超链接时,浏览器一定是get请求
“<form>”表单可设置get请求
使用get请求有限制,一般为1kb以下
-
POST请求
form表单指定为post请求时才可为post请求
文件上传必须使用post请求
ServletRequest,封装请求信息
其中主要代码写于service中,它用于应答每次的请求
-
根据提交参数返回提交的内容
String user = servletRequest.getParameter("user"); String password = servletRequest.getParameter("password"); System.out.println("user "+user+" password "+password);
-
根据请求参数名,返回请求参数返回对应的字符串
String[] interestings = servletRequest.getParameterValues("interesting"); System.out.println(Arrays.toString(interestings));
用于返回提交的多选框的内容
-
返回参数名对应的Enumeration对象,类似于ServletConfig(或ServletContext)
Enumeration<String> parameterNames = servletRequest.getParameterNames(); System.out.println(parameterNames);
-
返回请求参数的键值对,key——参数名,value——参数值,string数组类型
Map<String, String[]> parameterMap = servletRequest.getParameterMap(); System.out.println(parameterMap);
ServletResponse,封装响应信息
-
打印字符串到浏览器页面
PrintWriter writer = servletResponse.getWriter(); writer.println("hello java_web...");
-
设置响应类型
返回word类型,需要返回的类型可取tomcat的config目录下的web.xml文件中查找
servletResponse.setContentType("application/msword");
GenericServlet,定义一个普遍的Servlet,其余Servlet继承此类
由于Servlet接口中的方法很多都不需要,所有我们写一个新的GnericServlet类继承Servlet创建Servlet时只需继承GnericServlet即可
-
GenericServlet.java
package com.why.servlet; import javax.servlet.*; import java.io.IOException; public abstract class GenericServlet implements Servlet { //定义私有属性 private ServletConfig servletConfig; public GenericServlet() { } @Override public void init(ServletConfig servletConfig) throws ServletException { this.servletConfig = servletConfig; } @Override public ServletConfig getServletConfig() { //得到servletConfig return this.servletConfig; } @Override public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException ; @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
-
自定义的Servlet
package com.why.servlet; import javax.servlet.*; import java.io.IOException; public class LoginServlet extends GenericServlet{ public LoginServlet() { } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { String username = servletRequest.getParameter("username"); String password = servletRequest.getParameter("password"); String username1 = getServletConfig().getServletContext().getInitParameter("username"); String password1 = getServletConfig().getServletContext().getInitParameter("password"); if (username!=null&&username.equals(username1)&&password!=null&&password.equals(password1)){ servletResponse.getWriter().println(username); servletResponse.getWriter().println(password); servletResponse.getWriter().println("欢迎回来"+username+"!"); }else { servletResponse.getWriter().println("用户名或密码有误,请重新登录!"); } } }
HttpServlet
传统servlet不能很好区别post和get方法
package com.why.study2.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
JSP
JSP概述
-
动态网页,希望在浏览器页面中编写Java代码,简化Servlet
-
举例:
<%
-
JSP可放置在web应用除了WEB-INF中的任何目录下
-
JSP本质上是一个Servlet
JSP页面的9个隐含对象
-
PageContext pageContext = null; 配置页面上下文,可从该对象获取到其他八个隐含对象,也可获取到其他信息(自定义标签时使用);
-
HttpSession session = null;
-
ServletConfig config = null; 使用时需要映射jsp,同servlet
-
ServletContext application = null;
-
JspWriter out = null; 调用out.println(),可把字符串打印在浏览器页面上;
-
Object page = this; 指向当前JSP对应的Servlet对象的引用,几乎不使用;
-
request;
-
response,几乎不会使用。
使用<% %>编写代码在此位置,可用到这八个隐含对象(实际上还有exception隐含对象)
exception使用需要一定的条件,要有声明<%@ page isErrorPage="true" %>
隐含对象不需要声明即可使用
jsp换行可通过<% %>换行,可嵌套至html中
JSP指令
-
<%@page ... %> 定于一网页依赖属性,比如脚本语言、error页面、缓存需求等
一个JSP页面可包含多个page指令
语法格式:
<%
相关属性:
-
<%@ include ... %> 包含其他文件被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是该JSP文件的一部分,会被同时编译执行。
指令格式:
<%
-
<%@taglib ... %> 引入标签库定义。JSP API允许用户自定义标签,一个自定义标签库就是自定义标签的集合。
Taglib指令引入一个自定义标签集合的定义,包括库路径、自定义标签。
指令格式:
<%
JSP页面的请求的转发和重定向
本质区别:请求的撞飞只发出一次请求,重定向多次请求
-
转发
request.getRequestDispatcher("other.jsp").forward(request, response);
-
重定向
response.sendRedirect("other.jsp");
JSP域对象及其属性有关的方法
解决中文乱码问题
-
page指令字符编码集要支持中文
-
post请求request之前设置页面编码格式
request.setCharacterEncoding("UTF-8");
-
GET请求tomcat有问题
重新配置tomcat
MVC开发模式
MVC概述
Model-View-Controller,即为MVC。
-
Model层:包括业务处理层Service和数据访问层Dao。
Dao数据访问层主要是对数据库中一些操作地封装。
Service业务处理层主要是用作将从Controller层获取地数据和数据库的数据进行桥接,对复杂的业务逻辑进行处理,比如事务处理
-
Controller层:指控制部分,是对View层提交的请求为其设置对应的Servlet进行特定功能的处理,充当中介的作用
-
View层:视图部分,如jsp或html页面
不推荐跨层操作,各层之间耦合度要低,即独立性高
MVC模式开发web应用示例
创建工程,工程目录
创建数据库mvcproject
设计user表
entity包中创建User实体类
package com.why.study2.entity; import java.util.Date; import java.util.Objects; /** * 用户类 * @author why */ public class User { /** * 用户编号 */ private Integer id; /** * 用户名 */ private String username; /** * 用户密码 */ private String password; /** * 用户电话 */ private String phoneNo; /** * 用户地址 */ private String address; /** * 用户注册日期 */ private Date regDate; public User(Integer id, String username, String password, String phoneNo, String address, Date regDate) { this.id = id; this.username = username; this.password = password; this.phoneNo = phoneNo; this.address = address; this.regDate = regDate; } public User() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPhoneNo() { return phoneNo; } public void setPhoneNo(String phoneNo) { this.phoneNo = phoneNo; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Date getRegDate() { return regDate; } public void setRegDate(Date regDate) { this.regDate = regDate; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", phoneNo='" + phoneNo + '\'' + ", address='" + address + '\'' + ", regDate=" + regDate + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(id, user.id) && Objects.equals(username, user.username) && Objects.equals(password, user.password) && Objects.equals(phoneNo, user.phoneNo) && Objects.equals(address, user.address) && Objects.equals(regDate, user.regDate); } @Override public int hashCode() { return Objects.hash(id, username, password, phoneNo, address, regDate); } }
一定有做好注释等工作
添加c3p0需要的jar包和MySQL驱动的jar包
c3p0的配置
-
在src目录下创建c3p0-config.xml文件
-
配置 c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- This app is massive! --> <named-config name="mysql"> <!-- 连接MySQL基本的配置--> <property name="jdbcUrl">jdbc:mysql://localhost:3306/mvcproject?serverTimezone=Asia/Shanghai</property> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="user">root</property> <property name="password">root</property> <!-- 若数据库中的连接数量不足时,向数据库申请的连接数量--> <property name="acquireIncrement">5</property> <!-- 初始化数据库连接池时链接的数量--> <property name="initialPoolSize">10</property> <!-- 数据库连接池中最小的数据库链接数--> <property name="minPoolSize">5</property> <!-- 数据库连接池中最大的数据库链接数--> <property name="maxPoolSize">100</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <!-- c3p0数据库连接池可维护的Statement数量--> <property name="maxStatements">2</property> <!-- 每个连接同时可使用的Statement数量--> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config>
-
在Utils包下创建JdbcUtils工具类
-
编写JdbcUtils工具类
package com.why.study2.utils; import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; /** * jdbc工具类 * * @author why */ public class JdbcUtils { //数据库连接池,C3P0 private static DataSource dataSource = null; static {//静态代码块只会被执行一次 dataSource = new ComboPooledDataSource(); } /** * 获取到mysql的数据库连接对象 * * @return conn */ public static Connection getConnection(){ Connection conn = null; try { conn = dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 通用的关闭数据库连接对象的方法 * @param conn */ public static void closeConn(Connection conn){ if (conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
创建测试类JdbcUtilsTest.java
package com.why.study2.test; import com.why.study2.utils.JdbcUtils; import org.junit.jupiter.api.Test; import java.sql.Connection; import static org.junit.jupiter.api.Assertions.*; class JdbcUtilsTest { @Test void getConnection() { Connection connection = JdbcUtils.getConnection(); System.out.println(connection); } }
dao层开发
创建BaseDao.java
实现基本的增删改查操作
package com.why.study2.dao; import com.why.study2.utils.JdbcUtils; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * 这是一个dao层中的基本类,在于被具体的dao类继承,不能直接new BasesDao()来直接使用 * * @author why * @param <T> 针对要操作各章数据包映射到java工程里的java类 */ public class BaseDao<T> { QueryRunner queryRunner = new QueryRunner(); private Class<T> Clazz; /** * 反射拿到T.class */ public BaseDao() { //用BaseDao的构造器初始化aClass属性 //拿到User类 Type superType = this.getClass().getGenericSuperclass();//getGenericSuperclass()拿到调用者的父类的类型 //拿到User.class if (superType instanceof ParameterizedType){ ParameterizedType pt = (ParameterizedType) superType; Type[] tarry = pt.getActualTypeArguments();//返回类型数组,其第一个元素是我们需要的T.class if (tarry[0] instanceof Class){ Clazz = (Class<T>) tarry[0]; } } } /** * 查询数据表,取出结果sql语句的结果集的第一条数据,封装成一个类对象返回,不支持事务 * 用到dbutils工具类 * @param sql * @param args * @return */ public T get(String sql,Object... args){ Connection conn = null; T entity = null; //拿到conn try { conn = JdbcUtils.getConnection(); entity = queryRunner.query(conn,sql, new BeanHandler<T>(Clazz),args); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtils.closeConn(conn); } return entity; } /** * 重写查询数据表方法,取出结果sql语句的结果集的第一条数据,封装成一个类对象返回,支持事务 * @param sql * @param args * @return */ public T get(Connection conn,String sql,Object... args){ T entity = null; try { entity = queryRunner.query(conn,sql, new BeanHandler<T>(Clazz),args); } catch (Exception e) { e.printStackTrace(); } finally { } return entity; } /** * 获取多条记录的通用方法 * @return */ List<T> getList(String sql,Object... args){ Connection conn = null; List<T> list = null; //拿到conn try { conn = JdbcUtils.getConnection(); list = queryRunner.query(conn,sql, new BeanListHandler<T>(Clazz),args); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtils.closeConn(conn); } return list; } /** * 实现insert,update,delete通用的更新方法 * @param sql * @param args * @return */ int update(String sql,Object... args){ Connection conn = null; int rows = 0; //拿到conn try { conn = JdbcUtils.getConnection(); rows = queryRunner.update(conn,sql,args); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtils.closeConn(conn); } return rows; } /** * 通用的sql语句的结果只有一个数值的类型的查询,用户个数或其他计数 * @param sql * @param args * @return */ Object getValue(String sql,Object... args){ Connection conn = null; Object obj = null; //拿到conn try { conn = JdbcUtils.getConnection(); obj = queryRunner.query(conn,sql, new ScalarHandler<>(),args); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtils.closeConn(conn); } return obj; } }
创建UserDao接口
package com.why.study2.dao; import com.why.study2.entity.User; import java.sql.Connection; import java.util.List; /** * 接口制定规则,只定义方法但不实现 * UserDao只定义与User数据表有关的方法 * * @author why */ public interface UserDao { /** * 实现插入一条用户数据 * @param user * @return */ int save(User user); /** * 根据用户编号删除用户 * @param id * @return */ int deleteUserById(int id); /** * 根据id更新用户数据 * @param user * @return */ int updateUserById(User user); /** * 根据用户id获取用户信息,支持事务 * @param id * @return */ User get(int id); /** * 支持事务 * @param conn * @param id * @return */ User get(Connection conn,int id); /** * 获取所有用户数据 * @return */ List<User> getListAll(); /** * 查询指定用户名的人有多少人 * @param username * @return */ long getCountByName(String username); /** * dao层实现模糊查询的方法 * @param username * @param address * @param phoneNo * @return */ List<User> query(String username, String address, String phoneNo); }
UserDao实现类
package com.why.study2.dao; import com.why.study2.entity.User; import java.sql.Connection; import java.util.List; public class UserDaoImpl extends BaseDao<User> implements UserDao { @Override public int save(User user) { String sql = "INSERT INTO user(`username`,`password`,`phone_no`,`address`,`reg_date`) VALUES(?,?,?,?,?);"; return super.update(sql,user.getUsername(),user.getPassword(),user.getPhoneNo(),user.getAddress(),user.getRegDate()); } @Override public int deleteUserById(int id) { String sql = "delete from user where id = ?"; return super.update(sql,id); } @Override public int updateUserById(User user) { String sql = "update user set username = ?,password = ?,phone_no = ?,address = ? where id = ?"; return super.update(sql,user.getUsername(),user.getPassword(),user.getPhoneNo(),user.getId()); } /** * 不支持事务 * @param id * @return */ @Override public User get(int id) { String sql = "select `id`,`username`,`password`,`phone_no` phoneNo,`address`,`reg_date` regDate FROM user WHERE `id`=?;"; User user = super.get(sql, id); return user; } /** * 支持事务 * @param conn * @param id * @return */ @Override public User get(Connection conn, int id) { String sql = "select `id`,`username`,`password`,`phone_no` phoneNo,`address`,`reg_date` regDate FROM user WHERE `id`=?;"; return super.get(conn,sql,id); } @Override public List<User> getListAll() { String sql = "select `id`,`username`,`password`,`phone_no` phoneNo,`address`,`reg_date` regDate from user"; return super.getList(sql); } @Override public long getCountByName(String username) { String sql = "SELECT COUNT(id) FROM user WHERE username = ?;"; return (long) super.getValue(sql,username); } /** * 拼接sql语句存在sql注入的风险 * @param username * @param address * @param phoneNo * @return */ @Override public List<User> query(String username, String address, String phoneNo) { System.out.println(username); System.out.println(address); System.out.println(phoneNo); String sql = "SELECT id,username,password,phone_no phoneNo,address,reg_date regDate FROM user WHERE 1=1"; if (username!=null&&!"".equals(username)){ sql = sql + " AND username like '%"+username+"%'"; } if (address!=null&&!"".equals(address)){ sql = sql + " AND address like '%"+address+"%'"; } if (phoneNo!=null&&!"".equals(phoneNo)){ sql = sql + " AND phone_no like '%"+phoneNo+"%'"; } System.out.println(sql); return super.getList(sql); } }
创建FactoryDao
降低耦合度,dao层修改service及其他层不用修改
package com.why.study2.dao; /** * 工厂类 * 降低耦合度 */ public class FactoryDao { /** * 返回Dao层对象 * @return */ public static UserDao getUserDao(){ return new UserDaoImpl(); } }
业务(Service)层开发
创建UserService接口及其实现类
接口Userservice.java
package com.why.study2.service; import com.why.study2.entity.User; import java.sql.Connection; import java.util.List; public interface UserService { /** * 实现插入一条用户数据 * @param user * @return */ int save(User user); /** * 根据用户编号删除用户 * @param id * @return */ int deleteUserById(int id); /** * 根据id更新用户数据 * @param user * @return */ int updateUserById(User user); /** * 根据用户id获取用户信息,支持事务 * @param id * @return */ User get(int id); /** * 支持事务 * @param id * @return */ User getTransaction(int id); /** * 获取所有用户数据 * @return */ List<User> getListAll(); /** * 查询指定用户名的人有多少人 * @param username * @return */ long getCountByName(String username); /** * 这是用户模糊查询的方法 * @param username * @param address * @param phoneNo * @return */ List<User> query(String username, String address, String phoneNo); }
实现类UserServiceImpl.java
package com.why.study2.service.impl; import com.why.study2.dao.FactoryDao; import com.why.study2.dao.UserDao; import com.why.study2.dao.UserDaoImpl; import com.why.study2.entity.User; import com.why.study2.service.UserService; import com.why.study2.utils.JdbcUtils; import jdk.nashorn.internal.runtime.regexp.JoniRegExp; import java.sql.Connection; import java.sql.SQLException; import java.util.List; public class UserServiceImpl implements UserService { UserDao userDao = FactoryDao.getUserDao(); @Override public int save(User user) { return userDao.save(user); } @Override public int deleteUserById(int id) { return userDao.deleteUserById(id); } @Override public int updateUserById(User user) { return userDao.updateUserById(user); } @Override public User get(int id) { return userDao.get(id); } @Override public User getTransaction(int id) { Connection conn = null; User user = null; try { conn = JdbcUtils.getConnection(); conn.setAutoCommit(false); user = userDao.get(conn,id); conn.commit(); } catch (SQLException e) { e.printStackTrace(); JdbcUtils.rollbackTransaction(conn); } finally { } return user; } @Override public List<User> getListAll() { return userDao.getListAll(); } @Override public long getCountByName(String username) { return userDao.getCountByName(username); } @Override public List<User> query(String username, String address, String phoneNo) { return userDao.query(username,address,phoneNo); } }
Controller层开发
实现控制转发的功能
package com.why.study2.service; import com.why.study2.entity.User; import java.sql.Connection; import java.util.List; public interface UserService { /** * 实现插入一条用户数据 * @param user * @return */ int save(User user); /** * 根据用户编号删除用户 * @param id * @return */ int deleteUserById(int id); /** * 根据id更新用户数据 * @param user * @return */ int updateUserById(User user); /** * 根据用户id获取用户信息,支持事务 * @param id * @return */ User get(int id); /** * 支持事务 * @param id * @return */ User getTransaction(int id); /** * 获取所有用户数据 * @return */ List<User> getListAll(); /** * 查询指定用户名的人有多少人 * @param username * @return */ long getCountByName(String username); /** * 这是用户模糊查询的方法 * @param username * @param address * @param phoneNo * @return */ List<User> query(String username, String address, String phoneNo); }
View试图层开发
index.jsp
<%@ page import="java.util.Date" %> <%@ page import="java.io.PrintWriter" %> <%@ page import="com.why.study2.entity.User" %> <%@ page import="java.util.List" %><%-- Created by IntelliJ IDEA. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>index</title> <style type="text/css"> tr{ height: 40px; } td{ padding: 10px; } </style> </head> <body> <form action="<%=request.getContextPath()%>/query.udo" method="post"> <table style="margin: 100px;padding: 50px;border: 1px #ccc solid; width: 400px"> <tr> <td style="text-align: right">用户名:</td> <td style="text-align: left"><input type="text" name="username"></td> </tr> <tr> <td style="text-align: right">用户地址:</td> <td style="text-align: left"><input type="text" name="address"></td> </tr> <tr> <td style="text-align: right">用户电话:</td> <td style="text-align: left"><input type="text" name="phoneNO"></td> </tr> <tr> <td colspan="2" style="text-align:center"> <input type="submit" value="查询用户"> </td> </tr> <tr> <td colspan="2" style="text-align:center"> <a href="<%=request.getContextPath()%>/add.jsp">注册新用户</a> </td> </tr> </table> </form> <table style="margin-left: 100px; padding: 50px;" border="1" cellpadding="0" cellspacing="0"> <tr> <td>用户ID</td> <td>用户姓名</td> <td>用户密码</td> <td>用户电话</td> <td>用户地址</td> <td>注册日期</td> <td>操作记录</td> </tr> <% List<User> list = (List<User>) request.getAttribute("userList"); System.out.println("jsp"+list); if (list!=null && list.size()>0){ for (User user : list) { %> <tr> <td><%=user.getId()%></td> <td><%=user.getUsername()%></td> <td><%=user.getPassword()%></td> <td><%=user.getPhoneNo()%></td> <td><%=user.getAddress()%></td> <td><%=user.getRegDate()%></td> <td><a href="<%=request.getContextPath()%>update.udo?id=<%=user.getId()%>">编辑</a> | <a href="<%=request.getContextPath()%>delete.udo?id=<%=user.getId()%>">删除</a></td> </tr> <% } } %> </table> </body> </html>
error.jsp
<%-- Created by IntelliJ IDEA. User: why Date: 2020/7/22 Time: 11:52 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>error</title> </head> <body> 出错了,操作失败!!! </body> </html>
add.jsp
<%-- Created by IntelliJ IDEA. User: why Date: 2020/7/22 Time: 11:42 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>add</title> <style type="text/css"> tr{ height: 40px; } td{ padding: 10px; } </style> </head> <body> <form action="<%=request.getContextPath()%>/add.udo" method="post"> <table style="margin: 100px;padding: 50px;border: 1px #ccc solid; width: 400px"> <tr> <td style="text-align: right">用户名:</td> <td style="text-align: left"><input type="text" name="username"></td> </tr> <tr> <td style="text-align: right">用户密码:</td> <td style="text-align: left"><input type="text" name="password"></td> </tr> <tr> <td style="text-align: right">用户地址:</td> <td style="text-align: left"><input type="text" name="address"></td> </tr> <tr> <td style="text-align: right">用户电话:</td> <td style="text-align: left"><input type="text" name="phoneNO"></td> </tr> <tr> <td colspan="2" style="text-align:center"> <input type="submit" value="注册用户"> </td> </tr> </table> </form> </body> </html>
web.xml配置文件
Cookie
Cookie概述
会话
把同一浏览器与web服务器的一次一系列的各种交互称为会话
对会话的跟踪
Cookie机制:放在客户端
Session机制:放在服务器端
Cookie运行过程
-
客户端第一次向服务器端http请求,无cookie
-
服务端设置客户端Cookie
-
再次访问服务端器 ,带Cookie标志
-
针对性响应
服务器通过操作 Cookie类对象
对客户端Cookie进行操作。
response.addCookie(Cookie cookie)向客户端设置Cookie
request.getCookie()获取客户端提交的所有Cookie,以Cookie[]数组形式返回
Cookie属性
//cookie名
private final String name;
//cookie值
private String value;
//cookie版本
private int version = 0;
//该cookie的用处说明
private String comment;
//设置访问域名,若设置为.google.com,则所有以.goole.com结尾的域名都可访问
private String domain;
//cookie失效时间,如果为正数则Cookie在>maxAge秒之后失效,若为负数,关闭浏览器时失效
private int maxAge = -1;
//Cookie的使用路径。如果设置为/sessionWeb/在,则只有contextPath为/sessionWeb的程序可访问,若设置为/,则本域名下contextPath都可访问,注意:最后一个字符必须为/
private String path;
//cookie是否仅使用安全协议传输,默认false
private boolean secure;
这些属性都可用seter&geter方法设置和获取
JS操作Cookie的函数
通过JS控制Cookie的设置,获取和删除
<script type="text/javascript">
//js对Cookie的操作,设置,获取,删除Cookie
//设置Cookie,c_expiredays失效时间,单位:天。c_name,c_value,必填,c_expiredays选填
function setCookie(c_name,c_value,c_expiredays) {
var expires = "";
if(c_expiredays != null){
//获得系统时间
var sysDate = new Date();
//浏览器页面弹窗打印
alert(sysDate.toUTCString());
//设置时间当前时间加传送的时间
sysDate.setDate(sysDate.getDate()+c_expiredays);
alert(sysDate.toUTCString());
expires = ";expires="+sysDate.toUTCString();
alert(expires);
}
//设置cookie
document.cookie = c_name + "=" + escape(c_value) + expires;
}
alert(document.cookie);
//获取cookie,通过Cookie名获取Cookie值
function getCookie(c_name) {
//判断是否有cookie
//cookie形式 ssid = abc
if (document.cookie.length>0){
//通过子字符串的截取
//开始截取的位置索引
var start = document.cookie.indexOf(c_name + "=");
start = start + c_name.length+1;
var end = document.cookie.indexOf(";",start);
if (end == -1){
end = document.cookie.length;
}
var val = document.cookie.substring(start,end);
return unescape(val);
}
}
alert(getCookie(ssid));
//删除cookie
function deleteCookie(c_name) {
//设置Cookie失效时间是比当前时间更早的时间删除Cookie
var sysDate = new Date();
sysDate.setDate(sysDate.getDate()-1);
var time = ";expires="+sysDate.toUTCString();
var val = getCookie(c_name);
document.cookie = c_name+"="+escape(val)+time;
}
deleteCookie(ssid);
</script>
Cookie实现用户登录
Cookie可记录用户登录状态
dao层开发
/** * 实现根据用户名和密码查询用户记录的方法 * @param username * @param password * @return */ User getUserByUp(String username, String password);
@Override public User getUserByUp(String username, String password) { String sql = "SELECT id,username,password,phone_no phoneNo,address,reg_date regDate FROM user WHERE username=? and password=?;"; User user = super.get(sql, username, password); return user; }
Service开发
/** * 判断登录是否成功 * @param username * @param password * @return */ User login(String username, String password);
@Override public User login(String username, String password) { return userDao.getUserByUp(username,password); }
工具类开发
CookieUtils.java
package com.why.study2.utils; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.security.MessageDigest; import java.util.Random; public class CookieUtils { /** * 命令浏览器创建Cookie文件的方法 * @param username : 放到Cookie信息的用户名 * @param req * @param resp : 调用Cookie方法的response对象 * @param sec : 设置Cookie失效时间,单位是秒 */ public static void creatCookie(String username, HttpServletRequest req,HttpServletResponse resp,int sec){ //创建第一个Cookie,标记是userkey,值为username Cookie userCookie = new Cookie("userKey",username); //创建第二个Cookie,标记是ssid,值为加密方法,此处用ssid保存加密后的用户名,Controller取出比较验证 Cookie ssidCookie = new Cookie("ssid",md5Encrypt(username)); /** * 设置有效期 */ userCookie.setMaxAge(sec); ssidCookie.setMaxAge(sec); /** * 调用添加Cookie */ resp.addCookie(userCookie); resp.addCookie(ssidCookie); } /** * 对明文字符串进行加密 * @param ss : 被加密的明文 * @return */ public static String md5Encrypt(String ss) { Random random = new Random(); int i1 = random.nextInt(100); System.out.println("随机数:"+i1); String str1 = createStr(i1); System.out.println("密钥:"+str1); ss = ss==null?"":ss+str1; //加密字典 char[] md5Digist = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] ssarr = ss.getBytes(); md.update(ssarr);//把明文放入加密类MessageDigest的对象实例中去,更新数据 byte[] digest = md.digest();//加密 int len = digest.length; char[] str = new char[2*len]; int k = 0;//计数 for (int i = 0; i <len ; i++) { byte b = digest[i]; //>>> 无符号位移右移n位,其余填充0 //b >>> 4 & 0xf,此处是b右移四位和0xf做与运算,运算结果是0~15 str[k++] = md5Digist[b >>> 4 & 0xf]; str[k++] = md5Digist[b & 0xf]; } System.out.println("密文:"+new String(str)); return new String(str); }catch (Exception e){ e.printStackTrace(); } return null; } /** * 随机生成密钥 * @param length * @return */ public static String createStr(int length){ String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(62); sb.append(str.charAt(number)); } System.out.println(sb.toString()); return sb.toString(); } }
Controller开发
/** * 用户登录方法 * @param req * @param resp * @throws ServletException * @throws IOException */ private void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ //第一步,拿到三个参数 String username = req.getParameter("username"); String password = req.getParameter("password"); String expiredays = req.getParameter("expiredays"); Cookie[] cookies = req.getCookies(); boolean login = false;//是否登陆的标记 String account = null;//登录的账号 String ssid = null;//这是一个标记,通过cookie拿到的一个判断用户该不该登录成功的标记 if (cookies!=null && cookies.length>0){ for (Cookie cookie: cookies) { if (cookie.getName().equals("userKey")){ account = cookie.getValue(); } if (cookie.getName().equals("ssid")){ ssid = cookie.getValue(); } } } if (account!=null && ssid != null){ login = ssid.equals(CookieUtils.md5Encrypt(username)); System.out.println(CookieUtils.md5Encrypt(username)); } //login时false取反变成true,表示用户未登录,第一次访问 if (!login){ //查询数据库的用户名和密码,判断用户的用户名和密码是否和输入一致 User user = userService.login(username,password);//登录成功,返回对应的User对象,登录失败,返回null if (user !=null){ //对的,登陆成功 //设置失效时间 expiredays = expiredays == null?"":expiredays; switch (expiredays){ case "7"://选择了记住我一周 //创建Cookie对象,设置失效时间为7天 CookieUtils.creatCookie(username,req,resp,7*24*60*60); break; case "30": //创建Cookie对象,设置失效时间为30天 CookieUtils.creatCookie(username,req,resp,30*24*60*60); break; case "100": //创建Cookie对象,设置没有失效时间 CookieUtils.creatCookie(username,req,resp,Integer.MAX_VALUE); break; default: //默认时创建Cookie对象,设置失效时间为-1,关闭浏览器就失效 CookieUtils.creatCookie(username,req,resp,-1); break; } //登录成功,准许客户进入到main.jsp页面 req.getRequestDispatcher("/main.jsp").forward(req,resp); }else { req.setAttribute("note","用户名或密码错误!!!"); req.getRequestDispatcher("/login.jsp").forward(req,resp); } }else { req.getRequestDispatcher("/main.jsp").forward(req,resp); } } }
View层开发
<%--
Created by IntelliJ IDEA.
User: why
Date: 2020/7/23
Time: 12:07
To change this template use File | Settings | File Templates.
--%>
<%