SpringMVC(Spring Web MVC 框架)

一、SpringMVC

SpringMVC是一个spring家族 MVC(Model View Controller 模型视图控制器)框架

Spring web MVC 框架提供了模型-视图-控制的体系结构和可以用来开发灵活、松散耦合的 web 应用程序的组件。MVC 模式导致了应用程序的不同方面(输入逻辑、业务逻辑和 UI 逻辑)的分离,同时提供了在这些元素之间的松散耦合。

  • 模型封装了应用程序数据,并且通常它们由 POJO 组成。

  • 视图主要用于呈现模型数据,并且通常它生成客户端的浏览器可以解释的 HTML 输出。

  • 控制器主要用于处理用户请求,并且构建合适的模型并将其传递到视图呈现。

DispatcherServlet

Spring Web 模型-视图-控制(MVC)框架是围绕 DispatcherServlet 设计的,DispatcherServlet 用来处理所有的 HTTP 请求和响应.

  • 收到一个 HTTP 请求后,DispatcherServlet 根据 HandlerMapping 来选择并且调用适当的控制器

  • 控制器接受请求,并基于使用的 GET 或 POST 方法来调用适当的 service 方法。Service 方法将设置基于定义的业务逻辑的模型数据,并返回视图名称到 DispatcherServlet 中。

  • DispatcherServlet 会从 ViewResolver 获取帮助,为请求检取定义视图。

  • 一旦确定视图,DispatcherServlet 将把模型数据传递给视图,最后呈现在浏览器中。

二、Spring MVC基于Annotation开发-Spring MVC环境搭建

(一)创建maven工程 

(二)添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.8</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.8</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>

(三)web.xml中配置前端控制器(核心控制器),其实就是一个Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--Spring Web MVC 框架-->

    <!--配置spring核心的DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--
        1)load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
        2)它的值必须是一个整数,表示servlet应该被载入的顺序
        3)当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
        4)当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
        5)正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
        6)当值相同时,容器就会自己选择顺序来加载。
        -->
        <!-- tomcat启动时候创建DispatcherServlet并初始化-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--正斜杠 所有的请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--配置编码过滤器(配置spring的CharacterEncodingFilter解决中文乱码)-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*</url-pattern>
    </filter-mapping>
</web-app>

(四)springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--配置扫描的基本包
    扫描四大注解的类(@Controller,@Service,@Repository,@Component),纳入springmvc管理
    -->
    <context:component-scan base-package="com.tjetc"></context:component-scan>
    <!--开启注解驱动-->
    <!--开启用后,Spring会默认帮我们注册处理请求,参数和返回值的类。
    如:将被@Controller和@RequestMapping注解的处理器方法放入了映射表,使其生效-->
    <mvc:annotation-driven></mvc:annotation-driven>
    <!--对于图片等静态资源使用默认的servlet处理器实际就是Tomcat-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>
    <!--配置视图解析器 查找指定的视图-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置视图 jstl视图 解析view的代码转换成html
            JstlView可以使用jstl解析展示数据
        -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <!--配置前缀和后缀 简化返回页面的代码
        例如: @RequestMapping注解到的方法中,return "hello" , 实际上 return "/hello.jsp" 页面
        -->
        <!--配置前缀 prefix代表自动在返回值前面添加 /-->
        <property name="prefix" value="/"></property>
        <!--配置后缀 suffix代表自动返回值后加上 .jsp-->
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

(五)HelloController

package com.tjetc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

//@Controller 注释表明一个特定类是一个控制器的作用。
@Controller
public class HelloController {
    /*@RequestMapping 注释用于映射 URL 到整个类或一个特定的处理方法。
    访问的url映射到加上@RequestMapping的方法上面,注解的值是URL
    */
    @RequestMapping("/hello")
    //ModeL对象:用来存储数据,传输的页面中,在页面就可以获取数据
    public String hello(Model model) {
        model.addAttribute("msg", "Hello Spring MVC Framework(框架)!");
        //请求转发到页面,/index.jsp 页面
        return "index";
    }
}

(六)index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Hello Spring MVC</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <%--使用el获取--%>
        <h1>${msg}</h1>
    </body>
</html>

(七)运行效果

