文章目录
START
-
author:空巷
-
WeChat Applet :Java空巷
-
QQ: 2399014502
-
Mail: ycw2399014502@163.com
-
WeiBo : KongXiang_
-
WeChat:
SpringMVC
推荐学习路径:http://c.biancheng.net/spring_mvc/
MVC设计模式
MVC 设计不仅限于 Java Web 应用,还包括许多应用,比如前端、PHP、.NET 等语言。之所以那么做的根本原因在于解耦各个模块。
MVC 是 Model、View 和 Controller 的缩写,分别代表 Web 应用程序中的 3 种职责。
- 模型:用于存储数据以及处理用户请求的业务逻辑。
- 视图:向控制器提交数据,显示模型中的数据。
- 控制器:根据视图提出的请求判断将请求和数据交给哪个模型处理,将处理后的有关结果交给哪个视图更新显示。
基于 Servlet 的 MVC 模式的具体实现如下。
- 模型:一个或多个 JavaBean 对象,用于存储数据(实体模型,由 JavaBean 类创建)和处理业务逻辑(业务模型,由一般的 Java 类创建)。
- 视图:一个或多个 JSP 页面,向控制器提交数据和为模型提供数据显示,JSP 页面主要使用 HTML 标记和 JavaBean 标记来显示数据。
- 控制器:一个或多个 Servlet 对象,根据视图提交的请求进行控制,即将请求转发给处理业务逻辑的 JavaBean,并将处理结果存放到实体模型 JavaBean 中,输出给视图显示。
Spring MVC 框架主要由 DispatcherServlet、处理器映射、控制器、视图解析器、视图组成,其工作原理如图 所示。
从图 可总结出 Spring MVC 的工作流程如下:
- 客户端请求提交到 DispatcherServlet。
- 由 DispatcherServlet 控制器寻找一个或多个 HandlerMapping,找到处理请求的 Controller。
- DispatcherServlet 将请求提交到 Controller。
- Controller 调用业务逻辑处理后返回 ModelAndView。
- DispatcherServlet 寻找一个或多个 ViewResolver 视图解析器,找到 ModelAndView 指定的视图。
- 视图负责将结果显示到客户端。
传统的模型层被拆分为了业务层(Service)和数据访问层(DAO,Data Access Object)。 在 Service 下可以通过
Spring 的声明式事务操作数据访问层,而在业务层上还允许我们访问 NoSQL ,这样就能够满足异军突起的NoSQL 的使用了,它可以大大提高互联网系统的性能。
特点: 结构松散,几乎可以在 Spring MVC 中使用各类视图 松耦合,各个模块分离 与 Spring 无缝集成
代码
使用配置文件
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springmvc-study</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source> <!-- 源代码使用的JDK版本 -->
<target>${java.version}</target> <!-- 需要生成的目标class文件的编译版本-->
<encoding>${project.build.sourceEncoding}</encoding><!-- 字符集编码 -->
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
在web工程下配置DispatcherServlet的servlet
<!--注册DispatcherServlet,这是springmvc的核心,就是个servlet-->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在springMvc中,视图都放在WEB-INF中以保证视图安全。客户端必须通过访问servlet才能跳转到WEB-INF
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 处理映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/page/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
编写一个Controller,继承Controller接口
public class FirstController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws Exception {
//ModelAndView 封装了模型和视图
ModelAndView mv = new ModelAndView();
//模型里封装数据
mv.addObject("HelloMvc","Hello springMVC!");
//封装跳转的视图
mv.setViewName("HelloMvc");
//不是有个视图解析器吗
//这玩意就是为了省事的,自动给你加个前缀后缀
//就成了 /jsp/hellomvc.jsp 不就是拼串吗
return mv;
}
}
spingMvc默认去找WEB-INF下的spring-mvc-servlet.xml ,要创建一个spring-mvc-servlet.xml 文件
<bean id="/hellomvc" class="com.xinzhi.controller.FirstController"/>
使用注解
注解就要扫包
<!-- 自动扫包 -->
<context:component-scan base-package="com.xinzhi"/>
<!-- 让Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler />
<!-- 让springmvc自带的注解生效 -->
<mvc:annotation-driven />
@Controller//说明是Controller层
@RequestMapping("/user/") //路径
public class UserController {
//一个主路径可以有多个子路径,多个功能可以由一个servlet来处理
@RequestMapping("login")
public String login(Model model) {
model.addAttribute("ogin","denlu!");
return "Login";
}
@RequestMapping("register")
public String register(Model model) {
model.addAttribute("egister","zhuce!");
return "Register";
}
}
聊聊整个过程 执行原理
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,在将结果返回给请求者。
执行原理
简要分析执行流程
-
DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
http://localhost:8080服务器域名
SpringMVC部署在服务器上的web站点
hello表示控制器
通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
-
HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
-
HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
-
HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
-
HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
-
Handler让具体的Controller执行。
-
Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
-
HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
-
DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
-
视图解析器将解析的逻辑视图名传给DispatcherServlet。
-
DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
-
最终视图呈现给用户。
深入学习
视图模型分离
之前返回的是模型加视图,耦合性太高,有时候不需要跳转视图也会强行跳转使用Model参数
Spring 视图解析器是 Spring MVC 中的重要组成部分,用户可以在配置文件中定义 Spring MVC 的一个视图解析器(ViewResolver),示例代码如下:
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/page/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
看代码
@RequestMapping(value = "login")
public String login(Model model) {
model.addAttribute("ogin","登录!");
return "Login";
}
//视图解析器将会自动添加前缀和后缀。
@RequestMapping
这个注解很强大,可以放在方法上也可以放在类上,放在类上所有方法都默认加上该注解有六个参数
- value:访问路径
- method :指定请求类型,如post、get等
- consumes :指定处理请求后提交的数据类型(Content-Type),如json,text
- produces :指定返回值类型
- params :指定request中必须有哪些参数,有才能让此方法执行
- headers :指定request中必须包含某些指定的header值 ,有才能让此方法执行
例如:
@RequestMapping(value = "login",method = RequestMethod.POST)
public String login(Model model, User user) {
System.out.println(user.getUsername());
System.out.println(user.getId());
System.out.println(user.getPassword());l
model.addAttribute("login","登录!");
return "Login";
}
好处:
- 一个一班处理一类事物,可以统一家前缀,好区分
- 简化书写复杂度
内置统一字符集处理
在 web.xml 中配置一个字符集过滤器即可
<!--在web.xml里配置-->
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
传参
建个首页
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
没注册的用户,请<a href="${pageContext.request.contextPath }/index/register"> 注册</a>!
<br/>
已注册的用户,去<a href="${pageContext.request.contextPath }/index/login"> 登录</a>!
</body>
</html>
建个实体类
package pojo;
public class UserForm {
private String uname; // 与请求参数名称相同
private String upass;
private String reupass;
// 省略getter和setter方法
}
不需要一个个的getParameter(),要什么直接拿
通过 @RequestParam 接收请求参数
通过 @RequestParam 接收请求参数适用于 get 和 post 提交请求方式,可以将“通过实体 Bean 接收请求参数”部分控制器类 UserController 中 register 方法
@RequestMapping("/register")
/**
* 通过@RequestParam接收请求参数
*/
public String register(@RequestParam String uname,
@RequestParam String upass, Model model) {
if ("zhangsan".equals(uname) && "123456".equals(upass)) {
logger.info("成功");
return "login"; // 注册成功,跳转到 login.jsp
} else {
// 在register.jsp页面上可以使用EL表达式取出model的uname值
model.addAttribute("uname", uname);
return "register"; // 返回 register.jsp
}
}
@RequestMapping(value = "login",method = RequestMethod.POST)
public String login(Model model, User user) {
System.out.println(user.getUsername());
System.out.println(user.getId());
System.out.println(user.getPassword());l
model.addAttribute("login","登录!");
return "Login";
}
通过 @PathVariable 接收 URL 中的请求参数
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/user")
// 必须节method属性
/**
* 通过@PathVariable获取URL的参数
*/
public String register(@PathVariable String uname,@PathVariable String upass,Model model) {
if ("zhangsan".equals(uname)
&& "123456".equals(upass)) {
logger.info("成功");
return "login"; // 注册成功,跳转到 login.jsp
} else {
// 在register.jsp页面上可以使用EL表达式取出model的uname值
model.addAttribute("uname", uname);
return "register"; // 返回 register.jsp
}
}
}
但参数多了这么传是不是很啰嗦。更牛逼了 直接传个对象
@RequestMapping(value = "login",method = RequestMethod.POST)
public String login(Model model, User user) {
System.out.println(user.getUsername());
System.out.println(user.getId());
System.out.println(user.getPassword());l
model.addAttribute("login","登录!");
return "Login";
}
这里介绍了几种常用的传参方式,还有很多,可以自行去学习。
返回json数据
可以使用fastjson
导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
@RequestMapping(value = "getUsers",produces = {"text/json;charset=utf-8"})
@ResponseBody
public String getUsers(){
List<User> users = new ArrayList<User>(){{
add(new User("wangwu","2222",23));
add(new User("空巷","333",23));
}};
return JSONArray.toJSONString(users);
}
@ResponseBody能将处理的结果放在响应体中,直接返回,不走视图解析器
每次都需要自己处理数据麻烦 那么springMVC 封装了一个更好用的 只需要在配置文件中注入一个消息转换器
<mvc:annotation-driven >
<mvc:message-converters>
<bean id="fastjson"
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
@RequestMapping("set")
//直接将返回值以数据的形式返回到响应体
@ResponseBody
public User set(@Validated User user, BindingResult br) {
List<ObjectError> allErrors = br.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getCode()+"---"+allError.getDefaultMessage());
}
System.out.println(user.getId());
return user;
}
数据转化
Spring MVC 提供了几个内置的格式化转换器,具体如下。
- NumberFormatter:实现 Number 与 String 之间的解析与格式化。
- CurrencyFormatter:实现 Number 与 String 之间的解析与格式化(带货币符号)。
- PercentFormatter:实现 Number 与 String 之间的解析与格式化(带百分数符号)。
- DateFormatter:实现 Date 与 String 之间的解析与格式化。
@DateTimeFormat(pattern = "yyyy-mm-dd")
private Date birthday;
@NumberFormat(pattern = "#,###,###.#")
private Double salary;
数据校验
@NotNull 对象不为空
@AssertTrue Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
@Size(min =, max =) 长度是否在给定的范围
@Min(value=) 验证 Number 对象是否大等于指定的值
@Max(value=) 验证 Number 对象是否小等于指定的值
@Pattern 验证 String 对象是否符合正则表达式的规则
@Past @Future验证 Date 和 Calendar 时间对象是否在当前时间之前/之后
@Email 是否是正确的邮箱地址
需要引入jar
<!-- 引入hibernate的校验器实现 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.1.Final</version>
</dependency>
在 springmvc.xml 中注册 hibernate 的校验器,并在原来的 mvc 注解驱动中设置 validator 属性:
<!--开启mvc注解驱动 -->
<mvc:annotation-driven validator="validator" />
<!-- 注册hibernate的校验器 -->
<bean id = "validator" class = "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value ="org.hibernate.validator.HibernateValidator"></property>
</bean>
java:
@Max(value = 20L,message = "id不能大于20")
private int id;
@NotNull(message = "名字不能为空")
private String username;
@Null
private String password;
@RequestMapping("set")
@ResponseBody
//用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。
public User set(@Validated User user, BindingResult br) {
//拿到错误,不会挡住请求
List<ObjectError> allErrors = br.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getCode()+"---"+allError.getDefaultMessage());
}
System.out.println(user.getId());
return user;
}
注意点:
-
在需要校验的对象前加 @Validated注解。
-
在该对象后加一个参数:BindingResut 来接收校验信息。
-
调用 BindingResult 对象的 hasErrors 方法判断前台传过来的参数是否符合校验规则,有一个不符合规则,hasErrors 方法就会返回 true。
-
然后调用 getAllErrors() 方法获取 ObjectError 的 list 列表。
-
遍历集合,调用每个对象的 getDefaultMessage() 方法,获取相应的错误提示信息(在实体类上配置的)
-
获取到校验信息后再返回给前台或做一些其他的处理即可。
重定向和转发
请求转发:
@RequestMapping("/annotation")
public String testAnnotation(Model model) {
model.addAttribute("annotation", "hello Springmvc");
return "annotation";
}
重定向:(只需要在return 语句中加入 redirect:+ 地址 即可访问)
@RequestMapping(value = "/jump")
public String jumpUser(HttpServletRequest request,HttpServletResponse response){
//return "redirect:https://www.baidu.com/";
return "redirect:add";
}
restful
请求url | 请求方式 | 操作 |
---|---|---|
/admin/get/1 | get | 根据id查询用户 |
/admin/add | Post | 添加一个用户 |
/admin/update/1 | Put | 根据id修改用户 |
/admin/delete/1 | Delete | 删除一个用户 |
Restful web service是一种常见的rest的应用,是遵守了rest风格的web服务;rest式的web服务是一种ROA(The Resource-Oriented Architecture)(面向资源的架构)
常用状态码 工具类
/**
* @author 空巷
* @Date 2020/6/4
*/
@AllArgsConstructor
@Data
@NoArgsConstructor
public class R implements Serializable {
private int code;
private String msg;
private Map<String,String> data;
//返回成功后的信息
public static R success(){
return new R(200,"成功",null);
}
//返回失败后的信息
public static R fail(){
return new R(500,"fail",null);
}
//其他类型的返回
public static R build(int code,String msg){
return new R(500,msg,null);
}
public R put(String key,String msg){
if (msg == null){
this.getData().put(key,msg);
}
return this;
}
}
controller类
/**
* @author 空巷
* @Date 2020/6/4
*/
@Controller
@RequestMapping("/admin")
public class RestfulController {
@GetMapping("/get/{id}")
@ResponseBody
public User getUser(@PathVariable int id){
System.out.println(id);
return new User(13,"123","123456",new Date(),12123.12);
}
@PostMapping("/add")
@ResponseBody
public R addUser(User user){
System.out.println(user);
if (user == null){
return R.fail();
}else{
return R.success();
}
}
@PutMapping("/update/{id}")
@ResponseBody
public R updateUser(@PathVariable int id){
System.out.println(id);
return R.success();
}
@DeleteMapping("/delete/{id}")
@ResponseBody
public R deleteUser(@PathVariable int id){
System.out.println(id);
return R.success();
}
}
建立一个http文件或者在postman测试
GET http://localhost:8080/admin/get/1
Accept: application/json
###
POST http://localhost:8080/admin/add
Content-Type: text/html
###
PUT http://localhost:8080/admin/update/2
Content-Type: application/json
{
"id":2,
"username":"123",
"password":2,
"birthday":"2000-5-25",
"salary":"1,111.14"
}
###
DELETE http://localhost:8080/admin/delete/1
Content-Type: text/html
update 测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-81uCSZvO-1591533532699)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200604172838216.png)]
delete 测试:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9WFpgcgf-1591533532700)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200604173022938.png)]
get 测试:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HctHedNB-1591533532701)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200604173108784.png)]
add 测试:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ovlp1zQ5-1591533532702)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200604173200239.png)]
拦截器
- SpringMVC提供的拦截器类似于JavaWeb中的过滤器,只不过SpringMVC拦截器只拦截被前端控制器拦截的请求,而过滤器拦截从前端发送的任意请求。
- 熟练掌握 SpringMVC 拦截器对于我们开发非常有帮助,在没使用权限框架( shiro,spring security )之前,一般使用拦截器进行认证和授权操作。
- SpringMVC拦截器有许多应用场景,比如:登录认证拦截器,字符过滤拦截器,日志操作拦截器等等。
拦截器规则
自定义的拦截器需要实现 Spring 的 HandlerInterceptor 接口,其中有三个方法。
- preHandle:Controller方法处理请求前执行,根据拦截器定义的顺序,正向执行。
- postHandle:Controller方法处理请求后执行,根据拦截器定义的顺序,逆向执行。需要所有的preHandle方
法都返回true时才会调用。 - afterCompletion:View视图渲染后处理方法:根据拦截器定义的顺序,逆向执行。preHandle返回true就会
调用
登录拦截器
/**
* @author 空巷
* @Date 2020/6/4
*/
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user == null){
response.sendRedirect("/admin/toLogin");
}else {
return true;
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
还需要在 SpringMVC.xml 配置文件名中,配置编写的拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--
mapping:拦截的路径
/**:是指所有文件夹及其子孙文件夹
/*:是指所有问你减价,单不包含子孙文件夹
/:Web项目的根目录
-->
<mvc:mapping path="/**"/>
<!--
exclude-mapping:不拦截路径,不拦截登录路径
/toLogin:跳转到登陆页面
/login:登录操作
-->
<mvc:exclude-mapping path="/admin/toLogin"/>
<mvc:exclude-mapping path="/admin/login"/>
<!--class属性就是我们自定义的拦截器-->
<bean id="loginInterceptor" class="com.xinzhi.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
controller
@GetMapping("/toLogin")
public String toLogin(User user){
return "login";
}
@PostMapping("/login")
@ResponseBody
public R login(User user, HttpServletRequest request){
request.getSession().setAttribute("user",user);
return R.success();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n6xjbSrg-1591533532703)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200604184134261.png)]
文件上传
Spring MVC 框架的文件上传是基于 commons-fileupload 组件的文件上传,只不过 Spring MVC 框架在原有文件上传组件上做了进一步封装,简化了文件上传的代码实现,取消了不同上传组件上的编程差异。
commons-fileupload组件
由于 Spring MVC 框架的文件上传是基于 commons-fileupload 组件的文件上传,因此需要将 commons-fileupload 组件相关的 JAR(commons-fileupload-1.3.1.jar 和 commons-io-2.4.jar)复制到 Spring MVC 应用的 WEB-INF/lib 目录下。下面讲解如何下载相关 JAR 包。
Commons 是 Apache 开放源代码组织中的一个 Java 子项目,该项目包括文件上传、命令行处理、数据库连接池、XML 配置文件处理等模块。fileupload 就是其中用来处理基于表单的文件上传的子项目,commons-fileupload 组件性能优良,并支持任意大小文件的上传。文件上传
<form action="/admin/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file">
<input type="submit">
</form>
multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的CommonsFileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。
首先需要导入文件上传的 jar 包
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
在 SpringMVC 中配置bean
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--请求的编码格式,必须和jsp的pageEncoding的属性一致,以便正确读取表单的内筒,默认为ISO-8850-1-->
<property name="defaultEncoding" value="utf-8"/>
<!--上传文件大小上线,单位为字节 10485760 = 10M-->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
CommonsMultipartFile 的 常用方法:
- String getOriginalFilename():获取上传文件的原名
- InputStream getInputStream():获取文件流
- void transferTo(File dest):将上传文件保存到一个目录文件中
controller
@PostMapping("/upload")
@ResponseBody
public R upload(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request){
//getOriginalFilename 可以获得文件的名字
String filename = file.getOriginalFilename();
//文件路径
String path = "E:\\upload";
File relPath = new File(path);
//判断路径是否存在,不存在则创建一个
if (!relPath.exists()){
relPath.mkdir();
}
try {
file.transferTo(new File(path +"\\"+ filename));
} catch (IOException e) {
e.printStackTrace();
}
return R.success();
}
文件下载
实现文件下载有以下两种方法:
- 通过超链接实现下载。
- 利用程序编码实现下载。
使用 ResponseEntity
@GetMapping("/download")
public ResponseEntity<byte[]> download() {
String fileName = "6.png";
try {
//FileUtils 中有个方法 readFileToByteArray 可以读取文件
byte[] bytes = FileUtils.readFileToByteArray(new File("E:\\upload" + "\\" + fileName));
HttpHeaders handler = new HttpHeaders();
//下载文件时需要设置响应头
handler.set("Content-Disposition", "attachment;filename=" +
URLEncoder.encode(fileName, "UTF-8"));
handler.set("charsetEncoding", "utf-8");
handler.set("content-type", "multipart/form-data");
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(bytes, handler, HttpStatus.OK);
return responseEntity;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gsYxOaI3-1591533532704)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200604194010851.png)]
异常捕获
当页面出现异常时,不能显示在页面,之前是通过在web.xml配置错误页面,但往往这种处理办法是不好的。因为不知道他出现了什么错误。因此,Spring MVC提供了一个HandlerExceptionResolver接口,可用于统一异常处理。
/**
* @author 空巷
* @Date 2020/6/4
*/
@Component
public class MyException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//打印错误到控制台
e.printStackTrace();
ModelAndView mv = new ModelAndView();
mv.setViewName("error");
return mv;
}
}
国际化
国际化是设计软件应用的过程中应用被使用与不同语言和地区
spring-mvc.xml配置文件
<!--配置拦截器-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!--该拦截器通过名为”lang”的参数来拦截HTTP请求,使其重新设置页面的区域化信息 -->
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptor>
<!-- 存储区域设置信息 SessionLocaleResolver类通过一个预定义会话名将区域化信息存储在会话中 从session判断用户语言defaultLocale
:默认语言 -->
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="zh_CN" />
</bean>
<!-- 国际化资源文件 messageSource配置的是国际化资源文件的路径, classpath:messages指的是classpath路径下的
messages_zh_CN.properties文件和messages_en_US.properties文件 设置“useCodeAsDefaultMessage”,默认为false,这样当Spring在ResourceBundle中找不到messageKey的话,就抛出NoSuchMessageException,
把它设置为True,则找不到不会抛出异常,而是使用messageKey作为返回值。 -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="defaultEncoding" value="UTF-8" />
<property name="useCodeAsDefaultMessage" value="true" />
<property name="basenames">
<list>
<value>classpath:message</value>
</list>
</property>
</bean>
国际化语言属性文件:message_zh_CN.properties
TITLE = 开始冒险之旅
USERNAME = 账号:
PASSWORD = 密码:
LOGIN = 登录
message_en_US.properties
TITLE = BEGIN TO START
USERNAME = UserName
PASSWORD = PassWord
LOGIN = Login
chinese.jsp
<%--
Created by IntelliJ IDEA.
User: 空巷
Date: 2020/6/4
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>
<a href="/admin/getLogin?lang=zh_CN">中文</a>
<br />
<a href="/admin/getLogin?lang=en_US">英文</a>
</body>
</html>
controller
@GetMapping("/getLogin")
public String getLogin(){
return "result";
}
result.jsp
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%--
Created by IntelliJ IDEA.
User: 空巷
Date: 2020/6/4
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>
<div class="login">
<h1><spring:message code="TITLE" /> </h1>
<form action="test.do" method="post">
<input type="text" name="name" placeholder=<spring:message code="USERNAME" /> required="required" value="" />
<input type="password" name="password" placeholder=<spring:message code="PASSWORD" /> required="required" value="" />
<button type="submit" class="btn btn-primary btn-block btn-large"><spring:message code="LOGIN" /> </button>
</form>
</div>
</body>
</html>
ssm整合
pom依赖:
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring 相关 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.6.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- mybatis 相关 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- 数据库连接驱动 相关 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 提供了对JDBC操作的完整封装 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- 织入 相关 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<!-- spring,mybatis整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
</dependencies>
<!-- 资源文件过滤 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
mybatis-config.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>
<typeAliases>
<!--为 com.xinzhi.entity.User 这个类设置别名user-->
<!--<typeAlias type="com.xinzhi.entity.User" alias="user"/>-->
<!--为com.xinzhi.entity 包下的所有文件设置别名 -->
<package name="com.xinzhi.entity"/>
</typeAliases>
</configuration>
springmvc-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: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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--<!– 让Spring MVC不处理静态资源 –>-->
<mvc:default-servlet-handler />
<!--<!–当把静态资源放入WEN-INF下时,需要添加访问静态资源的配置–>
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>-->
<!-- 让springmvc自带的注解生效 -->
<mvc:annotation-driven >
<mvc:message-converters>
<bean id="fastjson" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
<!-- 处理映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/pages/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
application.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" 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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 加载外部的数据库信息 classpath:不叫会报错具体原因下边解释-->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 加入springmvc的配置 -->
<import resource="classpath:springmvc-servlet.xml"/>
<!--扫包-->
<context:component-scan base-package="com.xinzhi"/>
<!-- Mapper 扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描 cn.wmyskxz.mapper 包下的组件 -->
<property name="basePackage" value="com.xinzhi.dao"/>
</bean>
<!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name = "filters" value = "${filters}" />
<!-- 最大并发连接数 -->
<property name = "maxActive" value = "${maxActive}" />
<!-- 初始化连接数量 -->
<property name = "initialSize" value = "${initialSize}" />
<!-- 配置获取连接等待超时的时间 -->
<property name = "maxWait" value = "${maxWait}" />
<!-- 最小空闲连接数 -->
<property name = "minIdle" value = "${minIdle}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name = "timeBetweenEvictionRunsMillis" value ="${timeBetweenEvictionRunsMillis}" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name = "minEvictableIdleTimeMillis" value ="${minEvictableIdleTimeMillis}" />
<!-- <property name = "validationQuery" value = "${validationQuery}" /> -->
<property name = "testWhileIdle" value = "${testWhileIdle}" />
<property name = "testOnBorrow" value = "${testOnBorrow}" />
<property name = "testOnReturn" value = "${testOnReturn}" />
<property name = "maxOpenPreparedStatements" value ="${maxOpenPreparedStatements}" />
<!-- 打开 removeAbandoned 功能 -->
<property name = "removeAbandoned" value = "${removeAbandoned}" />
<!-- 1800 秒,也就是 30 分钟 -->
<property name = "removeAbandonedTimeout" value ="${removeAbandonedTimeout}" />
<!-- 关闭 abanded 连接时输出错误日志 -->
<property name = "logAbandoned" value = "${logAbandoned}" />
</bean>
<!--配置SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--关联Mybatis-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:mappers/*.xml"/>
</bean>
<!--注册sqlSessionTemplate , 关联sqlSessionFactory-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--利用构造器注入-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--配置哪些方法使用什么样的事务,配置事务的传播特性-->
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="search*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置aop织入事务-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.xinzhi.service.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
<!-- <!–开启事务注解,并配置一个事务管理器 –>-->
<!-- <tx:annotation-driven transaction-manager="transactionManager" />-->
</beans>
logback.xml(日志配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义参数常量 -->
<!-- 日志级别 TRACE<DEBUG<INFO<WARN<ERROR -->
<!-- logger.trace("msg") logger.debug... -->
<property name="log.level" value="debug" />
<property name="log.maxHistory" value="0.5" />
<property name="log.filePath" value="D:/log" />
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" />
<!-- 控制台输出设置 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- DEBUG级别文件记录 -->
<appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/debug.log</file>
<!-- 滚动日志文件类型,就是每天都会有一个日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- INFO -->
<appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${log.filePath}/info/info.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- com.xinzhi开头的日志对应形式 -->
<logger name="com.xinzhi" level="${log.level}" additivity="true">
<appender-ref ref="debugAppender"/>
<appender-ref ref="infoAppender"/>
</logger>
<!-- <root> 是必选节点,用来指定最基础的日志输出级别,只有一个level属性 -->
<root level="info">
<appender-ref ref="consoleAppender"/>
</root>
<!-- 捕捉sql开头的日志 -->
<appender name="MyBatis" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.filePath}/sql_log/mybatis-sql.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${log.filePath}/sql_log/mybatis-sql.log.%d{yyyy-MM-dd}</FileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%thread|%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%logger{36}|%m%n</pattern>
</encoder>
</appender>
<logger name="sql" level="DEBUG">
<appender-ref ref="MyBatis"/>
</logger>
</configuration>
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/backlog?useSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
filters=wall,stat
maxActive=20
initialSize=3
maxWait=5000
minIdle=3
maxIdle=15
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 'x'
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
maxOpenPreparedStatements=20
removeAbandoned=true
removeAbandonedTimeout=1800
logAbandoned=true
web.xml
<?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">
<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:application.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 连接池 启用 Web 监控统计功能 start-->
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>DruidStatView </servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
<init-param>
<!-- 用户名 -->
<param-name>loginUsername</param-name>
<param-value>xinzhi</param-value>
</init-param>
<init-param>
<!-- 密码 -->
<param-name>loginPassword</param-name>
<param-value>123</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
</web-app>
xxxMapper.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.xinzhi.dao.UserMapper">
</mapper>
静态资源处理问题
静态资源的访问问题
访问 jsp 页面时 首先通过访问controller,通过请求转发到jsp页面 需要跳转首页时 建立一个indexConrtoller 使用GetMapping直接转发到首页
当一些页面的css,js等静态资源 放在WEB-INF 下,通过相对路径的方式是访问不到的
解决安案一:(不被保护的,外界可以查看)
将静态资源放入 webapp 下 通过 相对路径 或绝对路径的方式访问
解決方案二:(受保护的)
当把静态资源放入 WEB-INF 下的时候:
需要在spring-mvc配置文件中加入:
<!--当把静态资源放入WEN-INF下时,需要添加访问静态资源的配置-->
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
**eg: ** 当你使用了拦截器时,你会发现css等静态资源加不进来,打开 F12 进行调试,看到 css等静态资源并没有报红,你会发现,莫名其妙的重定向了。
解决方案一:(针对静态资源放入 webapp 下的处理办法)
在拦截器中加入
<mvc:exclude-mapping path="/**/*.css" />
<mvc:exclude-mapping path="/**/*.js" />
<mvc:exclude-mapping path="/**/*.jsp" />....
解决方案二:(针对静态资源存入WEB-INF 下)
在拦截器中加入
<mvc:exclude-mapping path="/static/**" />