SpringMVC

1 简介

Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 Servlet。

MVC结构:

 M 代表 模型(Model):数据,就是 dao,bean
V 代表 视图(View)    :网页, JSP,用来展示模型中的数据
C 代表 控制器(controller) :控制器的作用就是把不同的数据(Model),显示在不同的视图(View)上,Servlet 扮演的就是这样的角色。

 Spring MVC结构

2 Demo案例

 2.1 注解详解

@Controller 注解,添加在类上,表示这是控制器 Controller对象。

  • name 属性:该 Controller 对象的 Bean 名字。允许空。

@RequestMapping 注解,添加在类或方法上,标记该类/方法对应接口的配置信息。

  • path 属性:接口路径。[] 数组,可以填写多个接口路径。
  • values 属性:和 path 属性相同,是它的别名。
  • method 属性:请求方法 RequestMethod ,可以填写 GET、POST、POST、DELETE 等等。[] 数组, 可以填写多个请求方法。如果为空,表示匹配所有请求方法。
  • params 属性:请求参数需要包含值的参数名,可为空。
  • consumes 属性:提交内容类型( Content-Type )

@RequestParam注解,添加在方法参数上,标记该方法参数对应的请求参数的信息。

  • name 属性:对应的请求参数名。如果为空,则直接使用方法上的参数变量名。
  • value 属性:和 name 属性相同,是它的别名。
  • required 属性:参数是否必须传。默认为 true ,表示必传。
  • defaultValue 属性:参数默认值。

2.2 传统MVC的实现

 1)配置 

web.xml 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <context-param>
        <param-name>log4jConfiguration</param-name>
        <param-value>/WEB-INF/log4j2.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--最新的MVC方式 -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--传统的MVC方式 -->
    <servlet>
        <servlet-name>CheckIn</servlet-name>
        <servlet-class>Servlet.CheckIn</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CheckIn</servlet-name>
        <url-pattern>/CheckIn</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>UserRegister</servlet-name>
        <servlet-class>Servlet.UserRegister</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>UserRegister</servlet-name>
        <url-pattern>/UserRegister</url-pattern>
    </servlet-mapping>
</web-app>

 dispatcher-servlet.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: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/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <bean id="simpleUrlHandlerMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <!-- /hello 路径的请求交给 id 为 helloController 的控制器处理-->
                <prop key="/hello">hello</prop>
            </props>
        </property>
    </bean>
    <bean id="hello" class="control.hello"></bean>
    <!--配置静态资源允许访问 -->
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/assets/**" location="/assets/"/>

</beans>

2)Bean

package Bean;

public class User {
    private String id;
    private String number;
    private String password;
    private String name;
    private String sex;
    private String address;

    public User(String id ,String number,String password) {
        super();
        this.id = id;
        this.number = number;
        this.password = password;
    }

    public User(String number, String password) {
        super();
        this.number = number;
        this.password = password;
    }

    public User(String number, String password,String name,String sex,String address) {
        super();
        this.number = number;
        this.password = password;
        this.name = name;
        this.sex = sex;
        this.address = address;
    }

   
    省略get / set

    /*
    create table student(
    id int(3) primary key auto_increment,
    number char(11) not null,
    password char(20) not null,
    name varchar(20) not null,
    sex char(2) not null,
    address varchar(40)
)
     */
}

3)DButil

public class DBUtil {
    private static Logger logger= LogManager.getLogger();
    private static final String url = "jdbc:mysql://localhost:3306/iast1" + "?useSSL=true&characterEncoding=UTF-8";
    private static final String USERNAME = "root";
    private static final String PWD = "root";
    public static Connection con = null;
    public static PreparedStatement pstmt = null;
    public static ResultSet res = null;