(八)@RequestMapping 写在类上, controller 里所有的方法映射加一个前缀

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("user") //@RequestMapping 写在类上, controller 里所有的方法映射加一个前缀
public class HelloController {
    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("msg", "Hello Spring MVC Framework(框架)!");
        return "index";
    }
    @RequestMapping("/order")
    public String order(Model model) {
        model.addAttribute("msg", "order list");
        return "order";
    }
}

(九)order.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <%--使用el获取model存储的值--%>
        <h1>${msg}</h1>
    </body>
</html>

三、Spring MVC工作流程运行原理

1、 用户发送请求至前端控制器DispatcherServlet

2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、 DispatcherServlet调用HandlerAdapter处理器适配器。

5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、 Controller执行完成返回ModelAndView

7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

9、 ViewReslover解析后返回具体View

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、 DispatcherServlet响应用户。

四、SpringMVC接收请求参数的4种方式

(一)在controller使用参数接收,请求有什么参数,方法就有什么参数

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>登录</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <form action="login" method="post">
            用户名:<input type="text" name="username"/><br/>
            密码:<input type="password" name="password"/><br/>
            <input type="submit" value="登录"/><br/>
        </form>
    </body>
</html>
package com.tjetc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(Model model, String username, String password) {
        //登录判读 TODO
        model.addAttribute("username", username);
        model.addAttribute("password", password);
        return "welcome";
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Welcome</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <h1>username: ${username}</h1><br>
        <h1>password: ${password}</h1>
    </body>
</html>

(二)在controller使用参数接收, @RequstParam改变controller方法接收请求参数和使用参数不一致

 不用@RequstParam,,传值

 

@Controller
public class LoginController {
    @RequestMapping("/login")
    /*public String login(Model model, String username, String password) {*/
    public String login(Model model,String un,String pd) {
        model.addAttribute("username", un);
        model.addAttribute("password", pd);
        return "welcome";
    }
}

@RequstParam 

  • required=false 表示这个参数可以不传,传和不传 程序不会报错
  • defaultValue 表示默认值,不提交字段,使用默认值,提交字段不使用默认值, defaultValue是在required = false情况下有意义
  • required=true  表示这个参数必须传,不传的(在login.jsp删掉input的name)报400错误

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(Model model,
                        @RequestParam(value = "username") String un,
                        @RequestParam(value = "password", required = false, defaultValue = "default") String pd) {
        model.addAttribute("username", un);
        model.addAttribute("password", pd);
        //请求转发到 welcome.jsp页面
        return "welcome";
    }
}

(三)在controller使用实体类作为参数接收,请求参数作为实体类的属性

package com.tjetc.entity;
public class User {
    private String username;
    private String password;
    @Override
    public String toString() {
        return "User{" + "username='" + username + '\'' +", password='" + password + '\'' +'}'; }
    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;}
}
@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(User user, Model model){
        System.out.println("username="+user.getUsername());
        System.out.println("password="+user.getPassword());
        model.addAttribute("username", user.getUsername());
        model.addAttribute("password", user.getPassword());
        return "welcome";
    }
}

(四)restful格式接收参数

url路径传参

OrderController.java

@Controller
public class OrderController {
    @RequestMapping("/del/{id}/{state}")
    public String del(@PathVariable("id") int id,
                      @PathVariable("state") String state,
                      Model model) {
        System.out.println("id=" + id + ",支付状态:" + state);
        model.addAttribute("id", id);
        model.addAttribute("state", state);
        return "success";
    }
}

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>订单删除成功</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <h1>订单删除成功,id:${id},支付状态:${state}</h1>
    </body>
</html>

五、请求转发和重定向

(一)请求转发

默认就是请求转发

@RequestMapping("/del/{id}/{state}")
public String del(@PathVariable("id") int id,
                  @PathVariable("state") String state,
                  Model model) {
    model.addAttribute("id", id);
    model.addAttribute("state", state);
    return "success";
}

(二)重定向

return “redirect:/url”;

@RequestMapping("aa")
public String aa() {
    //重定向到订单删除成功页面
    return "redirect:/del/3/unpaid";/*中文会乱码*/
}

六、Spring MVC视图解析器

1.什么是 Spring 视图和视图解析器

