【无标题】

Servlet

本身启动tomcat打开的是webapp/WEB-INF/index.jsp静态的文件,若在web-xml文件中加入servlet,并进行mapping映射,在映射中起名,映射的请求路径,tomcat会走动态页面流程,通过url加入网址为进入口,mapping中的name进行链接servlet,在serevlet中的class进入类中,识别是否继承HttpServlet,之后进行doget方法进行返回页面状态(初期个人理解)

Servlet接口sun公司有两个默认的实现类:httpservlet,GenericServlet

Servlet:把实现了servlet接口的java程序叫做servlet

1.2、helloservlet

1.构建一个普通的maven项目,删除里面的src目录,以后学习就用该项目里建立moudle,这个空的工程就是maven主工程

2.关于maven父子工程的理解:

父项目中会有:

<modules>

    <module>servlet-01</module>

</modules>

子项目中会有:

<parent>

    <artifactId>javaweb-02-servlet</artifactId>

    <groupId>com.cheng</groupId>

    <version>1.0-SNAPSHOT</version>

</parent>

父项目中的java子项目可以直接使用

3.编写一个servlet程序

         1.编写一个普通类

         2.实现servlet接口,这里我们直接继承httpservlet

一个类写好

public class HelloServlet extends HttpServlet {





    //由于get或者post只是请求实现的不同方式,可以互相调用,业务逻辑都一样

    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



        //ServletOutputStream outputStream = resp.getOutputStream();

        PrintWriter writer = resp.getWriter();//响应流



        writer.print("hello,servlet");

    }



    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        doGet(req, resp);

    }

}

5.编写servlet映射

6.编写servlet的映射

         为什么需要映射:我们写的是java程序,但是要通过浏览器访问,而浏览器需要链接web服务器,所以我们需要在web服务器中注册我们写的servlet,还需给他一个刘侃奇能够访问的路径;

<!--注册servlet-->

    <servlet>

        <servlet-name>hello</servlet-name>

        <servlet-class>com.cheng.servlet.HelloServlet</servlet-class>

    </servlet>

<!--servlet的请求路劲-->

    <servlet-mapping>

        <servlet-name>hello</servlet-name>

        <url-pattern>/hello</url-pattern>

    </servlet-mapping>

7、配置toncat

8、servlet原理

         从浏览器发出请求到web容器,web容器将rqquest请求在servlet接口的service类的servicerequest方法处理,并作出响应在传回response到web容器中,web容器在返回黑页面

6.4、mapping的问题

1.一个servlet可以指定一个映射路径<url-pattern>/hello</url-pattern>

2.一个servlet可以指定对个映射的路径<url-pattern>/hello</url-pattern>或者<url-pattern>/hello1</url-pattern>或者<url-pattern>/hello3</url-pattern>都可以

3.一个servlet可以指定通用映射路径<url-pattern>/hello/*</url-pattern>

4.默认路径<url-pattern>/*</url-pattern>

5.指定一些后缀或者前缀等等。。。。<url-pattern>*/cheng</url-pattern>

         6.优先级问题

         指定了固有的映射路径优先级最该高,如果找不到就会走默认的处理请求

6.5、ServletContext共享数据

Web容器在启动的时候,他会为每个web应用都创建一个对应的servletcontext对象,它代表了当前的web应用;

Getinitparameter()   初始化参数

Getservletconfig()    servlet配置

Getservletcontext()   servlet上下文

第一个web写入

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
ServletContext servletContext = this.getServletContext();
   
String username="cheng";
   
servletContext.setAttribute("username",username);//将一个数据保存在了ServletContext

}

第二个web使用

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().print("名字"+username);
}

转发

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
ServletContext context = this.getServletContext();
   
System.out.println("进入了方法");


   
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的请求路径
   
requestDispatcher.forward(req,resp);//调用forward实现请求转发

}

转发就是A需要资源,而C有,A问B要,B从C那拿过来再给A

重定向是A需要资源,而C有,A问B要,B说C有让A去C那拿,于是A去C那拿了

这也就是问什么转发的url没变化,重定向url会发生变化

4、读取资源文件

Properties

  1. 在java目录下新建properties
  2. 在resources目录下新建properties

发现:都被打包到了一个路径下:classes,我们俗称这个路径为classpath

思路:需要一个文件流

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/cheng/servlet/aa.properties");

   
Properties prop = new Properties();
   
prop.load(is);
   
String user = prop.getProperty("username");
   
String pwd = prop.getProperty("password");

   
resp.getWriter().print(user+":"+pwd);
}

6.6、HttpServletResponse

Web服务器接收到客户端的其请求,针对请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse对象

  1. 如果要获取客户端请求过来的参数:找HttpServletRequest
  2. 如果要给客户端响应一些信息:找HttpServletResponse

