一个成熟的web需要运用到多种语言的书写,这里的数据库连接我们已经学了使用jdbc以及mybatis的方式完成数据的获取与修改
请求体和i请求头之间有空格隔开的
对应的参数存放到请求体中
GET/POST的区别
1.GET请求参数放到请求行中,没用请求体。POST请求参数放到请求体中
2.GET请求请求参数大小有限制,POST 没有
这种类似的web服务器是一个软件,对http协议操作进行封装,使程序员不必直接对协议进行操作,让WEB开发更加快捷
可以将web项目部署到服务器中,对外提供网上浏览服务
我们用的tomcat是一个轻量级web服务器
这是一个绿色软件直接解压即安装,删除文件夹即卸载
打开方式点开bin start.bat安全打开,ctrl+c安全关闭
在idea中可以本地部署tomcat
也可以使用pom中添加配置
1.在pom文件里导入依赖jar包,直接复制以后都是一样的
这里注意一定要定义一个scope为provided
2.写一个方法完成servlet接口,重写其方法
3.配置访问路径使其能被访问到
这里说一下我这里困扰了一下午的tomcat页面一直404输入路径也无法跳转,最后我重新以模板的形式生成了maven新的工程,在pom中导入tomcat就解决了,真是让人头疼
这里我们的service方法里只是写了输出语句,其实这是用来接收以及向服务器返回数据的方法,之后学习了过后,会具体使用
package com.ember.web; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException; @WebServlet(urlPatterns = "/demo1",loadOnStartup = 1) public class ServletDemo2 implements Servlet { /*完成初始化的方法 * 1.调用时机:默认情况下,servlet被第一次访问时调用 * loadOnStartup:默认是-1,改成正整数则访问servlet的时候直接创建 * (使用属性来更改调用的时机使用属性要先补全注解里面的属性值urlPatterns =) * 2.调用次数:1次*/ @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("init"); } /*提供服务 * 1.调用时机:每一次servlet被访问时就调用 * 2.调用次数:每次访问页面就会被调用*/ @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("selevet hello world"); } /*1销毁方法 * 调用时机:内存释放或者服务器关闭的时候,servlet对象会被销毁,调用该方法释放资源 * 调用次数:1次*/ @Override public void destroy() { System.out.println("destroy"); } @Override public ServletConfig getServletConfig() { return null; } @Override public String getServletInfo() { return null; } }
其他两个方法在需要使用时查看javaee api
这里说一下要在一个方法中使用另一个方法中的成员变量,则直接提升改成与变量的作用域
@WebServlet(urlPatterns ="/demo3") public class ServletDemo3 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post..."); } }
以上代码显示servlet会根据页面的访问方式调用不同的方法,这里用一个例子显示了调用的是哪个方法我们通过a.html提交数据到demo3时使用的post方式则会调用dopost方法,直接访问用get方式则使用doget方法
http协议里一共有七种请求方式,对应了七种方法,用到的时候都是要复写的
HttpServlet的使用步骤:1.写类继承HttpServlet2.重写doget和dopost方法
使用原理:获取请求方式,并且根据不同的请求方式,调用不同的doxxx方法
一个servlet可以配置多个urlPattern,通过这些路径都可以访问到servlet
@WebServlet(urlPatterns ={"/demo3","/demo4"})
urlPattern的配置规则:
当一个路径同时符合精确匹配也符和路径匹配,则精确匹配的优先级要高一点
一般只用前三种,第四种尽量不要使用
优先级依次递减
1.继承httpservlet
public class ServletDemo4 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("demo4.get..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("demo4.post..."); } }
2、在web.xml里面完成配置
<!-- servlet全类名--> <servlet> <servlet-name>renyi</servlet-name> <servlet-class>com.ember.web.ServletDemo4</servlet-class> </servlet> <!-- servlet访问路径--> <servlet-mapping> <servlet-name>renyi</servlet-name> <url-pattern>/demo4</url-pattern><!-- 配置可以访问的路径--> </servlet-mapping>
很明显注解的方式简单多了
Request:获取请求数据
Response:设置响应数据
以下代码实现以下浏览器的交互
@WebServlet(urlPatterns ="/demo3") public class ServletDemo3 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { //用request获取请求数据 String name=request.getParameter("name"); resp.setHeader("content-type","text/html;charset=utf-8"); //用response 设置响应数据 resp.getWriter().write("<h1>"+name+",欢迎您!<h1>"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post..."); } }
当我们在网址后面输入?name=xxx的时候页面会根据名字内容更改显示内容,这就是交互
Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中
要使用request对象,直接查阅javaee api文档的httpservletrequest接口
分为三步:获取请求行&请求头&请求体
下面写一个例子
@WebServlet(urlPatterns = "/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method=req.getMethod();//获取请求方式GET System.out.println(method); String contextPath=req.getContextPath(); System.out.println(contextPath); StringBuffer url=req.getRequestURL(); System.out.println(url.toString()); String uri = req.getRequestURI(); System.out.println(uri); String queryString = req.getQueryString();//获取请求参数(get方式) System.out.println(queryString); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
对于我们要向页面传入一些信息我们可以写一个表单完成数据传入(注意这里要使用get方式,应为我们是在doget方法中写的测试)
<form name="user" action="/testtomcat2/req1" method="get"> username:<input name="uername"> password:<input name="password"> <input type="submit"> </form>
点击提交后会直接跳转,数据会返回到控制台
/*获取请求头 * user-agent获取浏览器的版本*/ String agent = req.getHeader("user-agent"); System.out.println(agent);
以上呢get和post都会有,而请求体只有post请求才会有所以要测试请求体的方法则需要写一个表单
<form action="/testtomcat2/req1" method="post"> 用户名: <input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit"> </form>
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取post 请求体 请求参数 // 获取字符输入流 BufferedReader br = req.getReader(); String line = br.readLine(); System.out.println(line); }
通过获取字节流或字符流获得数据
因为一个servlet根据请求方式的不同会调用不同的方法,但是这两个方法中只有获取请求的方式这一段代码不同其他的都是差不多的,这就造成了代码的重复,所以我们可以使用一种统一的获取请求参数的方式,从而统一doget和dopost方法内的代码
首先我们判断是哪种请求在调用相应的获取参数的方式,系统将这些参数封装成一个Map集合,这三个方法就是request对象提供的通用获取请求参数的方法,以下是对三个方法的实现例子
@WebServlet("/req2") public class RequestDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // GET请求逻辑 System.out.println("get....."); // 1.获取所有参数的MAP集合(iter快捷遍历) Map<String, String[]> map = req.getParameterMap(); for (String s : map.keySet()) { // 获取的格式时username:zhangsan System.out.print(s+":"); // 获取值 String[] values = map.get(s); for (String value : values) { System.out.print(value+" "); } System.out.println(); } System.out.println("..............."); // 根据key获取参数值(数组) String[] hobbies = req.getParameterValues("hobby"); for (String hobby : hobbies) { System.out.println(hobby); } //3.根据key获取单个的参数值 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); }
将doget里面的代码全部复制到doget中也是可以获取到数据的这就是通用的三个方法
因为里面的代码是完全一样的,所以我们的dopost方法里只用调用doget就可以了
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // POST请求逻辑 this.doGet(req, resp); } }
使用了通用方式之后,屏蔽了get和post的请求方式的不同,则我们可以使用servlet模板来创建servlet
可以根据需要去改造模板
这是我们写了一个例子来获取用户名,并且在html页面中提交了中文用户名导致的乱码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取username String username = request.getParameter("username"); System.out.println(username); }
// 解决乱码 POST.getReader()获取字符流默认的编码不是utf-8,所以post请求的中文会乱码 request.setCharacterEncoding("UTF-8");/*设置字符输入流的编码*/
在最上面加入如上代码,改变其编码与html相同
解决中文乱码 get 乱码原因:浏览器处理数据进行url编码(UTF-8),服务器接收数据再进行url解码(ISO-8859-1),但是编码解码使用的字符集不一样导致乱码,只能从url编码底层入手
以下是对get请求传入中文的username解决办法
/*1.先对乱码数据进行编码,转为字节数组*/ // byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1); // /*字节数组解码*/ // username = new String(bytes, StandardCharsets.UTF_8); username=new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8); System.out.println("解决乱码后"+username);
熟练过后将上面两行代码合并成一行了,这种方式是一种通用的方式同样可以解决post乱码
一种在服务器内部的资源跳转方式
// 请求转发 request.getRequestDispatcher("/req6").forward(request,response);
将请求转发给另一个路径,一般两个路径要共享数据
在req5页面中请求转发
System.out.println("demo5''''[''"); // 存储数据 request.setAttribute("msg","hello"); // 请求转发 request.getRequestDispatcher("/req6").forward(request,response);
在req6中接收请求
获取数据 Object msg = request.getAttribute("msg"); System.out.println(msg); System.out.println("demo6'''''''"); }
转发的特点:
浏览器地址栏路径不发生改变
只能转发到当前服务器的内部资源
一次请求,可以在转发资源间使用request共享数据
以下是响应数据的分类以及对应的设置的方法
即当不能处理请求的时候返回其他路径
即分为两步:
1.返回状态码302
2.返回跳转路径
实现:
resp.setStatus(302);
resp.setHeader("location","资源b的路径")
以下例子
resp1
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("resp1.........."); // 重定向 // 1.设置响应数据码302 response.setStatus(302); // 2.设置响应头Location response.setHeader("Location","/testtomcat2/resp2");//注意资源路径要写服务器的虚拟前缀 }
resp2
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("resp2.........."); }
只要访问resp1就自动跳转到resp2
可以发现这个代码只有跳转的路劲会有改变所以以后这样写
// 简化方式完成重定向 response.sendRedirect("/testtomcat2/resp2");
(注意:可以重定向到任意路径)
浏览器使用:需要加虚拟目录(项目访问路径)
服务端使用:不加虚拟目录(即不需要浏览器跳转页面访问)
对于要加虚拟路径的时候直接写虚拟目录,使得耦合性太强了,以后一改路劲就会出错,所以我们一般采用动态路径
// 简化方式完成重定向 // response.sendRedirect("/testtomcat2/resp2"); // 动态获取虚拟目录 String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"resp2");
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /*防止设置的字节流是中文乱码以及能够解析html格式和文本格式的字符流*/ response.setContentType("text/html;charset=utf-8"); /*1.获取字符输出流*/ PrintWriter writer = response.getWriter(); writer.write("设置的响应字符"); writer.write("<h1>wy,你好</h1>"); }
获取字节流就是使用的获取方法不一样,用与获取一些文件并输出
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取文件 FileInputStream fis = new FileInputStream("C://Users//Ember//Desktop//icon//file.png"); // 2.获取Response字节输出流 ServletOutputStream os = response.getOutputStream(); // 3.完成流的Copy byte[] buff=new byte[1024]; int len=0; while((len=fis.read(buff))!=-1){ os.write(buff,0,len); } fis.close(); }
这种复制方法是javaIO中的知识,我们一般使用工具类来简化
先去pom里增加依赖
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
导入后即可使用IOUtils的方法了
// 3.完成流的Copy // byte[] buff=new byte[1024]; // int len=0; // while((len=fis.read(buff))!=-1){ // os.write(buff,0,len); // } IOUtils.copy(fis,os); fis.close();
(注意:这里选着IOUtils时要注意导入的包是apache)
1.用户登录
首先在我们之前建立了maven插件以及servlet的工程里首先配置好mybatis需要的环境
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <!-- junit 单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.2</version> <scope>test</scope> </dependency> <!-- 添加slf4j日志api --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.20</version> </dependency> <!-- 添加logback-classic依赖 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <!-- 添加logback-core依赖 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> </dependencies> <build>
接着在目录下创建一个pojo用于存放封装对象的类
写好user的属性以及set、get方法
接着写接口和对应的增删改方法(简单的增删改就写注解就好了,不用写配置文件了)
在对应准备好的页面里定义跳转的页面
接着·我们就可以完成对应的servlet的代码(这里要用到servlet,mybatis,request相关的知识)
@WebServlet(name = "loginServlet", value = "/loginServlet") public class loginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String username=request.getParameter("username"); String password=request.getParameter("password"); String resource = "mybatis-config.xml"; InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession=sqlSessionFactory.openSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); User user=userMapper.select(username,password); if(user!=null){ response.setHeader("content-type","text/html;charset=utf-8"); //用response 设置响应数据 response.getWriter().write("<h1>"+username+",欢迎您!<h1>"); }else{ response.setHeader("content-type","text/html;charset=utf-8"); //用response 设置响应数据 response.getWriter().write(username+"用户不存在或密码错误"); } sqlSession.close(); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
2.注册界面也是一样的
(1)接口中方法的书写(用注解完成sql语句)
(2)对应html页面写好form属性
(3)servlet完成代码(这是难点)
@WebServlet(name = "registerServlet", value = "/registerServlet") public class registerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); username=new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8); // username="%"+username+"%"; // ssw paord="%"+password+"%"; User user=new User(); user.setUsername(username); user.setPassword(password); response.setHeader("content-type","text/html;charset=utf-8"); String resource = "mybatis-config.xml"; InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession=sqlSessionFactory.openSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); User user2=userMapper.select(username,password); if(user2!=null){ //用response 设置响应数据 response.getWriter().write("用户已存在"); }else { userMapper.insert(user); User user1=userMapper.select(username,password); if(user1!=null){ response.getWriter().write(username+"用户注册成功!"); } } sqlSession.commit();/*需要手动提交数据才能更改数据库数据*/ sqlSession.close(); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
(注意:如果要更改数据库的数据要在释放前手动提交表单)
其实最容易出错的还是maven环境和mybatis环境的搭建,建议工程开始前先借鉴mybatis快速入门搭建环境看看能否启动成功
而maven环境就用maven插件(安装插件再到pom中配置相关maven插件)就好了
<plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> </plugins>
这样就是简单的案例,以后常练习
之前我们学习jdbc一样,我们发现我们只要一使用mybatis就会连接一次SqlSessionFactory对象,这样会造成有许多同样的代码,所以我们写个工具类来封装这些代码,减少重复的代码而且有多个连接池就创建多次工厂,这会让资源消耗大大增加,所以我们这样也可以让工厂只被创建一次(静态代码块,只会执行一次)
我们先创建个包,来存放所有的工具类
public class SqlSessionFactoryUtils { //定义静态对象,使类中方法能访问静态代码 private static SqlSessionFactory sqlSessionFactory; // 静态代码块随着类的加载自动执行,且只会执行一次 static { String resource = "mybatis-config.xml"; InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory; } }
随后我们将项目中重复的代码直接换成调用我们工具类中的get方法就行了
// String resource = "mybatis-config.xml"; // InputStream inputStream = null; // try { // inputStream = Resources.getResourceAsStream(resource); // } catch (IOException e) { // e.printStackTrace(); // } // SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSessionFactory sqlSessionFactory= SqlSessionFactoryUtils.getSqlSessionFactory();
注意在导入坐标的时候一定要加provided应为要排除这个jar包,tomcat里面自带了这个jar包,如果不排除就会报错
原理:
在jsp中写不同类型的代码就是用这个脚本产生断点使得语言连贯
练习
用jsp在页面上根据数据打印表格
<%@ page import="com.ember.pojo.Brand" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %><%-- Created by IntelliJ IDEA. User: Ember Date: 2022/4/4 0004 Time: 15:55 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% //查询数据库(这里直接用集合模仿) List<Brand> brands = new ArrayList<Brand>(); brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1)); brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0)); brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1)); %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0" width="800"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <% for (int i = 0; i < brands.size(); i++) { Brand brand = brands.get(i); %> <tr align="center"> <td><%=brand.getId()%></td> <td><%=brand.getBrandName()%></td> <td><%=brand.getCompanyName()%></td> <td><%=brand.getOrdered()%></td> <td><%=brand.getDescription()%></td> <td><%=brand.getStatus()%></td> <% if (brand.getStatus()==1){ %> <td><%="启用"%></td> <% }else{ %> <td><%="禁用"%></td> <% } %> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> <% } %> </table> </body> </html>
通过这个案例我们发现jsp还是有不扫缺点的
现在jsp已经不常用了,而是由html和Ajax(异步的js)来替代了
现在就是介绍目前最主流的servlet+html+ajax开发之前的servlet+jsp开发模式
要减少jsp的缺点,我们就不要直接在JSP里写java代码
我们在servlet里写java逻辑处理,封装数据
jsp只用来获取数据,遍历展现数据
相当于通过访问serlvet界面转发到jsp页面
@WebServlet("/demo1") public class ServletDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取资源(这里直接用集合模仿) List<Brand> brands = new ArrayList<Brand>(); brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1)); brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0)); brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1)); // 存储到request域中 request.setAttribute("brands",brands); // 转发到el-demo.jsp request.getRequestDispatcher("/el-demo.jsp").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
接着我们直接在jsp页面中接收brands集合
<%@ page isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> ${brands} </body> </html>
当我们访问页面发现页面忽视了我们的el表达式时在jsp开头加上<%@ page isELIgnored="false" %>,则可以成功获取
以下举例一个标签
这两种就是将模块分开,提高代码的复用性,当我们改变一种方式的时候,只需要改相应模块的代码就好了
环境准备:
导入坐标
2.创建三成架构包结构
3.创建数据表tb_brand之前已经创建好了的
4.创建实体类Brand
包括了数据库中的属性,以及含参和无参的构造函数,以及属性对应的set,get方法,还有tostring方法
5.mybatis基础环境:
核心配置文件
brandmapper.xml
brandmapper接口
案例分析:
之前我们直接在serlvet里面就调用了接口中的方法(直接调用dao层)这种方法每次要调用同一个方法都要重新写一遍serlvet这使得代码复用性很差,现在我们使用三层构架将方法调用交给中间层service,这样提高了代码的复用性
因为是简单的查询直接使用注解的方式
/*查询所有*/ public interface BrandMapper { @Select("SELECT * FROM tb_brand") List<Brand> selectAll(); }
2.完成service层的类,用于调用接口中的方法,这里要使用工具类(我们之前写好了的)放入util中
public class SqlSessionFactoryUtils { private static SqlSessionFactory sqlSessionFactory; static{ String resource="mybatis-config.xml"; InputStream inputStream=null; try { inputStream= Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory; } }
随后完成service层
public class BrandService { public List<Brand> selectAll(){ // 调用BrandMapper.sellctAll,这里使用之前的工具类 SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory(); // 获取对应的SqlSession SqlSession sqlSession = factory.openSession(); // 获取对应的BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 调用方法 List<Brand> brands=mapper.selectAll(); // 释放资源 sqlSession.close(); // 返回值 return brands; } }
3.完成web层,写页面首页以及serlvet
<html> <body> <a href="/webJsp/selectAllServlet">查询所有</a> </body> </html>
@WebServlet(name = "selectAllServlet", value = "/selectAllServlet") public class selectAllServlet extends HttpServlet { BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.调用BrandService完成查询 // BrandService service = new BrandService();/*因为可能多次使用我们放到方法外面去使它只创建一次*/ List<Brand> brands = service.selectAll(); // 2.存入request域中 request.setAttribute("brands",brands); // 3.转发到brand.jsp request.getRequestDispatcher("/brand.jsp").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
在brand.jsp中我们通过jstl表达式遍历集合打印表格
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellpadding="0" width="800"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="status"> <tr> <td>${status.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:if test="${brand.status==1}"> <td>启用</td> </c:if> <c:if test="${brand.status!=1}"> <td>禁用</td> </c:if> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> </body> </html>
随后发现页面有的数据不显示,这是因为我们写的名字和失去了、
中的列名不匹配,之前就讲过解决办法,就是在映射文件中转化一下
随后在接口中引用写好的resultmap
/*查询所有*/ public interface BrandMapper { @Select("SELECT * FROM tb_brand") @ResultMap("brandResultMap") List<Brand> selectAll(); }
案例分析2新增功能
1.完成Dao
接口中添加方法,注解完成sql语句
@Insert("" + "INSERT INTO" + " tb_brand(" + "brand_name, " + "company_name, " + "ordered," + " description," + " status) " + "VALUES (" + "#{brandName}," + "#{companyName}," + "#{ordered}," + "#{description}," + "#{status})") void add(Brand brand); }
2.service层
在之前写好的BrandService里面添加方法
/*添加数据*/ public void add(Brand brand){ // 获取对应的SqlSession SqlSession sqlSession = factory.openSession(); // 获取对应的BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 调用方法 mapper.add(brand); // 提交事务 sqlSession.commit(); // 释放资源 sqlSession.close(); }
3.web层
在页面中为新增按钮添加点击事件,点击完成页面跳转
可以看到跳转到了addBrand页面,所以我们写一个这个页面来完成表单提交
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加品牌</title> </head> <body> <h3>添加品牌</h3> <form action="/webJsp/AddServlet" method="post"> 品牌名称:<input name="brandName"><br> 企业名称:<input name="companyName"><br> 排序:<input name="ordered"><br> 描述信息:<textarea rows="5" cols="20" name="description"></textarea><br> 状态: <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1">启用<br> <input type="submit" value="提交"> </form> </body> </html>
随后我们就可以完成对应的AddServlet代码了
@WebServlet(name = "AddServlet", value = "/AddServlet") public class AddServlet extends HttpServlet { private BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理post请求的乱码问题 request.setCharacterEncoding("utf-8"); // 1.接收表单提交的数据,封装为一个Brand对象 String brandName=request.getParameter("brandName"); String companyName=request.getParameter("companyName"); String ordered=request.getParameter("ordered"); String description =request.getParameter("description"); String status =request.getParameter("status"); // 封装为一个Brand对象 Brand brand=new Brand(); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setOrdered(Integer.parseInt(ordered)); brand.setDescription(description); brand.setStatus(Integer.parseInt(status)); // 2.调用service完成添加 service.add(brand); // 3.转发到查询所有的servlet request.getRequestDispatcher("/selectAllServlet").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
案例三修改
要完成点击修改按钮后,显示原有数据,并且修改后提交跳转到查询所有
我们分为两步
1.dao
/*根据id查询*/ @Select("SELECT * FROM tb_brand WHERE id=#{id}") @ResultMap("brandResultMap")
2.service
public Brand selectById(int id){ SqlSession sqlSession=factory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); Brand brand= mapper.selectById(id); sqlSession.close(); return brand; }
<td><a href="/webJsp/SelectByIdServlet?id=${brand.id}">修改</a>
这个是给修改按钮添加点击跳转,并传入对应id值。
@WebServlet(name = "SelectByIdServlet", value = "/SelectByIdServlet") public class SelectByIdServlet extends HttpServlet { private BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id= request.getParameter("id"); Brand brand=service.selectById(Integer.parseInt(id)); /*存储到request中*/ request.setAttribute("brand",brand); /*转发到update.jsp中*/ request.getRequestDispatcher("update.jsp").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
这里是将原数据转发到update.jsp界面显示出来,接下来在update中和修改数据
1.dao
/*修改数据*/ @Update("UPDATE tb_brand " + "SET " + "brand_name=#{brandName}," + "company_name=#{companyName}, " + "ordered=#{ordered}," + "description=#{description}," + "status=#{status} WHERE id=#{id}") void update(Brand brand); }
2.service
public void update(Brand brand){ SqlSession sqlSession = factory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); mapper.update(brand); sqlSession.commit(); sqlSession.close(); }
3.servlet
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page isELIgnored="false" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改品牌</title> </head> <body> <h3>添加品牌</h3> <form action="/webJsp/updateServlet" method="post"> <%--隐藏域,不显示id但是提交--%> <input type="hidden" name="id" value="${brand.id}"> 品牌名称:<input name="brandName" value="${brand.brandName}"><br> 企业名称:<input name="companyName" value="${brand.companyName}"><br> 排序:<input name="ordered" value="${brand.ordered}"><br> 描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br> 状态: <c:if test="${brand.status==0}"> <input type="radio" name="status" value="0" checked>禁用 <input type="radio" name="status" value="1">启用<br> </c:if> <c:if test="${brand.status!=0}"> <input type="radio" name="status" value="0" >禁用 <input type="radio" name="status" value="1" checked>启用<br> </c:if> <input type="submit" value="提交"> </form> </body> </html>
@WebServlet(name = "UpdateServlet", value = "/updateServlet") public class UpdateServlet extends HttpServlet { private BrandService service=new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理post请求的乱码问题 request.setCharacterEncoding("utf-8"); // 1.接收表单提交的数据,封装为一个Brand对象 String id=request.getParameter("id"); String brandName=request.getParameter("brandName"); String companyName=request.getParameter("companyName"); String ordered=request.getParameter("ordered"); String description =request.getParameter("description"); String status =request.getParameter("status"); // 封装为一个Brand对象 Brand brand=new Brand(); brand.setId(Integer.parseInt(id)); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setOrdered(Integer.parseInt(ordered)); brand.setDescription(description); brand.setStatus(Integer.parseInt(status)); // 2.调用service完成修改 service.update(brand); // 3.转发到查询所有的servlet request.getRequestDispatcher("/selectAllServlet").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取Cookie // 1.获取Cookie数组 Cookie[] cookies = request.getCookies(); // 2.遍历数组 for (Cookie cookie : cookies) { // 3.获取数据 String name = cookie.getName(); if ("username".equals(name)) { String value = cookie.getValue(); System.out.println(name+":"+value); break; } } }
发送cookie比较简单,以上是获取cookie的例子
以下是设置存活时间
// 发送cookie // 1.创建cookie对象 Cookie cookie=new Cookie("username","sb"); // 设置存活时间(要计算) 1周7天 cookie.setMaxAge(60*60*24*7);
以下是解决中文问题
String value="张三"; // URL编码 value=URLEncoder.encode(value,"UTF-8"); // 1.创建cookie对象 Cookie cookie=new Cookie("username",value);
if ("username".equals(name)) { String value = cookie.getValue(); // 解码 value= URLDecoder.decode(value,"UTF-8");
@WebServlet(name = "SessionDemo1", value = "/demo1") public class SessionDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 存储数据到Session中 HttpSession session = request.getSession(); // 存储数据 session.setAttribute("username","zs"); }
@WebServlet(name = "SessionDemo2", value = "/demo2") public class SessionDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取数据,从Session中 // 1.获取session对象 HttpSession session = request.getSession(); // 2.获取数据 Object username=session.getAttribute("username"); System.out.println("username"+":"+username); }
因为在响应的时候session会携带id,id存到了浏览器所以,同一个浏览器请求统一资源时得到的session是一样的(除非关闭浏览器),如下图请求一二