Spring MVC(Model View Controller)是 Spring 中一个重要的组成部分,而 Spring 视图和视图解析器则是 Spring MVC 中的组成部分。在介绍 Spring 视图和视图解析器前,我们先了解下在 Spring MVC 框架中,一个 Web 请求所需经历的六个阶段:

  1. 请求会首先被 Spring MVC 的前端请求分发器(Dispatcher)拦截。该拦截器是一个 Servlet, 需要在 web.xml 中配置,所有符合所配置的 URL 样式的访问请求,将都会被该拦截器拦截。Spring 提供了默认的分发器 org.springframework.web.servlet.DispatcherServlet,可以根据需要,决定是否需要定制自己的分发器。
  2. 在接收到访问请求后,分发器会根据开发人员在 Spring 配置文件或代码中的注解(Annotation),来查找合适的控制器。
  3. 分发器在查找到合适的控制器后,将请求转交给该控制器处理。
  4. 通常,控制器会调用相应服务类来处理业务逻辑,在将请求处理后,控制器需返回处理后的结果数据模型(Model)以及下一个需要显示的视图名。
  5. 在控制器处理结束并返回模型和视图名之后,Spring 会依次调用 Spring 容器中所注册的视图解析器,来查找符合条件的视图。
  6. 在获得 Spring 视图后,Spring 会根据该视图的配置信息,显示该视图。
①图 1.Spring MVC 处理流程

通过以上 Spring MVC 的介绍,我们可以发现,视图和视图解析器将出现在整个请求处理流程中的最后部分。

那么到底什么是视图和视图解析器?

  简而言之,视图是指 Spring MVC 中的 V(View)

       视图解析器的功能则是依据指定的规则来查找相应的视图

2.常用视图和视图解析器简介

在开发中,视图通常就是 JSP、Velocity、FreeMarker等。Spring 默认提供了多种视图解析器,比如,我们可以使用最常用解析器 InternalResourceViewResolver 来查找 JSP 视图(与之相对应的视图类为 InternalResourceView)。通常,一个视图解析器只能查找一个或多个特定类型的视图,在遇到 Spring 不支持的视图或者我们要自定义视图查找规则的情况下,我们就可以通过扩展 Spring 来自定义自己所需的视图解析器。目前,视图解析器都需要实现接口 org.springframework.web.servlet.ViewResolver, 它包含方法 resolveViewName,该方法会通过视图名查找并返回 Spring 视图对象。表 1 列出了常用的 Spring 视图解析器。

①表 1.Spring 常用视图解析器列表

视图解析器

描述

XmlViewResolver

接口 ViewResolver 的实现,从 XML 配置文件中查找视图实现(默认 XML 配置文件为 /WEB-INF/views.xml).

ResourceBundleViewResolver

接口 ViewResolver 的实现,用于从 properties 文件中查找视图。.

UrlBasedViewResolver

接口 ViewResolver 的实现,用于根据请求的 URL 路径返回相应的视图,该视图需为抽象类 AbstractUrlBasedView 的实现,它还有些子类,如 InternalResourceView 和 JstlView 等 .

InternalResourceViewResolver

UrlBasedViewResolver 的子类,通常用于查找 JSP(类 InternalResourceView)和 JSTL(类 JstlView,InternalResourceView 的子类)等视图。

VelocityViewResolver /FreeMarkerViewResolver

UrlBasedViewResolver 的子类分别用于支持 Velocity(类 VelocityView)和 FreeMark 视图(类 FreeMarkerView)。

ContentNegotiatingViewResolver

接口 ViewResolver 的实现,用于根据请求文件的后缀名或请求的 header 中的 accept 字段查找视图。

在多数项目中,InternalResourceViewResolver 是最常用的,该解析器可以返回指定目录下指定后缀的文件,它支持 JSP 及 JSTL 等视图技术。

在 Web 开发中,我们的前端显示可以是 JSP、Excel、Velocity 、FreeMarker等,在 Spring 中,不同的前端显示技术都有其对应的 Java 视图类,正如表 1 所提到的,InternalResourceView 可以代表 JSP 视图,FreeMarkerView 代表 FreeMarker 视图。目前,Spring 支持多种技术开发的视图,包括 JSP、JSTL、Excel,Velocity、FreeMarker 等

七、Spring MVC与JSON

从Controller得到json:

controller的方法返回一个对象(实体类对象,也可是集合对象),同时标注了@ResponseBody,jackson在后台默默将对象转化为json字符串

1.SpringMVC处理json的框架是Jackson,要引入pom的依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.4</version>
</dependency>

2.在springmvc.xml配置

<!--开启注解驱动--><!-- 配置注解驱动,同时开启对json(jackson的支持)-->
<!--开启用后,Spring会默认帮我们注册处理请求,参数和返回值的类。
如:将被@Controller和@RequestMapping注解的处理器方法放入了映射表,使其生效-->
<mvc:annotation-driven></mvc:annotation-driven>

3.写controller

@Controller
@RequestMapping("/json")
public class JsonController {
    @RequestMapping("get-user")
    @ResponseBody
    public User getUser() {
        return new User("kelly", "123");
    }
}

4.浏览器运行效果

@ResponseBody

将方法的返回值写到响应体中,当controller的方法返回一个对象(实体类对象,也可是集合对象),同时标注了@ResponseBody,jackson在后台默默将对象转化为json字符串

@Controller
@RequestMapping("/json")
public class JsonController {
    @RequestMapping("get-user-list")
    @ResponseBody
    public List<User> getUserList() {
        return Arrays.asList(new User("The8", "888"),
                new User("Jun", "444"),
                new User("carat", "17526"));
    }
}

(一)课堂练习

在controller写一个方法,该方法返回值是map集合:

{"code":0,"list":[{"username":"zs","password":"123"},{"username":"ls","password":"123456"},{"username":"zl","password":"123"}]}

@Controller
@RequestMapping("/json")
public class JsonController {
    @RequestMapping("get-map")
    @ResponseBody
    public Map<String, Object> getMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("code", 0);
        map.put("list", Arrays.asList(new User("zs", "123"), new User("ls", "123456"), new User("zl", "123")));
        return map;
    }
}

  

八、拦截器

(一)什么是拦截器?适用场景?

Spring MVC的拦截器(Interceptor)与Java Servlet的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理。通常应用在权限验证、记录请求信息的日志、判断用户是否登录功能上。

(二)拦截器相关接口?

实现HandlerInterceptor接口,实现接口提供三个方法:

  • preHandle:该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作。返回true表示继续向下执行,返回false表示中断后续操作。
  • postHandle:该方法在控制器的处理请求方法调用之后,解析视图之前执行。可以通过此方法对请求域中的模型和视图做进一步的修改。
  • afterCompletion:该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。

(三)登录拦截器类

 

public class LoginInterceptor implements HandlerInterceptor {
    /**
     * preHandle
方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,
    
* SpringMVC中的Interceptor拦截器是链式的,可以同时存在
    
* 多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,
    
* 而且所有的Interceptor中的preHandle方法都会在
    
* Controller方法调用之前调用。
    
* SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返
    
* 回值为false,当preHandle的返回值为false的时候整个请求就结束了。
    
*/
   
@Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        //获取请求的URI:去除http:localhost:8080这部分剩下的
       
String uri = request.getRequestURI();
        //检查是否为需要登录后才能操作的请求
       
if (uri.indexOf("/permission") >= 0) {
            //检查是否登录
           
//获取session
           
HttpSession session = request.getSession();
            User user = (User) session.getAttribute("USER_SESSION");
            //判断session中是否有用户数据,如果有,则返回true,继续向下执行
           
if (user != null) {
                return true;
            }

//跳转到登录页面

response.sendRedirect(contextPath + "/login.jsp");

        } else {
        //不拦截
         
return true;
       }}



    /**
     *
这个方法只会在当前这个InterceptorpreHandle方法返回值为true的时候才会执行。
    
* postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之
    
* 后,也就是在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,
    
* 也就是说在这个方法中你可以对ModelAndView进行操
    
* 作。
    
*/
   
@Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub

   
}

    /**
     *
该方法也是需要当前对应的InterceptorpreHandle方法的返回值为true时才会执行。
    
* 该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行,
    
* 这个方法的主要作用是用于清理资源的,
    
* 当然这个方法也只能在当前这个InterceptorpreHandle方法的返回值为true时才会执行。
    
*/
   
@Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub

   
}
}

 

(四)springmvc.xml配置拦截器

<!--配置拦截器-->
<mvc:interceptors>
    <!--登录拦截器-->
   
<mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.tjetc.interceptor.LoginInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

 

九、Spring整合Spring MVC及MyBatis

(一)什么是SSM整合

  • SSM:Spring+Spring MVC+Mybatis 三大框架整合

(二)三大框架的角色划分和职责

1.Spring框架

  • 1.能整合各种框架
  • 2.Spring充当父容器
  • 3.ContextLoaderListener启动Spring容器,实例化Spring容器,管理bean(Service,Mapper,数据源,SqlSession,MapperScanConfiguror,Transaction),能管业务层和数据访问层

2.SpringMVC框架

  • 1.SpringMVC是子容器
  • 2.实例化SpringMVC容器(是Spring容器的子容器,子容器的bean可以访问父容器的bean),管理  bean(controller,视图解析器,CommonsMultipartResolver)
  • 3.配置扫描基本包:com.tjetc.controller,管理控制层,视图层

3.Mybatis

  • mapper,pojo,配置文件 ,映射文件

(三)父子容器的关系

  • 1.父容器是Spring容器
  • 2.子容器SpringMVC容器
  • 3.子容器的bean可以访问父容器的bean 

(四)SSM整合步骤

1.创建maven工程

2.pom.xml

<!--spring-context-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.8</version>
</dependency>
<!--spring-mvc-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.8</version>
</dependency>
<!--spring事务-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.8</version>
</dependency>
<!--spring-jdbc-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.8</version>
</dependency>
<!--mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>
<!--mybatis-spring整合-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
</dependency>
<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.27</version>
</dependency>
<!--数据源--><!--SpringBoot-->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>4.0.3</version>
</dependency>
<!--单元测试-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.8</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.7.2</version>
    <scope>test</scope>
</dependency>
<!-- aspectj 依赖--><!--AOP-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
<!--mybatis的分页插件-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.9</version>
</dependency>
<!--处理json-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.4</version>
</dependency>
<!--字符串处理--><!--StringUtils-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.11</version>
</dependency>
<!--上传文件-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
<!--JSTL-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

3.配置web

 

 

4.配置web.xml

1.ContextLoaderListener:加载实例化Spring容器(父容器)

2.配置CharacterEncodingFilter:form post提交的乱码(可选)

3.DispatcherServlet:SpringMVC容器(子容器)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置加载spring容器配置文件和spring的监听器-->

    <!--全局配置,上下文参数(spring父容器)-->
    <context-param>
        <!--contextConfigLocation上下文配置文件位置(名称)-->
        <param-name>contextConfigLocation</param-name>
        <!--classpath下的applicationContext.xml文件-->
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--配置上下文加载监听器,在web服务器Tomcat启动时,实例化spring容器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--配置编码过滤器(配置spring的CharacterEncodingFilter解决中文乱码)-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>

    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--配置spring核心的DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--
        1)load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
        2)它的值必须是一个整数,表示servlet应该被载入的顺序
        3)当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
        4)当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
        5)正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
        6)当值相同时,容器就会自己选择顺序来加载。
        -->
        <!-- tomcat启动时候创建DispatcherServlet并初始化-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--正斜杠 所有的请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