2、常见应用

       1.向浏览器输出信息()

       2.下载文件

              1.要获取下载文件的路径

              2.下载的文件名

              3.设置想办法让浏览器能够支持下载需要的东西

              4.获取下载文件的输入流

              5.创建缓冲区

              6.获取OutputStream对象

              7.将FileOutputStream流写入到buffer缓冲区

              8.使用OutputStream将缓冲区中的数据输出到客户端

    @Override
   
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1.要获取下载文件的路径
       
String realPath ="F:\\idea文件作业\\javaweb-02-servlet\\response\\target\\classes\\1.JPG";
       
System.out.println("要获取下载文件的路径"+realPath);
//        2.下载的文件名
       
String substring = realPath.substring(realPath.lastIndexOf("//") + 1);
//        3.设置想办法让浏览器能够支持(Content-disposition)下载需要的东西
       
resp.setHeader("Content-disposition","attachment;filename="+URLEncoder.encode(substring,"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){
           
out.write(buffer,0,len);
       
}
       
in.close();
       
out.close();

   
}

3、验证码功能

  1. 前端实现
  2. 后端实现,需要用到java的图片类,生成一个图片
  3. @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       
    //如何让浏览器五秒刷新一次
       
    resp.setHeader("refresh","0.5");

       
    //在内存中创建图片
       
    BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
       
    //得到图片
       
    Graphics2D g = (Graphics2D) image.getGraphics();//
        //设置图片背景颜色
       
    g.setColor(Color.blue);
       
    g.fillRect(0,0,80,20);
       
    //给图片写数据
       
    g.setColor(Color.black);
       
    g.setFont(new Font(null,Font.BOLD,20));
       
    g.drawString(makeNum(),0,20);

       
    //告诉浏览器,这个请求用图片的方式打开
       
    resp.setContentType("image/jpeg");
       
    //网站存在缓存,不让浏览器缓存
       
    resp.setDateHeader("expires",-1);
       
    resp.setHeader("Cache-Control","no-cache");
       
    resp.setHeader("Pragma","no-cache");

       
    //把图片写给浏览器
       
    ImageIO.write(image, "jpg", resp.getOutputStream());

    }

4、重定向

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


   
resp.sendRedirect("/image");//重定向

}

6.7、HttpServletRequest

1.获取前端传入的参数

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
//后台接收中文乱码问题
   
req.setCharacterEncoding("utf-8");

   
String username = req.getParameter("username");
   
String password = req.getParameter("password");
   
String[] hobbys = req.getParameterValues("hobbys");



   
System.out.println(username+":"+password);
   
System.out.println(Arrays.toString(hobbys));

   
//通过请求转发
   
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}

7、cookie、session

会话:用户打开一个浏览器,点击或访问web资源,然后关闭浏览器,这个过程称为会话;

有状态会话:证明客户端曾经浏览过该网页称之为有状态会话

客户端          服务端

  1. 服务端给客户端一个信件,客户端下次访问服务器带上信息就可以;cookie
  2. 服务器登记客户端来过,下次客户端在来,服务端就进行匹配该客户端;session

7.2、保存会话的两种技术

Cookie

客户端技术(响应,请求)

Session

服务器技术,保存用户会话信息

7.3、cookie

1.从请求中拿到cookie信息

2.服务器响应给客户端cookie

req.getCookies();//获得cookie

cookie.getName();//获得cookie中的key

cookie.getValue();//获得cookie中的value

new Cookie("lastlogintime",System.currentTimeMillis()+"");新建一个cookie

cookie.setMaxAge(24*60*60);设置cookie有效期

resp.addCookie(cookie);响应给客户端一个cookie

7.4、Session(重点)

什么是session:

  1. 服务器会给每一个用户(浏览器)创建一个session对象
  2. 一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在
  3. 用户登录之后,整个网站它都可以进行访问!->保存用户的信息;保存购物车的信息
  4. //得到session
    HttpSession session = req.getSession();
    //给session中存东西
    session.setAttribute("name",new Person("程",1));

    //获取session的ID
    String sessionid = session.getId();

    //判断session是不是新创建的
    if (session.isNew()){
       
    resp.getWriter().write("session创建成功,session的ID为:"+sessionid);
    }else {
       
    resp.getWriter().write("session已经在服务器存在了,session的ID为:"+sessionid);
    }
  5. //得到session
    HttpSession session = req.getSession();

Session的注销

HttpSession session = req.getSession();
session.removeAttribute("name");
session.invalidate();//注销

会话自动过期在web.xml中配置

<session-config>
   
<!--1分钟后session失效-->
   
<session-timeout>1</session-timeout>
</
session-config>

Session和cookie的区别:

  1. Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  2. Session把用户的数据写到用户独占session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
  3. Session对象有服务器创建

8、JSP

8.1、什么是SJP

Java server pages:java服务器端页面,也和servlet一样,用于动态web技术!

最大的特点:

  1. HTML只给用户提供静态的数据
  2. JSP页面可以嵌入java代码,为用户提供动态数据

8.2、JSP原理

JSP本质上就是一个servlet

用户通过电脑发送请求道服务器调取页面,服务器在web容器中将JSP最终转换为class给服务器在,服务器在响应给用户

