<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.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>SpringMVC_textartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>2.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.1.9.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>5.1.9.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.1.9.RELEASEversion>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>80port>
<path>/path>
configuration>
plugin>
plugins>
build>
project>
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
public String save(){
System.out.println("user mvc controller is running ...... ");
}
}
spring-mvc.xml
)
<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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="com.liu" />
beans>
<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>DispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:spring-mvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>DispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/save")
public String save(){
System.out.println("user mvc controller is running ...... ");
}
}
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/save")
public String save(){
System.out.println("user mvc controller is running ...... ");
return "success.jsp";
}
}
在spring-mvc.xml
文件中修改成
<context:component-scan base-package="com.liu">
<context:include-filter
type="annotation"
expression="osg.springframework .stereotype.Controller" />
context:component-scan>
或者在SpringMVCConfig.java
文件中修改成
package com.liu.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
@Configuration
@ComponentScan(
value = "com.liu",
includeFilters =
@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = {Controller.class}
)
)
public class SpringMVCConfig {
}
<mvc:resources mapping="/img/**" 1ocation="/ing/" />
<mvc:resources mapping="/js/**" location="/js/" />
<mve: default-servlet-handler />
在spring-mvc.xml
文件中修改成
<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
https://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
">
<context:component-scan base-package="com.liu" >
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<mvc:default-servlet-handler />
beans>
或者在SpringMVCConfig.java
文件中修改成
package com.liu.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@ComponentScan(
value = "com.liu",
includeFilters =
@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = {Controller.class}
)
)
public class SpringMVCConfig implements WebMvcConfigurer {
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// // 静态资源加载控制
// registry.addResourceHandler("/img/**").addResourceLocations("/img/");
// registry.addResourceHandler("/js/**").addResourceLocations("/js/");
// registry.addResourceHandler("/css/**").addResourceLocations("/css/");
// }
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// 简化:静态资源加载控制
configurer.enable();
}
}
<filter>
<filter-name>characterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-olass>
<init-paran>
<paran-name>encodingparan-nane>
<param-value>UTF-8paran-value>
init-param>
filter>
<filter-mapping>
<filter-name>characterEncodingFilterfi1ter-name>
<uri-pattern>/*ur1-pattern>
fi1ter-mapping>
在 web.xml 中加上
<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">
<filter>
<filter-name>characterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>characterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<servlet>
<servlet-name>DispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:spring-mvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>DispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
或者在
package com.liu.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.EnumSet;
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createServletApplicationContext() {
//
// DispatcherServlet
// org.springframework.web.servlet.DispatcherServlet
//
// contextConfigLocation
// classpath*:spring-mvc.xml
//
//
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMVCConfig.class);
return ctx;
}
@Override
protected String[] getServletMappings() {
//
// DispatcherServlet
// /
//
return new String[]{"/"};
}
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//
// characterEncodingFilter
// org.springframework.web.filter.CharacterEncodingFilter
//
// encoding
// UTF-8
//
//
//
// characterEncodingFilter
// /*
//
// 中文乱码处理
// 调用父类的onStartup
super.onStartup(servletContext);
// 1.创建字符集过滤器对象
CharacterEncodingFilter cef = new CharacterEncodingFilter();
// 2.设置使用的字符集
cef.setEncoding("UTF-8");
// 3.添加到容器(它不是ioc容器,而是ServletContainer)
FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef);
// 4.添加映射
registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD,DispatcherType.INCLUDE),false,"/*");
}
}
服务器端要获得请求的参数,有时还需要进行数据的封装,SpringMVC可以接收如下类型的参数:
Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配。
http://localhost:8080/quick9?username=zhangsan&age=12
在业务层中
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
@Controller
public class UserController {
......
@RequestMapping("/quick9")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public void quickMethod9(String username,int age) throws IOException {
System.out.println(username);
System.out.println(age);
}
}
Controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配。
http://localhost:8080/quick9?username=zhangsan&age=12
要有User实体类(因为要自动映射匹配)
package com.liu.domain;
public class User {
private String username;
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
在业务层中
package com.liu.controller;
import com.liu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
@Controller
public class UserController {
......
@RequestMapping("/quick10")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public void quickMethod10(User user) throws IOException {
System.out.println(user);
}
}
Controller中的业务方法数组名称与请求参数的name一致,参数值会自动映射匹配。
http://localhost:8080/quick11?strs=111&strs=222&strs=333
在业务层中
package com.liu.controller;
import com.liu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.util.Arrays;
@Controller
public class UserController {
......
@RequestMapping("/quick11")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public void quickMethod11(String[] strs) throws IOException {
System.out.println(Arrays.asList(strs));
}
}
post : userList[0].username=zzz & userList[0].age=18 & userList[1].username=aaa & userList[1].age=20
package com.liu.domain;
import java.util.List;
public class VO {
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
@Override
public String toString() {
return "VO{" +
"userList=" + userList +
'}';
}
}
在业务层中
package com.liu.controller;
import com.liu.domain.User;
import com.liu.domain.VO;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.util.Arrays;
@Controller
public class UserController {
......
@RequestMapping("/quick12")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public void quickMethod12(VO vo) throws IOException {
System.out.println(vo);
}
}
在前端中
<%@ page contentType="text/htm1 ; charset=UTF-8" language="java"%>
<html>
<head>
<title>Titletitle>
<script src="$ lpageContext.request.contextPath/js/jquery-3.3.1.js">script><script>
var userList = new Array();
userList.push({username:"zhangsan",age:18});
userList.push({username:"lisi",age:28});
$.ajax ({
type:"POST",
ur1:"$ {pageContext.request.contextPath)/quick13",
data:JSON.stringify(userList),
contentType:"app1icationljson; charset=utf-8"
});
script>
head>
<body>
body>
html>
在业务层中
package com.liu.controller;
import com.liu.domain.User;
import com.liu.domain.VO;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@Controller
public class UserController {
......
@RequestMapping("/quick13")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public void quickMethod13(@RequestBody List<User> userList) throws IOException {
System.out.println(userList);
}
}
@RequestMapping ("/ajaxController")
public string ajaxController(@RequestBody String message){
system.out.println(message);
return "page.jsp";
}
直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转。
在spring-mvc.xml
里的配置(配置内部资源视图解析器)
<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
https://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
">
<context:component-scan base-package="com.liu" >
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
bean>
<mvc:default-servlet-handler />
beans>
在业务层中
@RequestMapping("/quick")
public String quickMethod(){
return "index" ;
}
就拼接成了转发资源地址:/views/index.jsp
返回带有前缀的字符串:
转发:forward:/views/index.jsp
重定向:redirect:/index.jsp
@RequestMapping("/quick1")
public ModelAndView quickMethod1(){
/*
* Model:模型 作用:封装数据
* View:视图 作用:展示数据
* */
ModelAndView modelAndView =new ModelAndView();
modelAndView.addObject("username","liu"); //传值变量,index.jsp 页面显示
// 设置视图名称
modelAndView.setViewName("index"); //返回 /views/index.jsp 页面
return modelAndView;
}
@RequestMapping("/quick2")
public ModelAndView quickMethod2(ModelAndView modelAndView){
modelAndView.addObject("username","liu"); //传值变量,index.jsp 页面显示
// 设置视图名称
modelAndView.setViewName("index"); //返回 /views/index.jsp 页面
return modelAndView;
}
@RequestMapping("/quick3")
public String quickMethod3(Model model){
model.addAttribute("username","liu");
return "index";
}
@RequestMapping("/quick4")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public String quickMethod4(){
return "不进行页面跳转(说明:直接回写数据方式返回)";
}
得先加入解析json字符串的坐标
......
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.9.0version>
dependency>
......
返回对象
@RequestMapping("/quick4")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public User quickMethod4(){
User user=new User();
user.setUsername("liu");
user.setAge(28);
return user;
}
返回集合
@RequestMapping("/quick5")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
public List quickMethod5(){
User user1=new User();
user1.setUsername("liu");
user1.setAge(28);
User user2=new User();
user2.setUsername("xiu");
user2.setAge(22);
ArrayList arrayList=new ArrayList();
arrayList.add(user1);
arrayList.add(user2);
return arrayList;
}
名称:@ResponseBody
类型:方法注解、返回值注解
位置:处理器类中的方法前方
作用:将异步提交数据组织成标准请求参数格式,并赋值给形参
范例:
@RequestMapping("/ajaxReturnString")
@ResponseBody
pubiic string ajaxReturnString(){
system.out.printIn("controller return string ...");
return "page.jsp";
)
当通过域名A下的操作访问域名B下的资源时,称为跨域访问
@RequestMapping("/quick6")
@ResponseBody //不进行页面跳转(说明:直接回写数据方式返回)
@CrossOrigin //支持跨域访问
public User quickMethod6(){
User user=new User();
user.setUsername("liu");
user.setAge(28);
return user;
}
创建 拦截器类
package com.liu.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
// 前面
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("前置运行-------al");
return true; // 为 false 后面都不执行,包括 控制器(controller)也不执行
}
// 后面
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("后置运行-------bl");
}
// 完成后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("完成后运行-------cl");
}
}
在spring-mvc.xml
里配置拦截器
<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
https://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
">
<context:component-scan base-package="com.liu" >
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<mvc:default-servlet-handler />
<mvc:annotation-driven />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/handleRun"/>
<bean class="com.liu.interceptor.MyInterceptor" />
mvc:interceptor>
mvc:interceptors>
beans>
package com.liu.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
// 前面(参数处理,权限校验)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// HttpServletRequest request:请求
// HttpServletResponse response:响应
// Object handler:被拦截方法对象
System.out.println("前置运行-------a1");
return true; // 为 false 后面都不执行,包括 控制器(controller)也不执行
}
// 后面(返回数据处理,修改返回的页面)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// ModelAndView modelAndView: 返回的结果 作用:修改返回的页面
System.out.println("后置运行-------b1");
}
// 完成后(处理异常)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// Exception ex: 拦截的异常
System.out.println("完成后运行-------c1");
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<mvc:mapping path="/handleRun"/>
<mvc:mapping path="/handleRun*"/>
<mvc:exclude-mapping path="/b*"/>
<bean class="com.liu.interceptor.MyInterceptor" />
mvc:interceptor>
mvc:interceptors>
*
*
表示任意名称,/*
仅表示根路径下任意名称,不再往下匹配目录**
表示当前路径及其子路径,/**
表示根路径及其子路径下任意名称*
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<bean class="com.liu.interceptor.MyInterceptor1" />
mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<bean class="com.liu.interceptor.MyInterceptor2" />
mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<bean class="com.liu.interceptor.MyInterceptor3" />
mvc:interceptor>
mvc:interceptors>
执行顺序为
a1
a2
a3
我是方法
b3
b2
b1
c3
c2
c1
当 a2 为的返回值false时,执行顺序为
a1
a2
c1
这个方案是在接受完参数后才工作的,所以接受参数是发生异常无法处理
创建异常处理类
只要继承 HandlerExceptionResolver 接口 和 @Component 报错对跳转到这个
package com.liu.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;
@Component
public class ExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView=new ModelAndView();
// 根据异常的种类不同,进行分门别类的管理,返回不同的信息
if (e instanceof NullPointerException){
modelAndView.addObject("msg","空指针异常");
}else if (e instanceof ArithmeticException){
modelAndView.addObject("msg","算数运算异常");
}else {
modelAndView.addObject("msg","未知的异常");
}
modelAndView.setViewName("error.jsp");
return modelAndView;
}
}
注解方式工作比较早,在Controller形成前就工作了,所以能处理接受参数时发生异常
@Component
@ControllerAdvice
public class ExceptionAdvice {}
package com.liu.exception;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Component
@ControllerAdvice
public class ExceptionAdvice {
@ExceptionHandler(NullPointerException.class)
@ResponseBody // 不返回页面
public String doNullException(Exception ex){
return "空指针异常------";
}
@ExceptionHandler(ArithmeticException.class)
@ResponseBody // 不返回页面
public String doArithmeticException(Exception ex){
return "算数异常------";
}
@ExceptionHandler(Exception.class)
@ResponseBody // 不返回页面
public String doException(Exception ex){
return "未知异常------";
}
}
异常分类
异常处理方案
创建用户行为异常类BusinessException
package com.liu.exception;
public class BusinessException extends RuntimeException {
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
把用户相关错误行为 都用这个类来接受(相当于中间机制)
if(user.getName().trim( ).length()< 8){
throw new BusinessException("对不起,用户名长度不满足要求,话重新输入");
}
if(user.getAge() < 0) {
throw new BusinessException("对不起,年龄必须是o到100之间的数字!");
}
创建系统异常类SystemException
package com.liu.exception;
public class SystemException extends RuntimeException {
public SystemException() {
}
public SystemException(String message) {
super(message);
}
public SystemException(String message, Throwable cause) {
super(message, cause);
}
public SystemException(Throwable cause) {
super(cause);
}
public SystemException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
在发生系统级错误用于接受,进行统一处理(如:告诉用户系统出错、告诉运维人员就行维护,进行日志写入等)
try {
//模拟连接数据库连接失败时
throw new SQLException();
} catch (SQLException e) {
throw new SystemException("数据库连接超时!",e);
}
package com.liu.exception;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Component
@ControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(BusinessException.class)
public String doBusinessException(Exception ex, Model m){
m.addAttribute("msg",ex.getMessage());
return "error.jsp";
}
@ExceptionHandler(SystemException.class)
public String doSystemException(Exception ex, Model m){
m.addAttribute("msg","服务器连接失败请联系管理员!");
//实际的问题显现更应该传递给redis服务器,运维人员通过后台系统查看
return "error.jsp";
}
@ExceptionHandler(Exception.class)
@ResponseBody // 不返回页面
public String doException(Exception ex, Model m){
m.addAttribute("msg",ex.getMessage());
// 将ex对象保存起来
return "error.jsp";
}
}
<dependency>
<groupId>commons-fileuploadgroupId>
<artifaotId>commons-fileuploadartifaotId>
<version>1.4version>
dependency>
......
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.4version>
dependency>
......
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="102400000000" />
bean>
上传文件的input
标签中的name
名要对应 控制器 接受参数时的变量名
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/fileupload" method="post" enctype="multipart/form-data">
上传LOGO:<input type="file" name="file" /><br/>
<input type="submit" value="上传" />
form>
body>
html>
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Controller
public class FileUploadController {
@RequestMapping("/fileupload")
public String fileupload(MultipartFile file) throws IOException {
// 上传文件方法
file.transferTo(new File("abc.png"));
return "page.jsp";
}
}
file.getoriginalFilename()
ServletContext context = request.getServletContext();
String basePath = context.getRealPath("/uploads");
File file = new File(basePath+"/");
if(!file.exists())file.mkdirs();
String uuid = UUID.randomUUID().toString().replace("-","").toUpperCase();
案例:文件路径和多文件上传
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
@Controller
public class FileUploadController {
@RequestMapping("/fileupload")
public String fileupload(MultipartFile file,MultipartFile file1,MultipartFile file2, HttpServletRequest request) throws IOException {
// System.out.println(file.getSize()); // 文件大小
// System.out.println(file.getBytes()); // 可以用于写文件
// System.out.println(file.getContentType()); // 类型
// System.out.println(file.getName()); // 是 input 的 name
// System.out.println(file.getOriginalFilename()); // 文件名称
// System.out.println(file.isEmpty()); // 是否为空
if (!file.isEmpty()){
String fileName=file.getOriginalFilename();
// 设置保存的路径
String realPath = request.getServletContext().getRealPath("/images");
file.transferTo(new File(realPath,fileName));
}
if (!file1.isEmpty()){
String fileName=file1.getOriginalFilename();
// 设置保存的路径
String realPath = request.getServletContext().getRealPath("/images");
file1.transferTo(new File(realPath,fileName));
}
if (!file2.isEmpty()){
String fileName=file2.getOriginalFilename();
// 设置保存的路径
String realPath = request.getServletContext().getRealPath("/images");
file2.transferTo(new File(realPath,fileName));
}
return "page.jsp";
}
}
Rest (REpresentational state Transfer)一种网络资源的访问风格,定义了网络资源的访问方式
Restful是按照Rest风格访问网络资源
优点
http://localhost/user/1 GET
http://localhost/user POST
http://localhost/user PUT
http://localhost/user DELETE
注意:上述行为是约定方式,约定不是规范,可以打破,所以称rest风格,而不是Rest规范
SpringMvc支持Restful
Restful规范主要用于前后端分离的项目
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
@RequestMapping("/user/{id}")
@ResponseBody
public String restLocation(@PathVariable Integer id){
System.out.println("我是UserController--------------get:"+id);
return "page.jsp";
}
}
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
//@Controller
//@ResponseBody
@RestController //这句相当于上面的合并
@RequestMapping("/user/")
public class UserController {
@RequestMapping("{id}")
public String restLocation(@PathVariable Integer id){
System.out.println("我是UserController--------------get:"+id);
return "page.jsp";
}
}
web.xml
让SpringMVC支持PUT和DELETE请求行为
<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">
<filter>
<filter-name>characterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>characterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>hiddenHttpMethodFilterfilter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilterfilter-name>
<servlet-name>DispatcherServletservlet-name>
filter-mapping>
<servlet>
<servlet-name>DispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:spring-mvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>DispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
在控制器里写
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
//@Controller
//@ResponseBody
@RestController //这句相当于上面的合并
@RequestMapping("/user/")
public class UserController {
// @RequestMapping(value = "{id}",method = RequestMethod.GET)
@GetMapping("{id}") //等于上面的那句话
public String get(@PathVariable Integer id){
System.out.println("我是UserController--------------get:"+id);
return "page.jsp";
}
// @RequestMapping(value = "{id}",method = RequestMethod.POST)
@PostMapping("{id}") //等于上面的那句话
public String post(@PathVariable Integer id){
System.out.println("我是UserController--------------post:"+id);
return "page.jsp";
}
// @RequestMapping(value = "{id}",method = RequestMethod.PUT)
@PutMapping("{id}") //等于上面的那句话
public String put(@PathVariable Integer id){
System.out.println("我是UserController--------------put:"+id);
return "page.jsp";
}
// @RequestMapping(value = "{id}",method = RequestMethod.DELETE)
@DeleteMapping("{id}") //等于上面的那句话
public String delete(@PathVariable Integer id){
System.out.println("我是UserController--------------delete:"+id);
return "page.jsp";
}
}
一款可以发送Restful风格请求的工具,方便开发调试。首次运行需要联网注册
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
注意:6版本以上要 tomcat8.5 以上的版本
......
<dependency>
<groupId>javax.validationgroupId>
<artifactId>validation-apiartifactId>
<version>2.0.1.Finalversion>
dependency>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.1.0.Finalversion>
dependency>
......
package com.liu.controller;
import com.liu.domain.Employee;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@Controller
public class EmployeeController {
@RequestMapping("/addemployee")
public String addEmployee(@Valid Employee employee){
return "success.jsp";
}
}
package com.liu.domain;
import javax.validation.constraints.NotBlank;
public class Employee {
@NotBlank(message = "姓名不能为空")
private String name;
private Integer age;
......
}
package com.liu.controller;
import com.liu.domain.Employee;
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 EmployeeController {
@RequestMapping("/addemployee")
public String addEmployee(@Valid Employee employee, Errors errors, Model model){
if (errors.hasErrors()){ // 条件是否成立
List<FieldError> fieldErrors = errors.getFieldErrors(); // 条件成立所有对象
for (FieldError error :fieldErrors){
// System.out.println(error.getField());
// System.out.println(error.getDefaultMessage());
// 封装返回页面
model.addAttribute(error.getField(),error.getDefaultMessage());
}
return "addemployee.jsp";
}
return "success.jsp";
}
}
@NotNull(message="请输入您的年龄")
@Max(value=60,message="年龄最大值不允许超过60岁")
@Min(value=18,message="年龄最小值不允许低于18岁")
private Integer age;// 员工年龄
表单数据 | @NotNull | @NotEmpty | @NotBlank |
---|---|---|---|
String s=null | false | false | false |
String s="" | true | false | false |
String s=" " | true | true | false |
String s=“Jock” | true | true | true |
<form action="/addemployee" method="post" >
员工姓名:<input type="text" name="name" value="liu"><span>${name}span><br/>
员工年龄:<input type="text" name="age" value="24"><span>${age}span><br/>
省:<input type="text" name="address.provinceName"><span>${requestScope['address.provinceName']}span>
<input type="submit" value="提交">
form>
实体类Employee.java
package com.liu.domain;
import com.liu.controller.groups.GroupA;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class Employee {
@NotBlank(message = "姓名不能为空",groups = {GroupA.class}) // groups 分组
private String name;
@NotNull(message = "请输入您的年龄",groups = {GroupA.class})
@Max(value = 60,message = "不能超过60")
@Min(value = 18,message = "不能小于18")
private Integer age;
@Valid // 嵌套校验加上这个,这个对象的校验,在自己里面做
private Address address;
......
}
实体类Address.java
package com.liu.domain;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;
public class Address implements Serializable {
@NotBlank(message = "请输入省份名称")
private String ProvinceName;
@NotBlank(message = "请输入城市名称")
private String cityName;
@NotBlank(message = "请输入详细地址")
private String detail;
@NotBlank(message = "请输入邮政编码")
@Size(max = 6,min = 6,message = "邮政编码由6位组成")
private String zipCode;
......
}
package com.liu.controller.groups;
public interface GroupA {
}
package com.liu.controller;
import com.liu.controller.groups.GroupA;
import com.liu.domain.Employee;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
import java.util.List;
@Controller
public class EmployeeController {
//@Validated 支持分组
@RequestMapping("/addemployee")
public String addEmployee(@Validated({GroupA.class}) Employee employee, Errors errors, Model model){
if (errors.hasErrors()){ // 条件是否成立
List<FieldError> fieldErrors = errors.getFieldErrors(); // 条件成立所有对象
for (FieldError error :fieldErrors){
// System.out.println(error.getField());
// System.out.println(error.getDefaultMessage());
// 封装返回页面
model.addAttribute(error.getField(),error.getDefaultMessage());
}
return "addemployee.jsp";
}
return "success.jsp";
}
// @Valid 不支持分组
@RequestMapping("/addemployee2")
public String addEmployee2(@Valid Employee employee, Errors errors, Model model){
if (errors.hasErrors()){
List<FieldError> fieldErrors = errors.getFieldErrors();
for (FieldError error :fieldErrors){
model.addAttribute(error.getField(),error.getDefaultMessage());
}
return "addemployee.jsp";
}
return "success.jsp";
}
}