5.applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--spring容器负责管理业务层和持久层的类-->

    <!--1、配置扫描三大注解类-->
    <!--扫描带有@Service,@Repository,@Component注解类,纳入spring容器的管理,所以要排除@Controller注解的类-->
    <!--扫描com.tjetc包和子包中带有@Repositry,@Service,@Component这些注解的类,则把这些类注册为bean-->
    <!--applicationContext.xml配置了@Service类方法的事务增强处理,所以@Service类在spring容器中扫描并被管理-->
    <context:component-scan base-package="com.tjetc"><!--扫描4个-->
        <!--扫描排除掉@Controller注解类
            因为启动后spring和springmvc是2个容器,@Controller注解的类由springmvc扫描管理,配置web.xml中有体现-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>


    <!--2、配置加载properties文件和数据源-->
    <!--加载属性文件(可以加载多个properties文件)-->
    <context:property-placeholder location="classpath*:*.properties"></context:property-placeholder>
    <!--配置数据源hikariCP-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="driverClassName" value="${jdbc.driverName}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>


    <!--注解方式使用事务
    1、开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象;适合中小型项目
    <tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven>
    2、最后在service主方法上增加@Transactional
    -->


    <!--3、配置事务-->
    <!--事务管理器 声明事务管理对象-->

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置事务通知
      声明业务方法的事务属性(隔离级别(isolation)、传播行为(propagation)、超时时间(timeout))
      id是自定义名称,表示配置内容
      transaction-manager:事务管理器对象的ID-->

    <!--注解和AOP二选一,不同时使用-->
    <!--(1)AOP-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <!--tx:method:给具体的方法配置事务属性,method可以有多个,给不同的方法配置事务属性
            name:方法名,1)完整的方法名,不带包和类;2)可以使用通配符*,表示任意字符
            propagation:传播行为,枚举值
            isolation:隔离级别
            rollback-for:指定的异常类名,全限定类名,发生异常,一定回滚
            -->
            <!--使用通配符,指定很多方法-->
            <!--添加使用事务 指定新增方法-->
            <tx:method name="add*" propagation="REQUIRED"/>
            <!--更新使用事务 指定更新方法-->
            <tx:method name="update*" propagation="REQUIRED"/>
            <!--删除使用事务 指定删除方法-->
            <tx:method name="del*" propagation="REQUIRED"/>
            <!--查询方法,query,search,find方法等
            其他方法是使用只读事务, 可以提高效率-->
            <tx:method name="*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    <!--配置aop切面-->
    <aop:config>
        <!--配置切入点表达式,指定哪些包里面的哪些类需要使用事务
            配置切入点, 对service包和子孙包下所有的业务类(service)使用事务
            id:切入点表达式的名称,唯一值
            expression:切入点表达式,指定哪些包哪些类哪些方法要使用事务,aspectj会创建代理对象-->
        <aop:pointcut id="txPointCut" expression="execution(* com.tjetc.service..*.*(..))"/>
        <!--配置增强器:关联advice和pointcut
            advice-ref:通知,上面的tx:advice的配置
            pointcut-ref:切入点表达式的id
            -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
    </aop:config>

    <!--(2)通过注解配置事务
              1、开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象;适合中小型项目
              2、最后在service主方法上增加@Transactional(这个小项目在UserServiceImpl里添加注解)
    -->
    <!--<tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven>-->

    <!--4、配置mybatis-->
    <!--配置sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置mybatis.xml的配置文件-->
        <property name="configLocation" value="classpath:mybatis.xml"></property>
        <!--配置mybatis的数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <!--配置mapper映射文件的文件,自动扫描mapper.xml文件-->
        <property name="mapperLocations" value="classpath:com/tjetc/dao/*.xml"/>
    </bean>
    <!--配置mybatis的dao扫描(扫描映射接口)-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <!--配置映射接口所在的包
        mybatis对spring支持,扫描mapper下的Mapper接口,生成代理bean交给spring管理-->
        <property name="basePackage" value="com.tjetc.dao"></property>
    </bean>
</beans>

6.db.properties

jdbc.driverName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456

7.mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <typeAliases>
        <package name="com.tjetc.entity"/>
    </typeAliases>
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
</configuration>