在JSP页面中:

只要是JAVA代码就会原封不动的输出;

如果是HTML代码,就会转换成:

Out.write(“<html>\r\n”)

这样的格式输出到前端

8.3、JSP基础语法


<%--JSP表达式:
  作用:用来将程序的输出,输出到客户端
  公式:
  <%=变量或表达式%>
  --%>

<%=new java.util.Date()%>

脚本片段

<%
int sum=0;
  for
(int i = 1; i <=100; i++) {
   
sum+=i;
 
}
 
out.println("<h1>Sum="+sum+"</h1>");

%>

JSP的注释,不会在客户端显示,HTML就会

8.4、JSP指令

<%@page errorPage="error/500.jsp" %>定制错误页面

<%@include file=""%>抽取网页固定部分

Jsp语法

<%@include file="common/header.jsp"%>
<h1>主体</h1>
<%@
include file="common/footer.jsp"%>

<hr>
<
jsp:include page="/common/header.jsp"></jsp:include>
<h1>主体</h1>
<
jsp:include page="common/footer.jsp"></jsp:include>

8.5、9大内置对象

  1. PageContext用于存东西
  2. Request用于存东西
  3. Response
  4. Session可以存东西
  5. Application[ServletContext]用于存东西
  6. Config[ServletConfig]
  7. Out
  8. Page
  9. exception

pageContext.setAttribute("name1","程1");//保存的数据只在一个页面中有效
request.setAttribute("name2","程2");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","程3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","程4");//保存的数据只在服务器中有效,从打开服务器到关闭服务器

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,例如:新闻,用户看完就没用了

session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据

8.6、JSP标签,JSTL标签,EL表达式

导入所用包

<!-- JSTL表达式的依赖 -->
<dependency>
    <
groupId>javax.servlet.jsp.jstl</groupId>
    <
artifactId>jstl-api</artifactId>
    <
version>1.2</version>
</
dependency>

<!-- standard标签库 -->
<dependency>
    <
groupId>taglibs</groupId>
    <
artifactId>standard</artifactId>
    <
version>1.1.2</version>
</
dependency>

EL表达式:${}

  1. 获取对象
  2. 执行运算
  3. 获取web开发的常用对象
  4. 调用java方法

JSP标签

<%request.setCharacterEncoding("utf-8");%>
<%--<jsp:include page=""></jsp:include>--%>

<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name1" value="程1"></jsp:param>
    <jsp:param name="name2" value="程2"></jsp:param>
</jsp:forward>

JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和java代码一样

<c:out>       用于在JSP中显示数据,就像<%= ... >

<c:set> 用于保存数据

<c:remove>      用于删除数据

<c:catch>   用来处理产生错误的异常状况,并且将错误信息储存起来

<c:if>    与我们在一般程序中用的if一样

<c:choose>       本身只当做<c:when>和<c:otherwise>的父标签

<c:when>   <c:choose>的子标签,用来判断条件是否成立

<c:otherwise>  <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行

<c:import> 检索一个绝对或相对 URL,然后将其内容暴露给页面

<c:forEach>      基础迭代标签,接受多种集合类型

<c:forTokens>  根据指定的分隔符来分隔内容并迭代输出

<c:param> 用来给包含或重定向的页面传递参数

<c:redirect>      重定向至一个新的URL.

<c:url> 使用可选的查询参数来创造一个UR

JSTL标签的使用步骤

  1. 引入对应的taglib
  2. 使用其中的方法
  3. 在Tomcat也要引入jstl的包,否则会报错:jstl解析错误
  4. <h1>测试</h1>

    <
    form action="coreif.jsp" method="get">
       
    <%--
            EL
    表达式获取表单中的数据
            ${param.参数名}
        --%>
       
    <input type="text" name="username" value="${param.username}">
            <
    input type="submit" value="登录">

    </
    form>

    <
    c:if test="${param.username=='admin'}" var="isAdmin">
        <c:out value="管理员欢迎"/>

    </c:if>
    <c:out value="${isAdmin}"/>

判断


<%--定义一个变量score,值为85--%>
<c:set var="score" value="85"/>

<c:choose>
    <c:when test="${score>=90}">
        <h1>你的成绩优秀</h1>
    </
c:when>
    <c:when test="${score>=80}">
        <h1>你的成绩优秀</h1>
    </
c:when>
    <c:when test="${score>=70}">
        <h1>你的成绩优秀</h1>
    </
c:when>
    <c:when test="${score<=60}">
        <h1>你的成绩优秀</h1>
    </
c:when>

</c:choose>

C:Foreach


<%
   
ArrayList<String> people = new ArrayList<>();
   
people.add(0,"一");
   
people.add(1,"二");
   
people.add(2,"四");
   
people.add(3,"五");
   
request.setAttribute("list",people);
%>


<%--
var,
每一次遍历的对象
items,要遍历的对象
--%>

<c:forEach var="people" items="${list}">
    <c:out value="${people}"/><br>

</
c:forEach>


