1️⃣JSON
一、什么是json?
json的全称为:JavaScript Object Notation,是一种轻量级的数据交互格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。【以上来自于百度百科】
简单来说:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互。
类似于:
- 国际通用语言-英语
- 中国56个民族不同地区的通用语言-普通话。
但真要说json到底是什么,以及json的作用,我们总是难以描述,下面我将从各个方面来进行说明:
二、与javascript的关系
相信很多程序员只要一提到json总会想到js,因为json不仅含有js的名字,其格式也与js中对象(object)的格式并无一二。
这里我们要进行一个说明,首先json是基于ECMAScript语法,但这并不意味着json必须在js中使用,或者必须要产生什么联系,json在js中的处理也并没有比其他语言占有更多优势。只是因为语法相似,而使得js开发者能更快的上手json而已。
事实上几乎所有编程语言中都有对json数据转换的支持:
js中,json与对象的转换:JSON.parse()
/JSON.stringify()
;
php中,json与数组的转换:json_encode()
/json_decode()
;
java中,json与对象的转换:fromJson()
/toJson()
;
python中,json与对象的转换:json.dumps()
/json.loads()
;
三、语法格式
那么json的语法格式到底是怎样的呢?我们先来看一段json数据:
{"name":"admin","age":18}
这就是一种最简单的json,如果有学过js的开发者是不是发现json的语法与js中object的语法几乎相同。
但是,注意:
- json是一种纯字符数据,不属于编程语言
- json的语法与js中object的语法几乎一致(下一部分说明不同)
- json数据以键值对形式存在,多个键值对之间用逗号
,
隔开,键值对的键和值之间用冒号:
连接 - json数据在js对象的基础上做了严格化
- json数据中的键值对可以使用编程语言中所谓的关键字(*见注意事项)
- json的数据可以用花括号
{}
或中括号[]
包裹,对应js中的object和array
四、注意事项
为什么说几乎相同,而不是完全相同呢?接下来我们要说的就是json与js中对象的不同点,也是json严格要求的部分:
- json的键值对的键部分,必须用双引号
"
包裹,单引号都不行(所以如果在键中出现了关键字,也被字符化了),而js中对象没有强制要求(所以在键中不允许出现关键字) - json的键值对的值部分,不允许出现函数
function
,undefined
,NaN
,但是可以有null
,js中对象的值中可以出现 - json数据结束后,不允许出现没有意义的逗号
,
如:{"name":"admin","age":18,}
,注意看数据结尾部分18的后面的逗号,不允许出现
五、总结
所以,json数据的格式可以是:
{"name":"admin","age":18}
也可以是:
["hello",3.1415,"json"]
还可以是:
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]
不能是:(key没有双引号)
{"name":"admin",age:18}
不能是:(无意义的逗号)
{"name":"admin","age":18,}
不能是:(不允许出现函数)
{"name":"admin","age":18,"show":function()()}
不能是:(不允许出现undefined)
{"name":"admin","age":18,"show":undefined}
不能是:(不允许出现NaN)
{"name":"admin","age":18,"strong":NaN}
不能是:(无意义的逗号)
["hello",3.1415,"json",]
不能是:(无意义的逗号)
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20},]
以上内容,希望能对以后使用json有所帮助,简单来说json处理的是
对象{},数值[ ] , 混合 {rows: [ ]}以及 json转换的注解
其实作为通用数据,xml也是一种不错的选择,但是随着json的出现,xml的使用场景正慢慢被json蚕食,相对来说json在某些方面下的体现还是比xml稍具优势,后期可再开一篇文档说明json和xml的区别。
六,使用json
1导入pom.xml依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.3</version> </dependency>
2.配置spring-mvc.xml
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="mappingJackson2HttpMessageConverter"/> </list> </property> </bean> <bean id="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <!--处理中文乱码以及避免IE执行AJAX时,返回JSON出现下载文件--> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>text/json;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> </bean>
3. @ResponseBody注解使用
@ResponseBody
注解的作用是将Controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON
数据或者是XML数据。注意:在使用此注解之后不会再走视图解析器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
创建一个web层控制器
package com.xzs.web; import com.xzs.Biz.ClazzBiz; import com.xzs.model.Clazz; import com.xzs.utils.PageBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.List; import java.util.Map; @Controller @RequestMapping("/clz/json") public class JsonController { @Autowired private ClazzBiz clazzBiz; /** * 返回List<T> * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/list") public List<Clazz> list(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean); return lst; } /** * 返回T * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/load") public Clazz load(HttpServletRequest req, Clazz clazz){ if(clazz.getCid() != null){ List<Clazz> lst = this.clazzBiz.listPager(clazz, null); return lst.get(0); } return null; } /** * 返回List<Map> * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/mapList") public List<Map> mapList(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Map> lst = this.clazzBiz.mapListPager(clazz, pageBean); return lst; } /** * 返回Map * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/mapLoad") public Map mapLoad(HttpServletRequest req, Clazz clazz){ if(clazz.getCid() != null){ List<Map> lst = this.clazzBiz.mapListPager(clazz, null); return lst.get(0); } return null; } @ResponseBody @RequestMapping("/all") public Map all(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean); Map map = new HashMap(); map.put("lst",lst); map.put("pageBean",pageBean); return map; } @ResponseBody @RequestMapping("/jsonStr") public String jsonStr(HttpServletRequest req, Clazz clazz){ return "clzEdit"; } }
在ClazzMapper.xml中创建
<select id="mapListPager" resultType="java.util.Map" parameterType="java.lang.Integer" > select <include refid="Base_Column_List" /> from t_struts_class <where><if test="cname !=null"> and cname like concat('%',#{cname},'%') </if></where> </select>
注意!!!这里方法返回的是map值所以resultType中的属性值要填java.util.Map
在ClazzMapper中实现该方法
package com.xzs.mapper; import com.xzs.model.Clazz; import com.xzs.utils.PageBean; import java.util.List; import java.util.Map; public interface ClazzMapper { int deleteByPrimaryKey(Integer cid); int insert(Clazz record); int insertSelective(Clazz record); Clazz selectByPrimaryKey(Integer cid); int updateByPrimaryKeySelective(Clazz record); int updateByPrimaryKey(Clazz record); List<Clazz> listPger(Clazz clazz); List<Map> mapListPager(Clazz clazz); }
编写ClazzBiz
package com.xzs.Biz; import com.xzs.model.Clazz; import com.xzs.utils.PageBean; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; @Repository public interface ClazzBiz { int deleteByPrimaryKey(Integer cid); int insert(Clazz record); int insertSelective(Clazz record); Clazz selectByPrimaryKey(Integer cid); int updateByPrimaryKeySelective(Clazz record); int updateByPrimaryKey(Clazz record); List<Clazz> listPager(Clazz clazz, PageBean page); List<Map> mapListPager(Clazz clazz, PageBean page); }
实现接口
package com.xzs.Impl; import com.xzs.Biz.ClazzBiz; import com.xzs.mapper.ClazzMapper; import com.xzs.model.Clazz; import com.xzs.utils.PageBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class ClazzBizImpl implements ClazzBiz { @Autowired private ClazzMapper clazzMapper; @Override public int deleteByPrimaryKey(Integer cid) { return clazzMapper.deleteByPrimaryKey(cid); } @Override public int insert(Clazz record) { return clazzMapper.insert(record); } @Override public int insertSelective(Clazz record) { return clazzMapper.insertSelective(record); } @Override public Clazz selectByPrimaryKey(Integer cid) { return clazzMapper.selectByPrimaryKey(cid); } @Override public int updateByPrimaryKeySelective(Clazz record) { return clazzMapper.updateByPrimaryKeySelective(record); } @Override public int updateByPrimaryKey(Clazz record) { return clazzMapper.updateByPrimaryKey(record); } @Override public List<Clazz> listPager(Clazz clazz, PageBean pageBean) { return clazzMapper.listPger(clazz); } @Override public List<Map> mapListPager(Clazz clazz, PageBean pageBean) { return clazzMapper.mapListPager(clazz); } }
测试:
public List list方法
public Clazz load 方法
public List mapList方法
public Map mapLoad方法
public Map all方法
public String jsonStr方法
注意:当我们的方法全部都是返SON对象时 @ResponseBody可以放在只写一个但是必须得是上述JsonController中@Controller的上方并且( @ResponseBody,@Controller)等于@RestController如果在JsonController中将 public String jsonStr方法上的@ResponseBody给注释掉那么将不再返回json数据而是进行页面跳转
证明:
import com.xzs.utils.PageBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.List; import java.util.Map; @Controller @RequestMapping("/clz/json") public class JsonController { @Autowired private ClazzBiz clazzBiz; /** * 返回List<T> * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/list") public List<Clazz> list(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean); return lst; } /** * 返回T * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/load") public Clazz load(HttpServletRequest req, Clazz clazz){ if(clazz.getCid() != null){ List<Clazz> lst = this.clazzBiz.listPager(clazz, null); return lst.get(0); } return null; } /** * 返回List<Map> * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/mapList") public List<Map> mapList(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Map> lst = this.clazzBiz.mapListPager(clazz, pageBean); return lst; } /** * 返回Map * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/mapLoad") public Map mapLoad(HttpServletRequest req, Clazz clazz){ if(clazz.getCid() != null){ List<Map> lst = this.clazzBiz.mapListPager(clazz, null); return lst.get(0); } return null; } @ResponseBody @RequestMapping("/all") public Map all(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean); Map map = new HashMap(); map.put("lst",lst); map.put("pageBean",pageBean); return map; } // @ResponseBody @RequestMapping("/jsonStr") public String jsonStr(HttpServletRequest req, Clazz clazz){ return "clzEdit"; } }
package com.xzs.web; import com.xzs.Biz.ClazzBiz; import com.xzs.model.Clazz; import com.xzs.utils.PageBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.List; import java.util.Map; @ResponseBody @Controller @RequestMapping("/clz/json") public class JsonController { @Autowired private ClazzBiz clazzBiz; /** * 返回List<T> * @param req * @param clazz * @return */ // @ResponseBody @RequestMapping("/list") public List<Clazz> list(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean); return lst; } /** * 返回T * @param req * @param clazz * @return */ // @ResponseBody @RequestMapping("/load") public Clazz load(HttpServletRequest req, Clazz clazz){ if(clazz.getCid() != null){ List<Clazz> lst = this.clazzBiz.listPager(clazz, null); return lst.get(0); } return null; } /** * 返回List<Map> * @param req * @param clazz * @return */ // @ResponseBody @RequestMapping("/mapList") public List<Map> mapList(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Map> lst = this.clazzBiz.mapListPager(clazz, pageBean); return lst; } /** * 返回Map * @param req * @param clazz * @return */ @ResponseBody @RequestMapping("/mapLoad") public Map mapLoad(HttpServletRequest req, Clazz clazz){ if(clazz.getCid() != null){ List<Map> lst = this.clazzBiz.mapListPager(clazz, null); return lst.get(0); } return null; } @ResponseBody @RequestMapping("/all") public Map all(HttpServletRequest req, Clazz clazz){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean); Map map = new HashMap(); map.put("lst",lst); map.put("pageBean",pageBean); return map; } // @ResponseBody @RequestMapping("/jsonStr") public String jsonStr(HttpServletRequest req, Clazz clazz){ return "clzEdit"; } }
隐藏数据
在实体类中在要隐藏的属性上添加@JsonIgnore即可
package com.xzs.model; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data//相当于set get toString方法 @AllArgsConstructor //有参构造器 @NoArgsConstructor public class Clazz { @NotNull(message = "班级编号不能为空") // @Size(max = 100,min = 10,message = "大小必须在10至100之间") protected Integer cid; @NotBlank(message = "班级名不能为空") protected String cname; @NotBlank(message = "班级教员老师不能为空") protected String cteacher; @JsonIgnore private String pic="暂无图片"; }
2.异常处理机制
1.为什么要全局异常处理?
我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。
2.异常处理思路
系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。
3.SpringMVC异常分类
- 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
- 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器;
- 使用@ControllerAdvice + @ExceptionHandler
4.异常处理方法
@RequestMapping("/mapList") public List<Map> mapList(HttpServletRequest req, Clazz clazz){ System.out.println((1 / 0)); PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Map> lst = this.clazzBiz.mapListPager(clazz, pageBean); return lst; }
方法一
<!-- springmvc提供的简单异常处理器 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- 定义默认的异常处理页面 --> <property name="defaultErrorView" value="error"/> <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception --> <property name="exceptionAttribute" value="ex"/> <!-- 定义需要特殊处理的异常,这是重要点 --> <property name="exceptionMappings"> <props> <prop key="java.lang.RuntimeException">error</prop> </props> <!-- 还可以定义其他的自定义异常 --> </property> </bean>
编写错误界面error.jsp
<%-- Created by IntelliJ IDEA. User: xzs Date: 2023/9/13 Time: 16:48 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> 网络异常 </body> </html>
方法二
package com.xzs.exception; public class GlobalException extends RuntimeException { public GlobalException() { } public GlobalException(String message) { super(message); } public GlobalException(String message, Throwable cause) { super(message, cause); } public GlobalException(Throwable cause) { super(cause); } public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }
package com.xzs.component; import com.xzs.exception.GlobalException; 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 GlobalExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { ModelAndView mv = new ModelAndView(); mv.setViewName("error"); if (e instanceof GlobalException){ GlobalException globalException = (GlobalException) e; mv.addObject("ex",globalException.getMessage()); mv.addObject("msg","全局异常...."); }else if (e instanceof RuntimeException){ RuntimeException runtimeException = (RuntimeException) e; mv.addObject("ex",runtimeException.getMessage()); mv.addObject("msg","运行时异常...."); }else { RuntimeException runtimeException = (RuntimeException) e; mv.addObject("ex",runtimeException.getMessage()); mv.addObject("msg","其他时异常...."); } return mv; } }
编写错误界面
<%-- Created by IntelliJ IDEA. User: xzs Date: 2023/9/13 Time: 16:48 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> 网络异常 ${msg} </body> </html>
运行结果
方法三
package com.xzs.component; import com.xzs.exception.GlobalException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; import java.util.Map; @ControllerAdvice public class GlobalExceptionResolver { // 跳转错误页面 // @ExceptionHandler // public ModelAndView handler(Exception e){ // ModelAndView mv = new ModelAndView(); // mv.setViewName("error"); // if (e instanceof GlobalException){ // GlobalException globalException = (GlobalException) e; // mv.addObject("ex",globalException.getMessage()); // mv.addObject("msg","全局异常...."); // }else if (e instanceof RuntimeException){ // RuntimeException runtimeException = (RuntimeException) e; // mv.addObject("ex",runtimeException.getMessage()); // mv.addObject("msg","运行时异常...."); // } // return mv; // } // 返回错误json数据 @ResponseBody @ExceptionHandler public Map handler(Exception e){ Map map = new HashMap(); if (e instanceof GlobalException){ GlobalException globalException = (GlobalException) e; map.put("ex",globalException.getMessage()); map.put("msg","全局异常...."); }else if (e instanceof RuntimeException){ RuntimeException runtimeException = (RuntimeException) e; map.put("ex",runtimeException.getMessage()); map.put("msg","运行时异常...."); }else { map.put("ex",e.getMessage()); map.put("msg","其它异常...."); } return map; } }
返回json数据
package com.xzs.component; import com.xzs.exception.GlobalException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.HashMap; import java.util.Map; @ControllerAdvice public class GlobalExceptionResolver { //跳转错误页面 @ExceptionHandler public ModelAndView handler(Exception e){ ModelAndView mv = new ModelAndView(); mv.setViewName("error"); if (e instanceof GlobalException){ GlobalException globalException = (GlobalException) e; mv.addObject("ex",globalException.getMessage()); mv.addObject("msg","全局异常...."); }else if (e instanceof RuntimeException){ RuntimeException runtimeException = (RuntimeException) e; mv.addObject("ex",runtimeException.getMessage()); mv.addObject("msg","运行时异常...."); } return mv; } // 返回错误json数据 // @ResponseBody // @ExceptionHandler // public Map handler(Exception e){ // Map map = new HashMap(); // if (e instanceof GlobalException){ // GlobalException globalException = (GlobalException) e; // map.put("ex",globalException.getMessage()); // map.put("msg","全局异常...."); // }else if (e instanceof RuntimeException){ // RuntimeException runtimeException = (RuntimeException) e; // map.put("ex",runtimeException.getMessage()); // map.put("msg","运行时异常...."); // }else { // map.put("ex",e.getMessage()); // map.put("msg","其它异常...."); // } // return map; // } }