8.springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--springmvc子容器只管理控制层-->

    <!--扫描使用注解的类(@Controller,纳入springmvc管理-->
    <context:component-scan base-package="com.tjetc.controller"></context:component-scan>

    <!--开启注解驱动--><!-- 配置注解驱动,同时开启对json(jackson的支持)-->
    <!--开启用后,Spring会默认帮我们注册处理请求,参数和返回值的类。
    如:将被@Controller和@RequestMapping注解的处理器方法放入了映射表,使其生效-->
    <mvc:annotation-driven></mvc:annotation-driven>
    <!--对于图片等静态资源使用默认的servlet处理器实际就是Tomcat-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>
    <!--配置视图解析器 查找指定的视图-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置视图 jstl视图 解析view的代码转换成html
            JstlView可以使用jstl解析展示数据
        -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <!--配置前缀和后缀 简化返回页面的代码
        例如: @RequestMapping注解到的方法中,return "hello" , 实际上 return "/hello.jsp" 页面
        -->
        <!--配置前缀 prefix代表自动在返回值前面添加 /-->
        <property name="prefix" value="/"></property>
        <!--配置后缀 suffix代表自动返回值后加上 .jsp-->
        <property name="suffix" value=".jsp"></property>
    </bean>


    <!--配置拦截器-->
    <!--    <mvc:interceptors>
            <mvc:interceptor>
                &lt;!&ndash;登录拦截器&ndash;&gt;
                <mvc:mapping path="/user/**"/>
                <bean class="com.tjetc.interceptor.LoginInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>-->


</beans>

9.User

package com.tjetc.entity;
public class User {
    private Long id;
    private String username;
    private String password;
    public User() {}
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    public Long getId() {return id; }
    public void setId(Long 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; }
}

10.UserMapper.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.tjetc.dao.UserMapper">
    <!--
    '%${username}%'直接拼接参数,有SQL注入的风险
    #{username}更安全-->
    <!--
      <if test="username!=null and username!=''">
      判断username不为null且不为空字符串
    -->
    <select id="selectAllForLike" resultMap="userMap">
        select id,username,`password` from user
        <where>
            <if test="username!=null and username!=''">
                username like concat('%',#{username},'%')
            </if>
        </where>
    </select>
    <resultMap id="userMap" type="user">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>
    </resultMap>
    <select id="selectById" resultMap="userMap">
        select id,username,`password` from user where id=#{id}
    </select>
    <update id="update" parameterType="user">
        update `user`
        <set>
            <if test="username!=null and username!=''">
                username = #{username},
            </if>
            <if test="password!=null and password!=''">
                password = #{password},
            </if>
        </set>
        where id=#{id}
    </update>
    <delete id="delete" parameterType="long">
        delete from user where id = #{id}
    </delete>
    <insert id="add" parameterType="user">
        insert into user(username,password) values (#{username},#{password})
    </insert>
</mapper>

 11.UserMapper.java

package com.tjetc.dao;
import com.tjetc.entity.User;
import java.util.List;
public interface UserMapper {
    List<User> selectAllForLike(String username);
    User selectById(Long id);
    int update(User user);
    int delete(Long id);
    void add(User user);
}

12.UserService.java

package com.tjetc.service;
import com.github.pagehelper.PageInfo;
import com.tjetc.entity.User;
import org.springframework.stereotype.Service;
import java.util.List;
public interface UserService {
    /** 用户名分页模糊查询
     * @param username 用户名
     * @param pageNo   页码
     * @param pageSize 每页数量
     * @return
     */
    PageInfo<User> findPageForLike(String username, int pageNo, int pageSize);
    /**根据id查询用户
     * @param id
     * @return
     */
    User findById(Long id);
    /** 更新用户
     * @param user
     * @return
     */
    boolean updateUser(User user);
    /**根据id删除用户
     * @param id
     * @return
     */
    boolean delete(Long id);
    /** 添加新用户
     * @param user
     */
    void add(User user);
}

13.UserServiceImpl.java

package com.tjetc.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tjetc.dao.UserMapper;
import com.tjetc.entity.User;
import com.tjetc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public PageInfo<User> findPageForLike(String username, int pageNo, int pageSize) {
        //设置页码和每页数量
        PageHelper.startPage(pageNo, pageSize);
        List<User> users = userMapper.selectAllForLike(username);
        //users集合对象包装PageInfo对象
        PageInfo<User> userPageInfo = new PageInfo<>(users);
        return userPageInfo;
    }
    @Override
    public User findById(Long id) {
        User user = userMapper.selectById(id);
        return user;
    }
    @Override
    public boolean updateUser(User user) {/*effectCount影响行数*/
        int effectCount = userMapper.update(user);
        return effectCount > 0;
    }
    @Override
    public boolean delete(Long id) {
        int effectCount = userMapper.delete(id);
        return effectCount > 0;
    }
    /*@Transactional//注解方式使用事务*/
    @Override
    public void add(User user) {
        userMapper.add(user);
    }
}

14.UserController.java

package com.tjetc.controller;
import com.github.pagehelper.PageInfo;
import com.tjetc.entity.User;
import com.tjetc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("user")
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("page")
    public String findPage(@RequestParam(value = "username", required = false) String username,
                           @RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
                           @RequestParam(value = "pageSize", required = false, defaultValue = "5") Integer pageSize,
                           Model model) {
        PageInfo<User> userPageInfo = userService.findPageForLike(username, pageNo, pageSize);
        model.addAttribute("userPageInfo", userPageInfo);
        model.addAttribute("username", username);
        //请求转发
        return "user-list";
    }
    @RequestMapping("edit/{id}")
    public String edit(@PathVariable("id") Long id, Model model) {
        User user = userService.findById(id);
        model.addAttribute("user", user);
        return "user-edit";
    }
    @RequestMapping("save")
    public String save(User user) {
        boolean bl = userService.updateUser(user);
        return "redirect:/user/page";
    }
    @RequestMapping("save1")
    public String save1(User user) {
        userService.add(user);
        return "redirect:/user/page";
    }
    @RequestMapping("delete/{id}")
    public String delete(@PathVariable("id") Long id) {
        boolean bl = userService.delete(id);
        return "redirect:/user/page";
    }
    @RequestMapping("add")
    public String add(User user) {
        return "user-add";
    }
}

15.user-add.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>添加新用户</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <form method="post" action="user/save1">
            用户名:<input type="text" name="username" value="${user.username}"><br>
            密码:<input type="password" name="password" value="${user.password}"><br>
            <input type="submit" value="保存"><br>
            <input type="button" value="返回" onclick="goBack()"/><br/>
        </form>
    </body>
    <script>
        function goBack() {
            window.history.go(-1);
        }
    </script>
</html>

16.user-list.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <head>
        <title>Title</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <form action="user/page" method="post">
                用户名:<input type="text" name="username" value="${username}" id="username"/> &nbsp;
                <input type="submit" value="查询"/><br/>
        </form>
        <c:if test="${userPageInfo!=null}">
            <%--<h3><a href="user/add">新增</a></h3>--%>
            <input type="button" value="新增" onclick="window.location.href='user/add'">
            <table border="1" cellpadding="1" cellspacing="0">
                <tr>  
                    <th>序号</th>
                    <th>用户名</th>
                    <th>密码</th>
                    <th colspan="2">操作</th>
                </tr>
                <c:forEach items="${userPageInfo.list}" var="user">
                    <tr>
                        <td>${user.id}</td>
                        <td>${user.username}</td>
                        <td>${user.password}</td>
                            <%--请求edit(编辑)的URL--%>
                        <td><a href="user/edit/${user.id}">更新</a></td>
                        <td><a href="user/delete/${user.id}" onclick="return confirm('是否删除该用户?')">删除</a></td>
                    </tr>
                </c:forEach>
            </table>
            <%--<c:if test="${userPageInfo.isFirstPage}">--%>
            <input type="button" value="首页" onclick="query('${userPageInfo.navigateFirstPage}')">
            <%--</c:if>--%>
            <c:if test="${userPageInfo.hasPreviousPage}">
                <input type="button" value="前一页" onclick="query('${userPageInfo.prePage}')">
            </c:if>
            <c:forEach items="${userPageInfo.navigatepageNums}" var="num">
                <input type="button" value="${num}" onclick="query('${num}')">
            </c:forEach>
            <c:if test="${userPageInfo.hasNextPage}">
                <input type="button" value="后一页" onclick="query('${userPageInfo.nextPage}')">
            </c:if>
            <%--<c:if test="${userPageInfo.isLastPage}">--%>
            <input type="button" value="尾页" onclick="query('${userPageInfo.navigateLastPage}')">
            <%--</c:if>--%>
        </c:if>
    </body>
    <script>
        function query(pageNo) {
            let username = document.getElementById("username").value;
            window.location.href = "user/page?username=" + username + "&pageNo=" + pageNo;
        }
    </script>
</html>

17.user-edit.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>更新</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <form action="user/save" method="post">
            <%--隐藏id--%>
            <input type="hidden" name="id" value="${user.id}">
            用户名:<input type="text" value="${user.username}" disabled/><br/><%--不可修改--%>
            密码:<input type="password" name="password" value="${user.password}"/><br/>
            <input type="submit" value="保存"/><br/>
            <input type="button" value="返回" onclick="goBack()"/><br/>
        </form>
    </body>
    <script>
        function goBack() {
            window.history.go(-1);
        }
    </script>
</html>

 

posted @ 2022-06-26 14:16  carat9588  阅读(601)  评论(1编辑  收藏  举报