<hr>
<%--
var,
每一次遍历的对象
items,要遍历的对象
begin,从那个开始
end,到哪为止
step,步长
--%>

<c:forEach var="people" items="${list}begin="1" end="2" step="2">
    <c:out value="${people}"/><br>

</
c:forEach>

9、JavaBean

实体类

JavaBean有特定的想法:

  1. 必须要有一个无参构造
  2. 属性必须私有
  3. 必须有对应的get/set方法

一般用来和数据库字段做映射         ORM

ORM:对象关系映射

  1. 表----à类
  2. 字段-----à属性
  3. 行纪录-----à对象

10、MVC三层架构

什么是MVC:Model  view  Controller  模型、视图、控制器

Model

  1. 业务处理:业务逻辑(service)
  2. 数据持久层:CRUD(Dao)

View

  1. 展示数据
  2. 提供链接发起Servlet请求(a,form,img….)

Controller(Servlet)

  1. 接收用户的请求:(req:请求的参数,session信息)
  2. 交给业务层处理对应的代码
  3. 控制视图的跳转

11、Filter过滤器

用于过滤网站的数据:

  1. 处理中文乱码
  2. 登录验证…….

Filter开发步骤:
1.导报

2.编写过滤器

       实现接口Filter是java.servlet的

实现Filter接口,重写对应方法

public class CharacterEncodingFilter implements Filter {

   
//初始化:web服务器启动,就已经初始化了,随时等待过滤对象出现
   
public void init(FilterConfig filterConfig) throws ServletException {
       
System.out.println("CharacterEncodingFilter初始化");
   
}

   
//chain:
//    1.过滤中的所有代码,在过滤特定请求的时候都会执行
//    2.必须要让过滤器继续通行
//    chain.doFilter(request,response);
   
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
       
request.setCharacterEncoding("utf-8");
       
response.setCharacterEncoding("utf-8");
       
response.setContentType("text/html;charset=utf-8");

       
System.out.println("CharacterEncodingFilter执行前。。。");
       
chain.doFilter(request,response);//让我们的请求继续走,如果不写,程序就会被拦截停止
       
System.out.println("CharacterEncodingFilter执行后。。。");
   
}

   
//销毁:web服务器关闭的时候进行销毁
   
public void destroy() {
       
System.out.println("CharacterEncodingFilter销毁");
   
}
}

在web.xml中配置filter

<filter>
    <
filter-name>CharacterEncodingFilter</filter-name>
    <
filter-class>com.cheng.Filter.CharacterEncodingFilter</filter-class>
</
filter>
<
filter-mapping>
    <
filter-name>CharacterEncodingFilter</filter-name>
   
<!--过滤只要是/servlet的任何请求,就会经历这个过滤器-->
   
