public class MyThread implements ThrowsAdvice {
public void afterThrowing(Exception ex){
System.out.println("出异常了");
}
}
public class MyAfter implements AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("后置日志");
}
}
public class MyInteceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("环绕前置通知");
//放行
invocation.proceed();
System.out.println("环绕后置通知");
return null;
}
}
@Aspect
@Component
public class Log {
//定义切入点
@Pointcut("execution(* service.impl.UserServiceImpl.*(..))")
public void a(){}
@Before("a()")
public void before(JoinPoint joinPoint){
System.out.println("注解前置通知");
}
@AfterReturning(value = "a()",returning = "obj")
public void after(JoinPoint joinpoint,Object obj){
System.out.println("注解后置通知");
}
//异常通知
@AfterThrowing(value = "a()",throwing = "ex")
public void thr(JoinPoint joinPoint,Exception ex){
System.out.println("异常通知");
}
//环绕通知
@Around(value = "a()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前置");
//放行
Object proceed = joinPoint.proceed();
System.out.println("环绕后置");
return proceed;
}
}
<!--环绕-->
<beans>
<bean id="inter" class="MyInteceptor"/>
<!--后置-->
<bean id="myAfter" class="MyAfter"/>
<!--异常通知-->
<bean id="myThrow" class="MyThread"/>
<aop:config>
<aop:pointcut id="point" expression="execution(* service.impl.UserServiceImpl.*(..))"></aop:pointcut>
<aop:advisor advice-ref="inter" pointcut-ref="point"></aop:advisor>
<aop:advisor advice-ref="myAfter" pointcut-ref="point"/>
<aop:advisor advice-ref="myThrow" pointcut-ref="point"/>
</aop:config>
<bean id="log" class="entity.Log"></bean>
<!--设置注解自动加入通知-->
<aop:aspectj-autoproxy/>
</beans>
mvc拦截器
public class inter implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("pre");
Object login = request.getSession().getAttribute("login");
if (login!=null){
//放行
return true;
}
//跳转到登录界面
response.sendRedirect(request.getContextPath()+"/login.jsp");
//不放行
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
<!--定义拦截器的配置 类需要实现接口implements HandlerInterceptor-->
<mvc:interceptors>
<mvc:interceptor>
<!--<mvc:mapping path="/inter/test1"/>-->
<!--<mvc:mapping path="/mvc/**"/>-->
<mvc:mapping path="/h1"/> <!-- test开头 -->
<!--<mvc:mapping path="/**"/> <!– /** 任意多级任意路径 –>-->
<mvc:exclude-mapping path="/login.jsp"/> <!--不拦截此路径-->
<bean class="com.lee.inter"></bean> <!--拦截器类-->
</mvc:interceptor>
</mvc:interceptors>
异常管理
/**
* 异常解析器处理所有异常
* 配置文件交由spring管理
*/
public class MyException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView=new ModelAndView();
//跳转到页面
if (e instanceof ArithmeticException){
modelAndView.setViewName("error1");
}else if (e instanceof IOException){
modelAndView.setViewName("error2");
}else {
modelAndView.setViewName("hello");
}
return modelAndView;
}
}
<!--定义异常处理的bean 类需要实现接口implements HandlerExceptionResolver-->
<bean class="com.lee.MyException"></bean>
mvc配置拦截器和异常处理以及controller的配置,mvc的使用需要在web.xml文件中配置前端控制器
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 告知springmvc 哪些包中 存在 被注解的类 扫描注解-->
<context:component-scan base-package="com.lee.controller"></context:component-scan>
<!--静态资源过滤 不加这个静态资源会被过滤掉-->
<mvc:default-servlet-handler/>
<!-- 注册注解开发驱动 特定注解需要驱动 -->
<mvc:annotation-driven>
<!-- 安装FastJson,转换器 -->
<!--<mvc:message-converters>-->
<!--<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">-->
<!--<property name="supportedMediaTypes">-->
<!--<list>-->
<!--<value>application/json</value>-->
<!--</list>-->
<!--</property>-->
<!--</bean>-->
<!--</mvc:message-converters>-->
</mvc:annotation-driven>
<!-- 视图解析器
作用:1.捕获后端控制器的返回值="index"
2.解析: 在返回值的前后 拼接 ==> "/index.jsp"
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<!--<property name="prefix" value="/WEB-INF/jsp/"></property>-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!-- 后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!--定义异常处理的bean 类需要实现接口implements HandlerExceptionResolver-->
<bean class="com.lee.MyException"></bean>
<!--定义拦截器的配置 类需要实现接口implements HandlerInterceptor-->
<mvc:interceptors>
<mvc:interceptor>
<!--<mvc:mapping path="/inter/test1"/>-->
<!--<mvc:mapping path="/mvc/**"/>-->
<mvc:mapping path="/h1"/> <!-- test开头 -->
<!--<mvc:mapping path="/**"/> <!– /** 任意多级任意路径 –>-->
<mvc:exclude-mapping path="/login.jsp"/> <!--不拦截此路径-->
<bean class="com.lee.inter"></bean> <!--拦截器类-->
</mvc:interceptor>
</mvc:interceptors>
<!-- 上传解析器
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1048576"/>
</bean>
</beans>
quartz定时器两种方式
注解方式
<!--扫描包-->
<context:component-scan base-package="com.lee"/>
<!--特定注解驱动-->
<task:annotation-driven/>
@Component
public class myjob {
//秒 分 时 日 月 星期 必须有一个问号?,一般写六位即可
@Scheduled(cron = "* * * * * ?")
public void m1(){
System.out.println("敲代码"+new Date());
}
@Scheduled(cron = "5,15,25,30 * * * * ?")
public void m2(){
System.out.println("-------------------------");
}
}
quartz方式二 继承
public class myjob2 implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("敲代码了嘛????");
}
}
<!--工作-->
<bean id="jobDetailFactoryBean" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="name" value="j1"/>
<property name="group" value="g1"/>
<property name="jobClass" value="com.lee.myjob2"/>
</bean>
<!--触发器-->
<bean id="triggerFactoryBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="t1"/>
<property name="group" value="g1"/>
<property name="cronExpression" value="* * * * * ?"/>
<property name="jobDetail" ref="jobDetailFactoryBean"/>
</bean>
<!--scheduler-->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="triggerFactoryBean"/>
</list>
</property>
</bean>
上传 需要pom、上传解析器
<!-- 上传解析器
id必须是:“multipartResolver” -->
<bean id=“multipartResolver”
class=“org.springframework.web.multipart.commons.CommonsMultipartResolver”>
<!-- 最大可上传的文件大小 单位:byte 超出后会抛MaxUploadSizeExceededException异常,可以异常解析器捕获 -->
</property</bean>
@RequestMapping("/test1")
public String hello1(String username,MultipartFile source,HttpSession session) {
//文件的原始名称
String filename = source.getOriginalFilename();
//定制全局唯一的命名
String unique = UUID.randomUUID().toString();
//获得文件的后缀
String ext = FilenameUtils.getExtension(filename);//abc.txt txt hello.html html
//定制全局唯一的文件名
String uniqueFileName = unique+"."+ext;
System.out.println("唯一的文件名:"+uniqueFileName);
//文件的类型
String type = source.getContentType();
System.out.println("filename:"+filename+" type:"+type);
//获得 upload_file的磁盘路径 ==> 在webapp目录下创建一个目录"upload_file",且此目录初始不要为空,否则编译时被忽略
String real_path = session.getServletContext().getRealPath("/upload_file");
System.out.println("real_path:"+real_path);
//将上传的文件,存入磁盘路径中
//source.transferTo(new File("d:/xxxx/xxxx/xx.jpg"))
source.transferTo(new File(real_path+"\\"+uniqueFileName));
return "index";
}
下载
@RequestMapping("/test1")
public void hello1(String name,HttpSession session,HttpServletResponse response){
System.out.println("name:"+name);
//获得要下载文件的绝对路径
String path = session.getServletContext().getRealPath("/upload_file");
//文件的完整路径
String real_path = path+"\\"+name;
//设置响应头 告知浏览器,要以附件的形式保存内容 filename=浏览器显示的下载文件名
response.setHeader("content-disposition","attachment;filename="+name);
//读取目标文件,写出给客户端
IOUtils.copy(new FileInputStream(real_path), response.getOutputStream());
//上一步,已经是响应了,所以此handler直接是void
}
fastjson
- 日期格式化:@JSONField(format=“yyyy/MM/dd”)
- 属性名修改:@JSONField(name=“birth”)
- 忽略属性:@JSONField(serialize = false)
- 包含null值:@JSONField(serialzeFeatures = SerializerFeature.WriteMapNullValue) 默认会忽略所有null值,有此注解会输出null
- @JSONField(serialzeFeatures = SerializerFeature.WriteNullStringAsEmpty) null的String输出为""
- 自定义序列化:@JSONField(serializeUsing = MySerializer2.class)
public class User implements Serializable{
@JSONField(serialize = false)
private Integer id;
@JSONField(name="NAME",serialzeFeatures = SerializerFeature.WriteNullStringAsEmpty)
private String name;
@JSONField(serialzeFeatures = SerializerFeature.WriteMapNullValue)
private String city;
@JSONField(format="yyyy/MM/dd")
private Date birth;
@JSONField(serializeUsing = MySerializer2.class)
private Double salary;
...
}
public class MySerializer2 implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
int features) throws IOException {
Double value = (Double) object; // salary属性值
String text = value + "元";// 在salary后拼接 “元”
serializer.write(text); // 输出拼接后的内容
}
}
new User(1,null,null,new Date(),100.5);
// 如上对象,转换json:
{NAME:"",city:null,"birth":"2020/12/12","salary":"100.5元"}
jackjson
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date birth;
@JsonProperty("new_id") //不再使用原属性名,而是 "new_id"
private Integer id;
@JsonIgnore // 生成json时,忽略此属性
private String name;
@JsonInclude(JsonInclude.Include.NON_NULL) // 若"name==null" 忽略此属性
private String name;
@JsonInclude(value= JsonInclude.Include.NON_EMPTY) // 若hobby长度为0或==null 忽略此属性
private List<String> hobby;
自定义序列化jackjson
@JsonSerialize(using = MySerializer.class) // 使用MySerializer输出某属性
public class User {
private Integer id;
private String name;
@JsonSerialize(using = MySerializer.class)
private Double salary = 10000.126;//在输出此属性时,使用MySerializer输出
....
get/set
}
则输出json时:{"id":xx,"name":"xxx","salary":10000.13}
public class MySerializer extends JsonSerializer<Double> {
// value即 Double salary的值
@Override
public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// 将Double salary的值 四舍五入
String number = BigDecimal.valueOf(value).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
// 输出 四舍五入后的值
gen.writeNumber(number);
}
}
特定的注解驱动
<!--特定注解驱动controller-->
<mvc:annotation-driven/>
<!--特定注解驱动 定时器-->
<task:annotation-driven/>
<!--特定注解驱动 事务-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>