脚本宝典收集整理的这篇文章主要介绍了day46_springmvc,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
异常处理两种方式
自定义异常处理器
简单异常处理器
HandlerExceptionResolver
,自定义异常处理器
SimpleMappingExceptionResolver
HandlerExceptionResolver
接口<dependencies>
<!--servlet-api-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Controller01 {
@RequestMapping("/show")
public void show(int no){
if(no == 1 ){
throw new NullPointerException("出现空指针异常了~!");
}else if(no == 2) {
throw new ClassCastException("出现类型转化异常了~!");
}else{
throw new RuntimeException("出现运行时异常了~!");
}
}
}
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/10/6
Time: 8:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!${msg}</h2>
</body>
</html>
package com.itheima.exception;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
自定义异常处理器
1. 定义类,实现接口HandlerExceptionResolver
2. 实现方法resolveException方法,通过返回值来跳转到页面,带上数据显示
3. 要配置这个类,只要把这个类交给spring管理即可
*/
//@Component
public class MyExceptionResolver implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//1. 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
//2. 设置跳转的页面
mv.setViewName("error");
//3. 设置数据
mv.addObject("msg" , ex.getMessage());
return mv;
}
}
<?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">
<!--1. 扫描包-->
<context:component-scan base-package="com.itheima"/>
<!--2. 注解驱动-->
<mvc:annotation-driven/>
<!--3. 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--4. 静态资源处理-->
<mvc:default-servlet-handler/>
</beans>
SpringMVC已经定义好了异常处理器,在使用时根据项目情况,配置异常与视图的映射关系
SimpleMappingExceptionResolver
error02.jsp
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/10/6
Time: 8:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!22222222</h2>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/10/6
Time: 8:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!2 空指针异常!</h2>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/10/6
Time: 8:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!2 类型转换异常!</h2>
</body>
</html>
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--1. 扫描包-->
<context:component-scan base-package="com.itheima"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:default-servlet-handler/>
<!--
5. 配置简单异常处理器
5.1 只要配置这个类SimpleMappingExceptionResolver ,注入属性即可
defaultErrorView : 通用的异常映射,只要报错就会跳转到这个指定的error02页面
exceptionMappings:给某一种特定的异常,指定的跳转的页面,如果出现了这种特定的异常
那么springmvc就会跳转到这些页面,而不是通用的页面!
-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="error02"/>
<property name="exceptionMappings">
<props>
<prop key="java.lang.NullPointerException">nullpoint</prop>
<prop key="java.lang.ClassCastException">classcast</prop>
</props>
</property>
</bean>
</beans>
HandlerExceptionResolver
接口:编写代码处理异常区别 | 过滤器Filter | 拦截器 |
---|---|---|
使用范围 | 是Servlet规范的一部分,任何Javaweb项目都可以使用 | 是SpringMVC自己的,只有使用了SpringMVC框架,才可以使用拦截器 |
拦截范围 | 配置了urlPatterns="/*"之后,可以对所有要访问的资源进行拦截 | 如果配置的是 /** , 会拦截DispatcherServlet抓到的所有资源(请求) |
拦截精度 | 只能拦截某个请求,不能对Servlet里某个方法进行拦截 , | 可以精细到拦截Controller里的某个方法 |
Controller01
,准备一个目标方法show()
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Controller01 {
@RequestMapping("/show")
public String show(){
System.out.println("调用了Controller01的show方法~!");
return "success";
}
}
HandlerInterceptor
接口
preHandle, postHandle, afterCompletion
HandlerInterceptor
接口package com.itheima.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
定义拦截器
1. 定义类,实现接口HandlerInterceptor
2. 重写3个方法 preHandle | postHandle | afterCompletion
*/
public class MyInterceptor implements HandlerInterceptor {
//拦截到请求的时候调用
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return false;
}
//controller方法调用之后,执行这个方法
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
//页面渲染完毕之后,调用这个方法!
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
<?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">
<!--1. 扫描包-->
<context:component-scan base-package="com.itheima"/>
<!--2. 注解驱动-->
<mvc:annotation-driven/>
<!--3. 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--4. 静态资源处理-->
<mvc:default-servlet-handler/>
<!--5. 配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/show"/>
<bean class="com.itheima.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
拦截器的处理结果,莫过于两种:
放行: 如果后面还有拦截器就执行下一个拦截器,如果后面没有了拦截器,就执行Controller方法
拦截: 但是注意,拦截后也需要返回到一个具体的结果(页面,Controller)。
package com.itheima.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
定义拦截器
1. 定义类,实现接口HandlerInterceptor
2. 重写3个方法 preHandle | postHandle | afterCompletion
*/
public class MyInterceptor implements HandlerInterceptor {
/*
拦截到请求的时候调用, 可以在这个方法里面拦截请求或者放行请求, 到底放行还是不放行,取决于返回值。
返回true : 即表示放行这个请求,把这个请求交给下一个拦截器或者controller去处理
返回false : 即表示不放行!不放行请求,也需要对这个请求进行处理,一般有两种方式:
1. 直接把一句简单的话写出去!
2. 也可以跳转到某一个页面
2.1 跳转页面的时候,可以使用请求转发,也可以使用重定向来跳转
2.2 跳转页面的路径写法最好使用绝对路径的写法,尽量不要使用相对路径来跳转!。
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
//1. 作出响应: 把一句简单的话写出去!
//response.setContentType("text/html;charset=utf-8");
//response.getWriter().write("您没有访问权限!");
//2. 作出响应: 跳转到某个页面 :index.jsp
//request.getRequestDispatcher("/index.jsp").forward(request,response);
//response.sendRedirect("/index.jsp");
return false;
}
}
<!--
5. 配置拦截器
mvc:interceptors : 用来配置拦截器的,可以配置很多个拦截器
mvc:interceptor : 用来配置拦截器,具体的配置
mvc:mapping:用于配置拦截什么样的地址
path: 指定具体拦截的地址
bean : 配置具体的拦截器来,也就是用什么拦截器去拦截上面的请求地址!
-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截路径解释:
1. 可以拦截具体某一种请求路径
path="/show" =========== localhost:82/show 可以拦截
path="/show" =========== localhost:82/haha 不可以拦截
2. 也可以使用通配符来拦截某一类|所有的请求 (仅局限于DispatcherServlet能抓到的请求)
/user/** =========== localhost:82/user/add localhost:82/user/update/a/b/c 可以拦截
/** =========== 只要是DispatcherServlet能抓到的请求,都能拦截
/* 只能匹配一级目录下的任意名字
/** 能匹配任意级别目录下的任意名字。
2.1 为什么配置成/**了之后, jsp页面不拦截,但是静态资源就会拦截呢?
a. DispatcherServlet 映射路径是 / 覆盖了Tomcat了里面的DefaultServlet的 / 所以能抓到静态资源的
请求,也就能拦截静态资源
b. 之所以没有办法拦截jsp的页面,是因为DispatcherServlet没有办法抓到有关jsp页面的请求,
DispatcherServlet 映射路径是 /
Tomcaty里面处理jsp页面请求的 JspServlet 映射路径是 *.jsp
*.jsp > /
3. 可以在这里让这个拦截器,不要拦截静态资源。
<mvc:exclude-mapping path="/html/**"/>
<mvc:exclude-mapping path="/css/**"/>
<mvc:exclude-mapping path="/js/**"/>
-->
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/html/**"/>
<mvc:exclude-mapping path="/css/**"/>
<mvc:exclude-mapping path="/js/**"/>
<bean class="com.itheima.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
package com.itheima.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
定义拦截器
1. 定义类,实现接口HandlerInterceptor
2. 重写3个方法 preHandle | postHandle | afterCompletion
*/
public class MyInterceptor implements HandlerInterceptor {
...
//controller方法调用之后,执行这个方法 , 如果controller方法不执行,那么这个postHandle方法不会执行!
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
//页面渲染完毕之后,调用这个方法!
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
我们可以配置多个拦截器, 所以就存在一个优先级问题了.多个拦截器的优先级是按照配置的顺序决定的。
拦截器1
package com.itheima.interceptor02;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor01 implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor01::preHandle...");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor01::postHandle...");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor01::afterCompletion...");
}
}
拦截器2
package com.itheima.interceptor02;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor02 implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor02::preHandle...");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor02::postHandle...");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor02::afterCompletion...");
}
}
拦截器3
package com.itheima.interceptor02;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor03 implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor03::preHandle...");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor03::postHandle...");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor03::afterCompletion...");
}
}
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Controller01 {
@RequestMapping("/show")
public String show(){
System.out.println("调用了Controller01 的show方法~!");
return "success";
}
}
<!--拦截器链-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/show"/>
<bean class="com.itheima.interceptor02.MyInterceptor01"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/show"/>
<bean class="com.itheima.interceptor02.MyInterceptor02"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/show"/>
<bean class="com.itheima.interceptor02.MyInterceptor03"/>
</mvc:interceptor>
</mvc:interceptors>
拦截器属于链式模式
只有preHandler方法才有返回true 放行,false 拦截
拦截后也需要对此次请求做出响应(跳转页面|跳转Controller)
拦截器执行方法顺序 preHandle->postHandle->afterCompletion
存在拦截器链时,按照配置文件顺序执行,自上而下。先进(preHandle)后出(postHandle,afterCompletion)
当我们的springmvc配置了静态资源处理,并且拦截器配置成了 /** ,那么拦截器也会拦截静态资源。如果非要让拦截器不拦截静态资源:
手动指定静态资源的路径,然后拦截器排除具体静态资源
mvc:default-servlet-handler 和 拦截器 /** 还是照常写
需要在web.xml中,添加DefaultServlet的映射路径
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
<url-pattern>*.html</url-pattern>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
create database ssm;
use ssm;
create table account(
id int primary key auto_increment,
name varchar(40),
money double
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('zs',1000);
insert into account(name,money) values('ls',1000);
insert into account(name,money) values('ww',1000);
创建web项目
导入依赖
<properties>
<!-- 版本锁定 -->
<spring.version>5.0.2.RELEASE</spring.version>
<log4j.version>1.2.17</log4j.version>
<slf4j.version>1.6.6</slf4j.version>
<mysql.version>5.1.47</mysql.version>
<mybatis.version>3.4.6</mybatis.version>
</properties>
<dependencies>
<!--Spring:ioc和aop,事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!--SpringMVC,jstl,json转换-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
</dependencies>
package com.itheima.bean;
import lombok.Data;
@Data
public class Account {
private int id;
private String name;
private double money;
}
在resource目录下创建一个
log4j.properties
文件
##设置日志记录到控制台的方式
log4j.appender.std=org.apache.log4j.ConsoleAppender
log4j.appender.std.Target=System.err
log4j.appender.std.layout=org.apache.log4j.PatternLayout
log4j.appender.std.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n
##设置日志记录到文件的方式
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=mylog.txt
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
##日志输出的级别,以及配置记录方案 debug info warn error
log4j.rootLogger= trace,std,file
package com.itheima.controller;
import com.itheima.bean.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
public class AccountController {
/*
查询所有
*/
@RequestMapping("/findAll")
public String findAll(){
System.out.println("调用了AccountController的findAll方法~!");
return "success";
}
}
<?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">
<!--1. 扫描包-->
<context:component-scan base-package="com.itheima"/>
<!--2. 注解驱动-->
<mvc:annotation-driven/>
<!--3. 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--4. 静态资源处理-->
<mvc:default-servlet-handler/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--配置前端控制器 DispatcherServlet-->
<servlet>
<servlet-name>dispatcher</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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--springmvc已经定义好了过滤器,可以帮助我们解决post请求,中文乱码的问题,我们只需要配置即可-->
<filter>
<filter-name>char</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>char</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
package com.itheima.service;
import com.itheima.bean.Account;
import java.util.List;
public interface AccountService {
/*
查询所有账户
*/
List<Account> findAll();
}
package com.itheima.service.impl;
import com.itheima.bean.Account;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@Service
public class AccountServiceImpl implements AccountService {
public List<Account> findAll() {
System.out.println("调用了AccountServiceImpl的findAll方法~!~");
return null;
}
}
package com.itheima.controller;
import com.itheima.bean.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
public class AccountController {
//注入service
@Autowired
private AccountService as;
/*
查询所有
*/
@RequestMapping("/findAll")
public String findAll(){
System.out.println("调用了AccountController的findAll方法~!");
//调用service
List<Account> list = as.findAll();
System.out.println("list = " + list);
return "success";
}
}
package com.itheima.dao;
import com.itheima.bean.Account;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;
import java.util.List;
public interface AccountDao {
@Select("select * from account")
List<Account> findAll();
}
<?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>
<!--核心配置文件,包含两部分内容: 如何连接数据库, dao文件|映射在哪里-->
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.itheima.dao"/>
</mappers>
</configuration>
package com.itheima.test;
import com.itheima.bean.Account;
import com.itheima.dao.AccountDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestAccountDao {
@Test
public void testFindAll() throws IOException {
//1. 读取核心配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2. 构建构建器SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3. 构建SqlSessionFactory
SqlSessionFactory sessionFactory = builder.build(is);
//4. 构建SqlSession
SqlSession session = sessionFactory.openSession();
//5. 问SqlSession要dao的代理对象
AccountDao dao = session.getMapper(AccountDao.class);
//6. 调用方法
List<Account> list = dao.findAll();
System.out.println("list = " + list);
//7. 收尾: 关闭sqlsession | 提交事务
session.commit();
session.close();
}
}
- 引入外部的数据源(连接池)
- 由Spring来管理SqlSessionFactory工厂
- 由Spring来扫描dao接口包
- 这么做的目的只有一个: 就是顶替掉mybatis的核心配置文件SqlMapConfig.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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1. 导入外部的连接池(数据源)-->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${db.driverClass}"/>
<property name="jdbcUrl" value="${db.jdbcUrl}"/>
<property name="user" value="${db.user}"/>
<property name="password" value="${db.password}"/>
</bean>
<!--
2. 由Spring来接管mybatis的SqlSessionFactory工厂
2.1 由Spring来接管|创建SqlSessionFactory工厂是有好处的。
2.2 其实在背后Spring不仅创建了SqlSessionFactory的工厂,它还会创建出来SqlSession对象
2.3 不仅创建了SqlSession对象,还会创建出来dao的代理对象,并且会把这个代理对象丢到
Spring的容器|工厂里面管理起来。
2.4 这样子做了之后,我们在service层里面想要dao对象就很简单了,只要让spring注入即可!
-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--由于SqlsessionFactory最终是可以操作数据库的,所以要给它注入DataSource-->
<property name="dataSource" ref="dataSource"/>
<!--给JavaBean类起别名-->
<property name="typeAliasesPackage" value="com.itheima.bean"/>
<!--可以把一部分内容配置在SQLMapConfig.xml里面,然后在这里导入!-->
<!--<property name="configLocation" value="SqlMapConfig.xml"/>-->
</bean>
<!--3. 由Spring来扫描 dao| 映射文件-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.itheima.dao"/>
</bean>
</beans>
mybatis默认不会自动提交: setAutoCommit(false) , 所以对于增伤改的动作,需要提交事务才行。在 applicationContext.xml中编写
<!--
4. 由Spring来管理事务
4.1 Spring管理事务,有一个特征: 就是由管理员来管理事务
4.2 管理员是谁,得看dao层使用的技术来决定。
如果dao层使用的技术是 jdbc|mybatis ======= DataSourceTransactionManager
如果dao层使用的技术是 hibernate ========= HibernateTransactionManager
4.3 操作事务需要用到连接对象,所以要把DataSource对象给注入进来
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务的注解开关-->
<tx:annotation-driven transaction-manager="transactionManager"/>
由于配置
springmvc
的时候,写了springmvc.xml
, 配置Mybatis
的时候,有applicationContext.xml
但是项目启动的时候,解析的入口是在web.xml
里面配置。此时存在两个文件,如何抉择呢?有三种方式可供选择。
方式一:别写applicationContext.xml了, 直接把applicationContext.xml里面的配置定义在springmvc.xml
方式二: 名字上面下功夫.
<!--初始化参数:加载配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</init-param>
在springmvc.xml中导入applicationContext.xml , 然后在web.xml中只需要引入springmvc.xml即可
<!--5. 导入applicationContext.xml-->
<import resource="applicationContext.xml"/>
package com.itheima.service.impl;
import com.itheima.bean.Account;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@Transactional
@Service
public class AccountServiceImpl implements AccountService {
//注入dao
@Autowired
private AccountDao dao;
public List<Account> findAll() {
System.out.println("调用了AccountServiceImpl的findAll方法~!");
return dao.findAll();
}
}
表单校验保障了数据有效性、安全性
客户端校验(前端页面)
服务端校验
长度:例如用户名长度,评论字符数量
非法字符:例如用户名组成
数据格式:例如Email格式、IP地址格式
边界值:例如转账金额上限,年龄上下限
重复性:例如用户名是否重复
...等
Hibernate框架中包含一套独立的校验框架hibernate-validator,实现了JSR303的规范
JSR全称(Java Specification Requests):Java 规范提案
第303个:提供bean属性相关校验规则
JSR是由JCP(Java Community Process):Java社区提出来的,每年都找各行业的人来提需求,之后就来制定成JSR规提案
tomcat7:搭配hibernate-validator版本5.x.x.Final
tomcat8.5以上的:搭配hibernate-validator版本6.x.x.Final
在这里,我们使用6.1.0.Final
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
如果使用tomcat7插件运行项目,那么应该使用5.x的版本
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
<!--tomcat7 ,请使用以下依赖替换上面的6.1.0的版本 -->
<!--
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency> -->
</dependencies>
package com.itheima.bean;
import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;
import javax.validation.constraints.Min;
@Data
public class User {
@NotBlank(message = "用户名不能为空!")
private String username;
@Min(value = 18 , message = "年龄不达标!")
private int age;
}
package com.itheima.controller;
import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
import java.util.List;
@Controller
public class UserController {
/*
接收一个用户信息,并且封装到user对象里面去。
1. 如果无法封装,那么可以从errors参数里面得到错误的信息
2. 如果希望把这个错误的信息归还给页面显示,可以往model对象里面设置
*/
@RequestMapping("/add")
public String add(@Valid User user , Errors errors , Model model){
//1. 判断校验是否有错误
if(errors.hasErrors()){ // 表示有错误
//2. 得到所有的错误信息
List<FieldError> list = errors.getFieldErrors();
//3. 遍历集合,取出每一个错误的属性。
for (FieldError fieldError : list) {
//4. 得到报错的属性名称
String field = fieldError.getField();
//5. 得到报错的具体信息
String message = fieldError.getDefaultMessage();
if( message.contains("NumberFormatException")){
message = "输入有误!";
}
//6. 把信息装到model里面去。
model.addAttribute(field , message);
}
return "index";
}
System.out.println("user=" + user);
//表示没有错误!
return "success";
}
}
<?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">
<!--1. 扫描包-->
<context:component-scan base-package="com.itheima"/>
<!--2. 注解驱动-->
<mvc:annotation-driven/>
<!--3. 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--4. 静态资源处理-->
<mvc:default-servlet-handler/>
</beans>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<form action="/add" method="post">
<table>
<tr>
<td>用户名</td>
<td><input name="username"/></td>
<td>${username}</td>
</tr>
<tr>
<td>年龄</td>
<td><input name="age"/></td>
<td>${age}</td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="提交"/></td>
</tr>
</table>
</form>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: xiaomi
Date: 2021/8/26
Time: 14:50
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>这是成功的页面~!</h2>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--配置前端控制器 DispatcherServlet-->
<servlet>
<servlet-name>dispatcher</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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
异常处理
1. 自定义异常处理器
2.2 定义类,实现接口: HandlerExceptionResolver
2.3. 配置成Bean即可
2. 简单异常处理器
2.1 不需要去代码了,只需要配置即可,只能让错误出现的时候,跳转到某一个页面上!
拦截器
1. 拦截器属于SpringMVC的产物,只有使用springmvc环境,才能使用它。
2. 它主要是用来拦截controller的请求,可以看成是对controller进行前置处理和后置处理。
3. 怎么使用?
3.1 定义类,实现接口HandlerInterceptor
3.2 配置拦截器即可
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/show"/>
<bean class="拦截器的具体路径"/>
4. 细节:
4.1 拦截器里面有3个方法: preHandle | postHandle | afterCompletion
preHandle : 在执行目标(controller)方法之前调用。
postHandle : 在执行目标方法之后调用
afterCompletion: 在页面渲染完毕,调用
4.2 当我们在拦截器里面拦截下来了某一个请求,那么还是需要对这个请求进行处理的
可以写一句话出去或者跳转到某个页面显示。否则用户将会看到一片空白!
4.3 到底是拦截还是放行,取决的是preHandle里面的返回值:
true : 放行
false : 拦截
SSM整合
SqlSessionFactoryBean : 用于帮助创建Dao的代理对象,丢到spring的容器里面
MapperScannnerConfiguer : 用于扫描dao的映射文件
以上是脚本宝典为你收集整理的day46_springmvc全部内容,希望文章能够帮你解决day46_springmvc所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。