    public static ResultSet executeQuery(String sql, Object...params) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection(url, USERNAME, PWD);
            pstmt = con.prepareStatement(sql);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            res = pstmt.executeQuery();
            logger.info("执行的SQL语句:"+pstmt.toString());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    public static boolean executeUpdate(String sql, Object...params) {
        int result = -1;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection(url, USERNAME, PWD);
            pstmt = con.prepareStatement(sql);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            result = pstmt.executeUpdate();
            logger.info("执行的SQL语句:"+pstmt.toString());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Close();
        }
        return result > 0 ? true : false;
    }

    public static void Close() {
        try {
            if (res != null)
                res.close();
            if (pstmt != null)
                pstmt.close();
            if (con != null)
                con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

4)LoginDAO

public class LoginDao {

    public int Login(User user) {
        int flag = -1;
        String sql = "select * from student where number = ? and password = ? ";
        ResultSet res = DBUtil.executeQuery(sql, user.getNumber(), user.getPassword());
        try {
            if (res.next()){
                flag = 1;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return flag;
    }

    public int register(User user) {
        int flag = -1;
        String sql = "insert into student(id,number,password,name,sex,address) values(null,?,?,?,?,?)";
        Boolean res = DBUtil.executeUpdate(sql, user.getNumber(), user.getPassword(),
                user.getName(),user.getSex(), user.getAddress());
        if (res){
            flag = 1;
        }
        return flag;
    }

    public int Check(User user) {
        int flag = -1;
        String sql = "select * from student where number = ? ";
        ResultSet res = DBUtil.executeQuery(sql, user.getNumber());
        try {
            if (res.next()) {
               flag = 1;
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return flag;
    }

}

5)CheckIn

public class CheckIn extends HttpServlet {

    private static Logger logger= LogManager.getLogger();
    public CheckIn() {
        super();
    }
    public void destroy() {
        super.destroy(); // Just puts "destroy" string in log
        // Put your code here
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String number=request.getParameter("number");
        String password=request.getParameter("password");
        User user=new User(number,password);
        LoginDao dao=new LoginDao();
        int result=dao.Login(user);
        if(result > 0) {
            request.setAttribute("number", number);
            logger.info("学号:"+number+" 尝试登陆成功");
            request.getRequestDispatcher("welcome.jsp").forward(request,response);
        }else {
            logger.error("学号:"+number+" 尝试登录失败");
            response.sendRedirect("error/loginFail.jsp");
        }
    }
    public void init() throws ServletException {
        // Put your code here
    }
}

6)jsp

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <link rel="stylesheet" type="text/css" href="css/login.css">
</head>
<body>
<div id="content">
    <div class="login-header">
        <img src="assets/images/icon.png"/>
    </div>
    <form action="CheckIn" method="post">
        <div class="login-input-box">
            <label for="number">学号:</label> <input type="text" name="number" id="number" placeholder="请输入学号!" required>
        </div>
        <div class="login-input-box">
            <label for="password">密码:</label> <input type="password" name="password" id="password" placeholder="请输入密码!" required>
        </div>
        <div class="remember-box">
            <label>
                <input type="checkbox">&nbsp;Remember Me
            </label>
        </div>
        <div class="login-button-box">
            <input type="submit" name="登录" value="登录">
        </div>
    </form>
    <div class="logon-box">
        <a href = "http://127.0.0.1:8080/Spring_MVC_Test_war_exploded/register.jsp">点击注册</a>
        <a href="">Forgot</a>
    </div>
</div>
</body>
</html>

Welcome.jsp 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功界面</title>
</head>
<body>
<%
    request.setCharacterEncoding("utf-8");
    String number = (String) request.getAttribute("number");
    out.println(number);
%>
</body>
</html>

2.3 SpringMVC实现

1 HandlerInterceptor

在使用 SpringMVC 的时候,我们可以使用 HandlerInterceptor ,拦截 SpringMVC 处理请求的过程,自定义前置和处理的逻辑。

  • 日志拦截器,记录请求与响应
  • 认证拦截器,解析前端传入的用户标识,例如access_token 访问令牌,记录到 ThreadLocal 中。
  • 授权拦截器,我们可以通过每个 API 接口需要的授权信息,进行判断,当前请求是否允许访问。
  • 限流拦截器,我们可以通过每个 API 接口的限流配置,进行判断,当前请求是否超过允许的请求频率。

多个 HandlerInterceptor 可以组成一个 Chain 拦截器链。那么,整个正常执行的过程,就变成:

  1. 首先,按照 HandlerInterceptor 链的正序,执行 #preHandle(...) 方法。
  2. 然后,执行 handler 的逻辑处理。
  3. 之后,按照 HandlerInterceptor 链的倒序,执行 #postHandle(...) 方法。
  4. 最后,按照 HandlerInterceptor 链的倒序,执行 #afterCompletion(...) 方法。

 执行流程如下:

// 首先,按照 HandlerInterceptor 链的**正序**,执行 `preHandle(...)` 方法。
INFO Interceptors.FirstInterceptor    : [preHandle]
INFO Interceptors.ThirdInterceptor    : [preHandle]

// 然后,执行 `handler` 的逻辑处理。
INFO springdockfiledemo.Control.DemoTest  : 
[ineceptorTest start to do something ...]

// 之后,按照 HandlerInterceptor 链的**倒序**,执行 `postHandle(...)` 方法。
INFO Interceptors.ThirdInterceptor    : [postHandle]
INFO Interceptors.FirstInterceptor    : [postHandle]

// 最后,按照 HandlerInterceptor 链的**倒序**,执行 `afterCompletion(...)` 方法。
INFO Interceptors.ThirdInterceptor    : [afterCompletion]
ERROR servlet.HandlerExecutionChain    : HandlerInterceptor.afterCompletion threw exception

java.lang.RuntimeException: 故意抛个错误
INFO Interceptors.FirstInterceptor    : [afterCompletion]

 2 核心代码

1)User类

@Data
public class User {
    private Integer id;
    private String name;
}

2)Servlet、Filter、Listener  配置

(1)通过 Bean 的方式

@Bean
public ServletRegistrationBean testServlet01() {
    ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean<>(new HttpServlet() {

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            logger.info("[doGet][uri: {}]", req.getRequestURI());
        }

    });
    servletRegistrationBean.setUrlMappings(Collections.singleton("/test/01"));
    return servletRegistrationBean;
}

@Bean
public FilterRegistrationBean testFilter01() {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(new Filter() {

        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            logger.info("[doFilter]");
            filterChain.doFilter(servletRequest, servletResponse);
        }

    });
    filterRegistrationBean.setUrlPatterns(Collections.singleton("/test/*"));
    return filterRegistrationBean;
}

@Bean
public ServletListenerRegistrationBean<?> testListener01() {
    return new ServletListenerRegistrationBean<>(new ServletContextListener() {

        @Override
        public void contextInitialized(ServletContextEvent sce) {
            logger.info("[contextInitialized]");
        }

        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }

    });
}
(2)通过注解的方式
@WebServlet(urlPatterns = "/test/02")
public class TestServlet02 extends HttpServlet {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        logger.info("[doGet][uri: {}]", req.getRequestURI());
    }

}

// TestFilter02.java
@WebFilter("/test/*")
public class TestFilter02 implements Filter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        logger.info("[doFilter]");
        filterChain.doFilter(servletRequest, servletResponse);
    }

}

// TestServletContextListener02.java
@WebListener
public class TestServletContextListener02 implements ServletContextListener {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        logger.info("[contextInitialized]");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值