<url-pattern>/servlet/*</url-pattern>
</
filter-mapping>

12、监听器

编写监听器,实现监听器接口

public class OnlineCountListener implements HttpSessionListener {
   
//创建session监听:看你的一举一动
    //一旦创建一个session就会触发这个实践
   
public void sessionCreated(HttpSessionEvent se) {
       
ServletContext ctx = se.getSession().getServletContext();
       
System.out.println(se.getSession().getId());
       
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);

   
}
   
//销毁session监听
   
public void sessionDestroyed(HttpSessionEvent se) {
       
ServletContext ctx = se.getSession().getServletContext();
       
Integer OnlineCount= (Integer) ctx.getAttribute("OnlineCount");

        if
(OnlineCount==null){
           
OnlineCount=new Integer(0);
       
}else {
           
int count = OnlineCount.intValue();

           
OnlineCount = new Integer(count-1);
       
}

       
ctx.setAttribute("OnlineCount",OnlineCount);
   
}
}

13、过滤器、监听器常见应用

1.导入数据库依赖

2.链接数据库,并抽取数据

public static void main(String[] args) throws ClassNotFoundException, SQLException {
   
//配置信息
   
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
   
String username="root";
   
String password="123456";

   
//1.加载驱动
   
Class.forName("com.mysql.jdbc.Driver");
   
//2.链接数据库,代表数据库
   
Connection connection = DriverManager.getConnection(url, username, password);

   
//3.向数据库发送sql的statement
   
Statement statement = connection.createStatement();

   
//4.编写sql
   
String sql="select  * from users";

   
//5.执行sql,返回一个结果集ResultSet
   
ResultSet rs = statement.executeQuery(sql);

    while
(rs.next()){
       
System.out.println("id="+rs.getObject("id"));
       
System.out.println("name="+rs.getObject("name"));
       
System.out.println("password="+rs.getObject("password"));
       
System.out.println("email="+rs.getObject("email"));
       
System.out.println("birthday="+rs.getObject("birthday"));
   
}

   
//6.关闭链接
   
rs.close();
   
statement.close();
   
connection.close();
}

JDBC步骤:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement:CRUD
  4. 编写SQL(根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭链接

预编译sql

public static void main(String[] args) throws Exception {
   
//配置信息
   
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
   
String username="root";
   
String password="123456";

   
//1.加载驱动
   
Class.forName("com.mysql.jdbc.Driver");
   
//2.链接数据库,代表数据库
    
Connection connection = DriverManager.getConnection(url, username, password);
   
//3.编写sql
   
String sql="insert into users(id, name, password, email, birthday) VALUES (?,?,?,?,?)";
   
//4.预编译
   
PreparedStatement preparedStatement = connection.prepareStatement(sql);

   
preparedStatement.setInt(1,5);//给第一个占位符添值
   
preparedStatement.setString(2,"yang");
   
preparedStatement.setString(3,"123456");
   
preparedStatement.setString(4,"46245256@qq.com");
   
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));

   
//5.执行sql
   
int i = preparedStatement.executeUpdate();
    if
(i>0){
       
System.out.println("插入成功");
   
}
   
//6.关闭链接

   
preparedStatement.close();
   
connection.close();
}

事务

要么都成功,要么都失败

ACID原则:保证数据的安全

Junit单元测试

依赖

<dependency>
    <
groupId>junit</groupId>
    <
artifactId>junit</artifactId>
    <
version>4.12</version>
</
dependency>

测试使用@Test

项目的搭建

  1. 搭建一个maven web项目
  2. 配置toncat
  3. 测试项目是否可以跑起来
  4. 导入jar包

Jsp,servlet,mysql驱动,jstl,stand…….

5.创建项目包结构

       6.编写实体类

       7.编写基础公共类

              1.数据库配置文件

             driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai

username=root

password=123456
    1. 编写字符编码过滤器

8、导入静态资源

登录功能

       1、设置欢迎页(启动tomcat就是登录页)

<!--设置欢迎页面-->
<welcome-file-list>
    <
welcome-file>login.jsp</welcome-file>
</
welcome-file-list>

       2.编写dao层登录用户登录的接口

//得到登录的用户
public User getLoginUser(Connection connection, String userCode) throws SQLException;

3.编写dao接口的实现类

public class UserDaoImpl implements UserDao {
   
public User getLoginUser(Connection connection, String userCode) throws SQLException {

       
PreparedStatement pstm=null;
       
ResultSet rs=null;
       
User user=null;


        if
(connection!=null){
           
String sql="select * from smbms_user where userCode=?";
           
Object[] params ={userCode};


               
rs = BaseDao.execute(connection,pstm,rs,sql,params);

                if
(rs.next()){
                   
user =new User();
                   
user.setId(rs.getInt("id"));
                   
user.setUserCode(rs.getString("userCode"));
                   
user.setUserName(rs.getString("userName"));
                   
user.setUserPassword(rs.getString("userPassword"));
                   
user.setGender(rs.getInt("gender"));
                   
user.setBirthday(rs.getDate("birthday"));
                   
user.setPhone(rs.getString("phone"));
                   
user.setAddress(rs.getString("address"));
                   
user.setUserRole(rs.getInt("userRole"));
                   
user.setCreateBy(rs.getInt("createdBy"));
                   
user.setCreattionDate(rs.getDate("creationDate"));
                   
user.setModifyBy(rs.getInt("modifyBy"));
                   
user.setModifyDate(rs.getDate("modifyDate"));

               
}
               
BaseDao.closeResources(null,pstm,rs);

       
}
           
return user;

   
}
}

  1. 业务层接口
  2. //用户登录
    public User Login(String userCode,String password);

6.业务层实现类

public class UserServiceImpl implements UserService{

   
//业务层都会调用dao层,所以我们要引入Dao层
   
private UserDao userDao;
    public
UserServiceImpl(){
       
userDao = new UserDaoImpl();
   
}

   
public User Login(String userCode, String password) {
       
Connection connection = null;
       
User user=null;


        try
{
           
connection=BaseDao.getConnection();
           
//通过业务层调用对应的具体的数据库操作
           
user = userDao.getLoginUser(connection,userCode);


       
} catch (SQLException e) {
           
e.printStackTrace();
       
}finally {
           
BaseDao.closeResources(connection,null,null);
       
}
       
return user;
   
}

7.编写sevlet

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

   
System.out.println("LoginServlet----start");

   
String userCode = req.getParameter("userCode");
   
String userPassword = req.getParameter("userPassword");

   
//和数据库中的密码进行对比,
   
UserServiceImpl userService = new UserServiceImpl();
   
User user = userService.Login(userCode, userPassword);

    if
(user!=null){
       
//将用户的信息放入session中
       
req.getSession().setAttribute(Constants.USER_SESSION,user);
       
//跳转到内部在主页
       
resp.sendRedirect("jsp/frame.jsp");
   
}else {
       
req.setAttribute("error","用户名或密码不正确");
       
req.getRequestDispatcher("login.jsp").forward(req,resp);
   
}
}


@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
doGet(req, resp);
}

注册servlet

<!--servlet-->
<servlet>
    <
servlet-name>LoginServlet</servlet-name>
    <
servlet-class>com.cheng.servlet.user.LoginServlet</servlet-class>
</
servlet>
<
servlet-mapping>
    <
servlet-name>LoginServlet</servlet-name>
    <
url-pattern>/login.do</url-pattern>
</
servlet-mapping>

测试访问,确保以上功能

登录功能优化

注销功能

思路:移除session,返回登录页面

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
//移除用户的session
   
req.getSession().removeAttribute(Constants.USER_SESSION);
   
resp.sendRedirect("/login.jsp");//返回登录页面
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
doGet(req, resp);
}

登录拦截优化

public class SysFilter implements Filter {
   
public void init(FilterConfig filterConfig) throws ServletException {

    }

   
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       
HttpServletRequest request = (HttpServletRequest) servletRequest;
       
HttpServletResponse response = (HttpServletResponse) servletResponse;

       
//从session中获取用户
       
User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
        if
(user==null){//已经被移除或注销,或未登录
           
response.sendRedirect("/error.jsp");
       
}else {
           
filterChain.doFilter(servletRequest,servletResponse);
       
}
    }

   
public void destroy() {

    }
}

密码修改

  1. UserDao接口
  2. //修改当前用户的密码
    public int updatepwd(Connection connection,int id,int password)throws SQLException;
  3. UserDao接口实现类
  4. //修改当前用户的密码
    public int updatepwd(Connection connection, int id, int password) throws SQLException {
      
    PreparedStatement pstm=null;
        int
    execute=0;
        if
    (connection!=null) {
           
    String sql = "update smbms_user set userPassword=? where id=?";
           
    Object params[] = {password, id};
           
    execute = BaseDao.execute(connection, pstm, sql, params);
           
    BaseDao.closeResources(null, pstm, null);
       
    }
       
    return execute;
    }
  1. UserService层接口
  2. //根据用户id修改密码
    public boolean updatepwd( int id, int pwd);
  3. UserService实现类
  4. public boolean updatepwd(int id, int pwd) {
       
    Connection connection=null;

        boolean
    flag=false;
       
    //修改密码
       
    try {
           
    connection = BaseDao.getConnection();
            if
    (userDao.updatepwd(connection,id,pwd)>0){
               
    flag=true;
           
    }
        }
    catch (SQLException e) {
           
    e.printStackTrace();
       
    }finally {
           
    BaseDao.closeResources(connection,null,null);
       
    }
           
    return flag;
    }

  1. servlet层
  2. //从session里获取id
    Object o = req.getSession().getAttribute(Constants.USER_SESSION);
    String newpassword = req.getParameter("newpassword");

    System.out.println("UserServlet"+newpassword);

    boolean
    flag=false;

    if
    (o!=null && newpassword!=null){
       
    UserService userService = new UserServiceImpl();
       
    flag = userService.updatepwd(((User) o).getId(), newpassword);
        if
    (flag){
           
    req.setAttribute("message","修改密码成功,请退出,使用新密码登录");
           
    //密码修改成功,移除当前session
           
    req.getSession().removeAttribute(Constants.USER_SESSION);

       
    }else {
           
    req.setAttribute("message","密码修改失败");

       
    }
    }
    else {
       
    req.setAttribute("message","新密码有问题");
    }
    try {
       
    req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp);
    } catch (ServletException e) {
       
    e.printStackTrace();
    } catch (IOException e) {
       
    e.printStackTrace();
    }

8.使用复用,提取方法

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
String method = req.getParameter("method");
    if
(method.equals("savepwd")&& method!=null){
       
this.updatePwd(req,resp);
   
}
}

优化密码修改使用Ajax

1.阿里巴巴的fastjson

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->

<dependency>

    <groupId>com.alibaba</groupId>

    <artifactId>fastjson</artifactId>

    <version>1.2.78</version>

</dependency>

用户管理实现

  1. 导入分页的工具类
  2. 用户列表页面导入

获取用户数量

  1. userDao
  2. //根据用户名或者角色查询用户总数
    public int getUserCount(Connection connection,String username,int userRole)throws SQLException;

  1. userDaoImpl
  2. //根据用户名或者角色查询用户总数
    public int getUserCount(Connection connection, String username, int userRole) throws SQLException {

       
    PreparedStatement pstm=null;
       
    ResultSet rs=null;
        int
    count=0;

        if
    (connection!=null){
           
    StringBuffer sql=new StringBuffer();
           
    sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole=r.id");
           
    ArrayList<Object> list = new ArrayList<Object>();//存放我们的参数

           
    if (!StringUtils.isNullOrEmpty(username)){
               
    sql.append(" and u.userName like ?");
               
    list.add("%"+username+"%");
           
    }

           
    if (userRole>0){
               
    sql.append(" and u.userRole=?");
               
    list.add(userRole);
           
    }

           
    //怎么把list转换为数组
           
    Object[] params = list.toArray();

           
    System.out.println("UserDaoImpl-->getUserCount:"+sql.toString());//输出完整的sql语句


           
    rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);

            if
    (rs.next()){
               
    count = rs.getInt("count");//从结果集中获取最终数量
           
    }
           
    BaseDao.closeResources(null,pstm,rs);
       
    }
       
    return count;
    }
  3. UserService
  4. //查询记录数
    public int getUserCount(String username,int userRole);
  5. UserServiceImpl
  6. //查询记录数
    public int getUserCount(String username, int userRole) {

       
    Connection connection = null;
        int
    count=0;
        try
    {
           
    connection = BaseDao.getConnection();
           
    count = userDao.getUserCount(connection, username, userRole);


       
    } catch (SQLException e) {
           
    e.printStackTrace();
       
    }finally {
           
    BaseDao.closeResources(connection,null,null);
       
    }

       
    return count;
    }

获取用户列表

  1. Userdao
  2. //获取用户列表
    public List<User> getUserList(Connection connection,String userName,int userRole,int currenPageNo,int pageSize)throws SQLException, Exception;
  3. Userdaoimpl
  4. //获取用户列表
    public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize)throws Exception {

       
    PreparedStatement pstm = null;
       
    ResultSet rs = null;
       
    List<User> userList = new ArrayList<User>();
        if
    (connection != null) {
           
    StringBuffer sql = new StringBuffer();
           
    sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id");
           
    List<Object> list = new ArrayList<Object>();
            if
    (!StringUtils.isNullOrEmpty(userName)) {
               
    sql.append(" and u.userName like ?");
               
    list.add("%" + userName + "%");
           
    }
           
    if (userRole > 0) {
               
    sql.append(" and u.userRole = ?");
               
    list.add(userRole);
           
    }
           
    //在mysql数据库中,分页使用 limit startIndex,pageSize ; 总数
           
    sql.append(" order by creationDate DESC limit ?,?");
           
    currentPageNo = (currentPageNo - 1) * pageSize;
           
    list.add(currentPageNo);
           
    list.add(pageSize);

           
    Object[] params = list.toArray();
           
    System.out.println("sql ----> " + sql.toString());
           
    rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
            while
    (rs.next()) {
               
    User _user = new User();
               
    _user.setId(rs.getInt("id"));
               
    _user.setUserCode(rs.getString("userCode"));
               
    _user.setUserName(rs.getString("userName"));
               
    _user.setGender(rs.getInt("gender"));
               
    _user.setBirthday(rs.getDate("birthday"));
               
    _user.setPhone(rs.getString("phone"));
               
    _user.setUserRole(rs.getInt("userRole"));
               
    _user.setUserRoleName(rs.getString("userRoleName"));
                
    userList.add(_user);
           
    }
           
    BaseDao.closeResources(null, pstm, rs);
       
    }
       
    return userList;
    }

  1. Userservice
  2. //根据条件查询用户列表
    public List<User> getUserList(String queryUserName,int queryUserRole,int currentPageNo,int pageSize);
  3. Userserviceimpl
  4. public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) {
       
    Connection connection = null;
       
    List<User> userList = null;
        try
    {
           
    connection = BaseDao.getConnection();
           
    userList = userDao.getUserList(connection, queryUserName, queryUserRole, currentPageNo, pageSize);
       
    } catch (Exception e) {
           
    e.printStackTrace();
       
    } finally {
           
    BaseDao.closeResources(connection, null, null);
       
    }
       
    return userList;
    }

获取用户操作

为了职责统一,可以把角色的操作单独放再一个包中,和entity类对应

  1. roledao

//获取角色列表
public List<Role> getRoleList(Connection connection)throws SQLException;

  1. roledaoimpl

//获取角色列表
public List<Role> getRoleList(Connection connection) throws SQLException {

   
PreparedStatement pstm=null;
   
ResultSet rs=null;
   
ArrayList<Role> roleList = new ArrayList<Role>();

    if
(connection!=null){
       
String sql="select * from smbms_role";
       
Object[] params={};
       
rs = BaseDao.execute(connection, pstm, rs, sql, params);

        while
(rs.next()){
           
Role _role=new Role();
           
_role.setId(rs.getInt("id"));
           
_role.setRoleName(rs.getString("roleNaem"));
           
_role.setRoleCode(rs.getString("roleCode"));

           
roleList.add(_role);
       
}
       
BaseDao.closeResources(null,pstm,rs);
   
}
   
return roleList;
}

  1. roleservice

//获取角色列表
public List<Role> getRoleList();

  1. roleserviceimpl

public List<Role> getRoleList() {
   
Connection connection = null;
   
List<Role> roleList=null;
    try
{
       
connection = BaseDao.getConnection();
       
roleList = roleDao.getRoleList(connection);
   
} catch (SQLException e) {
       
e.printStackTrace();
   
}finally {
       
BaseDao.closeResources(connection,null,null);
   
}
   
return roleList;
}

  1. 用户显示Servlet
  1. 获取用户前端的数据(查询)
  2. 判断请求是否需要执行,看参数的值判断
  3. 为了实现分页,需要计算出当前页面和总页面,页面大小。。
  4. 用户列表展示
  5. 返回前端

文件上传

public class UploadFileServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        //判断上传的表单是普通表单还是带文件的表单,是返回true,否返回false

        if (!ServletFileUpload.isMultipartContent(request)){

            return;//如果这是一个普通文件我们直接返回

        }//如果通过了这个if,说明我们的表单是带文件上传的

        //创建上传文件的保存目录,为了安全建议在WEB-INF目录下,用户无法访问

        String uploadpath = this.getServletContext().getRealPath("WEB-INF/Upload");//获取上传文件的保存路径

        File uploadfile = new File(uploadpath);

        if (!uploadfile.exists()){

            uploadfile.mkdir();//如果目录不存在就创建这样一个目录

        }

        //临时文件

        //临时路径,如果上传的文件超过预期的大小,我们将它存放到一个临时目录中,过几天自动删除,或者提醒用户转存为永久

        String tmppath = this.getServletContext().getRealPath("WEB-INF/tmp");

        File file = new File(tmppath);

        if (!file.exists()){

            file.mkdir();//如果目录不存在就创建这样临时目录

        }

        //处理上传的文件一般需要通过流来获取,我们可以通过request.getInputstream(),原生态文件上传流获取,十分麻烦

        //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件;

        try {

            //1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小

            DiskFileItemFactory factory = gteDiskFileItemFactory(file);

            //2、获取ServletFileUpload

            ServletFileUpload upload = getServletFileUpload(factory);

            //3、处理上传文件

            String msg = uploadParseRequest(upload,request,uploadpath);

            //Servlet请求转发消息

            request.setAttribute("msg",msg);

            request.getRequestDispatcher("/info.jsp").forward(request,response);

        }catch (FileUploadException e){

            e.printStackTrace();

        }

    }

    public static DiskFileItemFactory gteDiskFileItemFactory(File file){

        //1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小

        DiskFileItemFactory factory = new DiskFileItemFactory();

        //通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;

        factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M

        factory.setRepository(file);

        return factory;

    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){

        //2、获取ServletFileUpload

        ServletFileUpload upload = new ServletFileUpload(factory);

        //监听文件上传进度

        upload.setProgressListener(new ProgressListener() {

            @Override

            public void update(long pBytesRead, long lpContentLenght, int i) {

                //pBytesRead:已读取到的文件大小

                //pContentLenght:文件大小

                System.out.println("总大小:"+lpContentLenght+"已上传:"+pBytesRead);

            }

        });

        //处理乱码问题

        upload.setHeaderEncoding("UTF-8");

        //设置单个文件的最大值

        upload.setFileSizeMax(1024 * 1024 * 10);

        //设置总共能够上传文件的大小

        //1024 = 1kb * 1024 = 1M * 10 = 10M

        upload.setSizeMax(1024 * 1024 * 10);

        return upload;

    }

    public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadpath) throws IOException, FileUploadException {

        String msg = "";

        //3、处理上传文件

        //把前端的请求解析,封装成一个FileItem对象

        List<FileItem> fileItems = upload.parseRequest(request);

        for (FileItem fileItem : fileItems) {

            if (fileItem.isFormField()){ //判断是普通表单还是带文件的表单

                //getFieldName指的是前端表单控件的name

                String name = fileItem.getFieldName();

                String value = fileItem.getString("UTF-8");//处理乱码

                System.out.println(name+":"+value);

            }else {//判断它是带文件的表单

                //======================处理文件=======================//

                //拿到文件的名字

                String uploadFileName = fileItem.getName();

                System.out.println("上传的文件名:"+uploadFileName);

                if (uploadFileName.trim().equals("")) continue;

                //获得上传的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的后面的都不需要

                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);

                //获得文件的后缀名

                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);

                /*

                 * 如果后缀名 fileExtName 不是我们需要的

                 *就直接return,不处理,告诉用户类型不对

                 * */

                System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"");

                //可以使用UUID(唯一通用识别码)来保证文件名的统一

                String uuidFileName = UUID.randomUUID().toString();

                //=======================传输文件=========================//

                //获得文件上传的流

                InputStream inputStream = fileItem.getInputStream();

                //创建一个文件输出流

                FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+ fileExtName);

                //创建一个缓冲区

                byte[] buffer = new byte[1024 * 1024];

                //判断是否读取完毕

                int len;

                //如果大于0,说明还存在数据

                while ((len=inputStream.read(buffer))>0){

                    fos.write(buffer,0,len);

                }

                //关闭流

                fos.close();

                inputStream.close();

                msg = "文件上传成功!";

                fileItem.delete();//上传成功,清除临时文件

            }

        }

        return msg;

    }

}

邮件的发送实现

Session对象:定义整个程序所需要环境信息,比如主机名,端口,采用的邮件发送和接收协议

创建

Transport对象:用来发送邮件

引用

Message对象:表示一封电子邮件

邮件服务器

Store对象:用来接收邮件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值