Springboot项目搭建总结
2018-02-24 11:19
423 查看
Springboot项目搭建
SpringBoot是一个内嵌了web服务器(tomcat,jetty)的可执行程序的框架,拟开发的web应用不需要war包部署到web服务器上,而是作为一个可执行程序,启动时把web服务器配置好,加载起来。springboot比较适合微服务部署方式,不在是把一堆应用放到一个web服务器下,重启web服务器会影响到其他的应用,而是每个应用独立作为一个可执行程序,启动时把web服务器配置好。
springCloud是一套微服务开发和治理的框架,是管理一大堆SpringBoot项目之间关联关系的框架,比如SpringBoot项目之间远程调用,动态服务发现,负载均衡,限流等,可以实现像dubbo一样的功能。
总结来说 @SpringBootConfiguration注解就是由一下注解来组合而成的
1.@Configuration
2.@ComponentScan
3.EnableAutoConfigurationImportSelector.class
4.AutoConfigurationPackages.Registrar.class
MyBatis数据源1配置文件配置(这里配置两个数据源):
package net.chrone.merchant.service.datasource;
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
@MapperScan(basePackages={"net.chrone.merchant.service.dfpay.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory")
public class MyBatisConfiguration{
private static final Logger logger = Logger.getLogger(MyBatisConfiguration.class);
@Autowired
private Environment env;
@Bean(name="first.datasource")
@Primary
public DataSource getDataSource() {
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName(env.getProperty("custom.datasource.driverClassName").trim());
basic.setUrl(env.getProperty("custom.datasource.url").trim());
basic.setUsername(env.getProperty("custom.datasource.username").trim());
basic.setPassword(env.getProperty("custom.datasource.password").trim());
logger.info("init first datasource now ......" + basic.isClosed());
try{
basic.setMaxActive(Integer.parseInt(env.getProperty("spring.datasource.max-active")));
}catch(Exception e){
}
try{
basic.setMaxIdle(Integer.parseInt(env.getProperty("spring.datasource.max-idle")));
}catch(Exception e){
}
try{
basic.setMinIdle(Integer.parseInt(env.getProperty("spring.datasource.min-idle")));
}catch(Exception e){
}
try{
basic.setInitialSize(Integer.parseInt(env.getProperty("spring.datasource.initial-size")));
}catch(Exception e){
}
try{
basic.setMinEvictableIdleTimeMillis(Long.parseLong(env.getProperty("spring.datasource.min-evictable-idle-time-millis")));
}catch(Exception e){
}
try{
basic.setMaxWait(Long.parseLong(env.getProperty("spring.datasource.max-wait-millis")));
}catch(Exception e){
}
try{
basic.setTimeBetweenEvictionRunsMillis(Long.parseLong(env.getProperty("spring.datasource.time-between-eviction-runs-millis")));
}catch(Exception e){
}
try{
basic.setValidationQuery(env.getProperty("spring.datasource.validation-query"));
}catch(Exception e){
}
return basic;
}
@Bean(name="sqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory() throws IOException{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(getDataSource());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:net/chrone/merchant/service/dfpay/mapper/*.xml"));
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = bean.getObject();
}catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
return sqlSessionFactory;
}
}
MyBatis数据源2配置文件配置(这里配置两个数据源):
package net.chrone.merchant.service.datasource;
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@Configuration
@PropertySource("classpath:application.properties")
@MapperScan(basePackages = { "net.chrone.merchant.service.mapper" }, sqlSessionFactoryRef = "sqlSessionFactoryEpay")
public class EpayschConfiguration{
private static final Logger logger = Logger.getLogger(EpayschConfiguration.class);
@Autowired
private Environment env;
@Bean(name="second.datasource")
public DataSource getDataSource() {
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName(env.getProperty("spring.datasource.driverClassName").trim());
basic.setUrl(env.getProperty("spring.datasource.url").trim());
basic.setUsername(env.getProperty("spring.datasource.username").trim());
basic.setPassword(env.getProperty("spring.datasource.password").trim());
logger.info("init second datasource now ......" + basic.isClosed());
try{
basic.setMaxActive(Integer.parseInt(env.getProperty("spring.datasource.max-active")));
}catch(Exception e){
}
try{
basic.setMaxIdle(Integer.parseInt(env.getProperty("spring.datasource.max-idle")));
}catch(Exception e){
}
try{
basic.setMinIdle(Integer.parseInt(env.getProperty("spring.datasource.min-idle")));
}catch(Exception e){
}
try{
basic.setInitialSize(Integer.parseInt(env.getProperty("spring.datasource.initial-size")));
}catch(Exception e){
}
try{
basic.setMinEvictableIdleTimeMillis(Long.parseLong(env.getProperty("spring.datasource.min-evictable-idle-time-millis")));
}catch(Exception e){
}
try{
basic.setMaxWait(Long.parseLong(env.getProperty("spring.datasource.max-wait-millis")));
}catch(Exception e){
}
try{
basic.setTimeBetweenEvictionRunsMillis(Long.parseLong(env.getProperty("spring.datasource.time-between-eviction-runs-millis")));
}catch(Exception e){
}
try{
basic.setValidationQuery(env.getProperty("spring.datasource.validation-query"));
}catch(Exception e){
}
return basic;
}
@Bean(name = "sqlSessionFactoryEpay")
public SqlSessionFactory sqlSessionFactory() throws IOException {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(getDataSource());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:net/chrone/merchant/service/mapper/*.xml"));
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = bean.getObject();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
return sqlSessionFactory;
}
}
服务器错误页面跳转配置bean
package net.chrone.merchant.service.config;
import org.springframework.boot.context.embedded.ErrorPage;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.http.HttpStatus;
public class ServerConfig extends ServerProperties{
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
super.customize(container);
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,"/404.jsp"));
container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/500.jsp"));
container.addErrorPages(new ErrorPage("/error.jsp"));
}
}
springMVC配置:实现页面跳转
package net.chrone.merchant.service.config;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import net.chrone.merchant.service.filter.CheckPwdFilter;
import net.chrone.merchant.service.filter.CheckURLFilter;
import net.chrone.merchant.service.interceptor.MyInterceptor;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/").addResourceLocations("/css/**");
registry.addResourceHandler("/fonts/").addResourceLocations("/fonts/**");
registry.addResourceHandler("/images/").addResourceLocations("/images/**");
registry.addResourceHandler("/scripts/").addResourceLocations("/scripts/**");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
@Bean
public FilterRegistrationBean checkPwdFilterRegistration(){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new CheckPwdFilter());
String[] interceptController = {"/mchntCenter","/agent/*","/dfpay/*","/secondarymerchant/*","/ipManager/*","/mobileValidate/*","/ct/*","/public/*","/account/*","/role/*","/accountCheck/*","/cash/*","/queryrefund/*","/refund/*","/trans/*","/recharge/*","/user/user_list","/user/user_update","/user/user_add","/user/updateUserSt","/user/checkUserId","/user/payPwd","/user/forGetPayPwd","/user/checkPwd","/user/checkPayPwd","/user/updPayPwd","/user/checkCode","/user/newPayPwd","/user/updNewPayPwd","/user/sendEmail","/user/sendSmsCode","/user/user/bindEmail","/user/bindMobile","/user/interfaceKey"};
registration.addUrlPatterns(interceptController);
registration.setName("checkPwdFilter");
return registration;
}
/**
* 错误页面
* @return
*/
@Bean
public ServerProperties getErrorConfig() {
return new ServerConfig();
}
}
自定义拦截器
package net.chrone.merchant.service.interceptor;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.chrone.merchant.service.model.MerLoginUser;
import net.chrone.merchant.service.model.MerMenu;
import net.chrone.mercha
105c4
nt.service.util.ClientSysEvnUtil;
import net.chrone.merchant.service.util.Constants;
import net.chrone.merchant.service.util.LogWriter;
import net.chrone.merchant.service.util.MD5;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.chrone.util.StringUtils;
public class MyInterceptor implements HandlerInterceptor {
private static final Logger logger = Logger.getLogger(MyInterceptor.class);
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
String url=request.getServletPath();
String ip = ClientSysEvnUtil.getIpAddr(request);
String agent = request.getHeader("user-agent");
if (url.startsWith("/public/")||url.equals("/")||url.equals("/secret/random")||url.equals("")){
request.setAttribute("head", "index");
//输出访问日志
try {
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志]--IP:" + ip + "; 来源:" + request.getHeader("referer") + "; 浏览器:" + request.getHeader("user-agent") + "; 访问路径:" + url);
}
} catch (Exception e) {
// 防御容错
}
return true;
}else{
if(request.getSession().getAttribute(Constants.LOGIN_SESSION)==null){
if(url.equals("/mchntCenter")){
request.setAttribute("out_tp", "1");
}
try{
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志-登录超时]--IP:" + ip + "; 来源:" + request.getHeader("referer") + "; 浏览器:" + request.getHeader("user-agent") + "; 访问路径:" + url);
}
}catch(Exception e){
}
request.getRequestDispatcher("/sessionTimeOut.jsp").forward(request, response);
return false;
}
MerLoginUser userInf = (MerLoginUser) request.getSession().getAttribute(Constants.LOGIN_SESSION);
//输出访问日志
try {
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志]--IP:" + ip + "; 商户:" + userInf.getTaccountid() + "; 操作员:" + userInf.getId() + "; 访问路径:" + url);
}
} catch (Exception e) {
// 防御容错
}
String flag = MD5.md5(ip+agent);
if(!flag.equals(Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId())) && null != Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId())){
request.getSession().removeAttribute(Constants.LOGIN_SESSION);
request.getSession().removeAttribute(Constants.LOGIN_MENU);
request.setAttribute("out_tp", "3");
request.getRequestDispatcher("/sessionTimeOut.jsp").forward(request, response);
try{
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志-异地登录]--IP:" + ip + "; 商户:" + userInf.getTaccountid() + "; 操作员:" + userInf.getId() + "; 访问路径:" + url + "; flag-n:" + flag + "; flag-s:" + Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId()) );
}
}catch(Exception e){
}
return false;
}
if(null == Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId())){
Constants.LOGIN_SESSION_ID_MAP.put(userInf.getId(),flag);
}
if(url.startsWith("/mchntCenter")){
request.getSession().removeAttribute("leftfid");
request.getSession().removeAttribute("leftid");
}
if(StringUtils.isNotEmpty(request.getParameter("leftfid"))){
request.getSession().setAttribute("leftfid", request.getParameter("leftfid"));
}
if(StringUtils.isNotEmpty(request.getParameter("leftid"))){
request.getSession().setAttribute("leftid", request.getParameter("leftid"));
}
if(defaultAuth(url)){//默认权限
return true;
}
if(!urlIsAuth(request, url)){
request.getRequestDispatcher("/authError.jsp").forward(request, response);
return false;
}
return true;
}
}
/**
*默认权限
* @return
*/
public boolean defaultAuth(String url){
List<String> list = new ArrayList<String>();
list.add("/home");
list.add("/secret/random");
list.add("/mchntCenter");
list.add("/loginOut");
list.add("/error");
list.add("/public/loginWithMobileSecurityCode");//手机验证
list.add("/user/checkPwd");//检查密码
list.add("/user/checkPayPwd");//检查支付密码
list.add("/user/sendEmail");//发送邮件验证
list.add("/user/checkCode");//检查验证码
list.add("/user/checkUserId");//检查用户名
list.add("/user/updPwdSucc");//密码修改成功跳转
list.add("/user/sendSmsCode");//发送验证码
list.add("/user/hideKey");//隐藏密钥
list.add("/cash/cash");//提现
list.add("/cash/cashConfirm");//提现
list.add("/cash/cashSub");//提现
list.add("/trans/transAccount");//转账
list.add("/trans/verifyInAccount");//转账
list.add("/trans/transAccountConfirm");//转账
list.add("/trans/transAccountSub");//转账
list.add("/trans/verifyPayPwd");//转账
list.add("/recharge/index");//充值
list.add("/recharge/rechargeConfirm");//充值
list.add("/recharge/rechargeSub");//充值
list.add("/user/forGetPayPwd");//忘记支付密码
list.add("/user/newPayPwd");//忘记支付密码
list.add("/user/payPwd");//支付密码
list.add("/user/loginPwd");//登录密码
list.add("/user/forGetPayPwd");//忘记支付密码
list.add("/user/newPayPwd");//忘记支付密码
list.add("/user/payPwd");//支付密码
list.add("/user/loginPwd");//登录密码
list.add("/user/updLoginPwd");//登录密码保存
list.add("/user/updNewPayPwd");//忘记支付密码保存
list.add("/user/updPayPwd");//修改支付密码保存
list.add("/mernotice/updateReadCount");//更新阅读商户通知信息
for(String l:list){
if(url.startsWith(l)){
return true;
}
}
return false;
}
/**
* url是否有访问权限
* @return
*/
public boolean urlIsAuth(HttpServletRequest request,String url){
List<MerMenu> menuInfList = (List<MerMenu>) request.getSession().getAttribute(Constants.LOGIN_MENU);
for(MerMenu menuInf:menuInfList){
try {
if(StringUtils.isNotEmpty(menuInf.getUrl().trim())&&url.startsWith(menuInf.getUrl())){
return true;
}
} catch (Exception e) {
LogWriter.error("异常菜单:"+menuInf);
e.printStackTrace();
}
}
return false;
}
}
自定义url过滤器
package net.chrone.merchant.service.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import net.chrone.merchant.service.util.ClientSysEvnUtil;
import net.chrone.merchant.service.util.LogWriter;
public class CheckURLFilter implements Filter {
@Override
public void init(FilterConfig filterconfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletrequest,
ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletrequest;
HttpServletResponse res = (HttpServletResponse) servletresponse;
String urlString = req.getRequestURI();
if(servletrequest.getCharacterEncoding() == null || !servletrequest.getCharacterEncoding().toUpperCase().equals("UTF-8")){
servletrequest.setCharacterEncoding("UTF-8");
}
LogWriter.info("RemoteAddr:"+ClientSysEvnUtil.getIpAddr(req)+" 开始执行:"+urlString);
long bt = System.currentTimeMillis();
Map<String, String[]> map = servletrequest.getParameterMap();
for(String m:map.keySet()){
if(m.indexOf("password") != -1 || m.indexOf("Password") != -1)
continue;
String[] v = (String[]) map.get(m);
LogWriter.info(m+":"+v[0]);
}
filterchain.doFilter(servletrequest, servletresponse);
long et = System.currentTimeMillis();
LogWriter.debug(urlString+"执行完毕! 耗时:"+(et-bt));
}
@Override
public void destroy() {
}
}
自定义缓存
package net.chrone.merchant.service.config;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* 缓存,超时时间单位:分钟
*
* @author zhangzw 2015-05-19
*
*/
public class Cache<K, V> {
// 声明缓存
private LoadingCache<K, V> graphs;
/**
*
* @param timeOut
* 分钟
*/
public Cache(long timeOut) {
Initialize(timeOut);
}
/**
* 初始化缓存容器
*/
private void Initialize(long timeOut) {
if (timeOut > 0) {
graphs = CacheBuilder.newBuilder()
.expireAfterWrite(timeOut, TimeUnit.MINUTES) //
.build(new CacheLoader<K, V>() {
public V load(K key) {
// 取消默认的自动缓存添加器
return null;
}
});
} else {
graphs = CacheBuilder.newBuilder().build(new CacheLoader<K, V>() {
public V load(K key) {
// 取消默认的自动缓存添加器
return null;
}
});
}
}
/**
* 获取缓存信息
*
* @param key
* @return
*/
@SuppressWarnings("finally")
public V get(K key) {
V v = null;
try {
v = graphs.get(key);
} catch (ExecutionException e) {
} finally {
return v;
}
}
/**
* 设置缓存信息
*
* @param key
* @param value
*/
public void put(K key, V value) {
if (null != key && null != value)
graphs.put(key, value);
}
/**
* 删除一个缓存
*
* @param key
*/
public void remove(String key) {
graphs.invalidate(key);
}
/**
* 清空全部缓存
*/
public void clearAll() {
graphs.invalidateAll();
}
}
springboot启动main方法
package net.chrone.merchant.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//@ServletComponentScan
@SpringBootApplication
@EnableTransactionManagement
@ImportResource({"classpath:applicationContext.xml"})
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Springboot 常用注解
@SpringBootApplication:
包含@Configuration、@EnableAutoConfiguration、@ComponentScan
通常用在主类上。
@Repository:
用于标注数据访问组件,即DAO组件。
@Service:
用于标注业务层组件。
@RestController:
用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody。
@ResponseBody:
表示该方法的返回结果直接写入HTTP response body中
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
@Component:
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@ComponentScan:
组件扫描。个人理解相当于<context:component-scan>,如果扫描到有@Component @Controller @Service等这些注解的类,则把这些类注册为bean。
@Configuration:
指出该类是 Bean 配置的信息源,相当于XML中的<beans></beans>,一般加在主类上。
@Bean:
相当于XML中的<bean></bean>,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
@EnableAutoConfiguration:
让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,一般加在主类上。
@AutoWired:
byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
当加上(required=false)时,就算找不到bean也不报错。
@Qualifier:
当有多个同一类型的Bean时,可以用@Qualifier("name")来指定。与@Autowired配合使用
@Resource(name="name",type="type"):
没有括号内内容的话,默认byName。与@Autowired干类似的事。
@RequestMapping:
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
该注解有六个属性:
params:指定request中必须包含某些参数值时,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
value:指定请求的实际地址,指定的地址可以是URI Template 模式
method:指定请求的method类型, GET、POST、PUT、DELETE等
consumes:指定处理请求的提交内容类型(Content-Type),如application/json,text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
@RequestMapping(value="/testRequestMapping",method= RequestMethod.POST )
案例:
@Controller
@RequestMapping("/user")
public class UserController {
private Logger logger = LoggerFactory.getLogger(LoginController.class);
@Autowired
private MerLoginUserService merLoginUserService;
@RequestMapping("user_list")
public String list(HttpServletRequest request,String start,Model model){
return "user/user_list";
}
}
@RequestParam:
用在方法的参数前面。
@RequestParam String a 相当于String a =request.getParameter("a")。
@PathVariable:
路径变量。参数与大括号里的名字一样要相同。
RequestMapping("user/get/mac/{macAddress}")
public String getByMacAddress(@PathVariable String macAddress){
�
//do something;
}
}
@Profiles
Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。
任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。
@Configuration
@
@Profile("prod")
public class ProductionConfiguration {
// ...
}
}
比如:@Profile("product")
生产环境下加载
@Profile("dev")
开发环境下加载
@Profile("test")
测试环境下加载
@ConfigurationProperties
Spring Boot将尝试校验外部的配置,默认使用JSR-303(如果在classpath路径中)。
你可以轻松的为你的@ConfigurationProperties类添加JSR-303 javax.validation约束注解:
@Component
@
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
@
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
}
全局异常处理
@ControllerAdvice:
包含@Component。可以被扫描到。
统一处理异常。
@ExceptionHandler(Exception.class):
用在方法上面表示遇到这个异常就执行以下方法。
================================================================================================
spring-boot默认提供内嵌的tomcat,所以打包直接生成jar包,用java -jar命令就可以启动。但是,有时候我们更希望一个tomcat来管理多个项目,这种情况下就需要项目是war格式的包而不是jar格式的包。spring-boot同样提供了解决方案,只需要简单的几步更改就可以了,这里提供maven项目的解决方法:
1.将springboot项目的启动类Application.java继承SpringBootServletInitializer并重写configure方法
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{ return application.sources(Application.class); }
public static void main(String[] args) throws Exception
{SpringApplication.run(Application.class, args); }
}
2.在pom.xml文件中,project下面增加package标签
<packaging>war</packaging>
3.还是在pom.xml文件中,dependencies下面添加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>
或者这种方法:
SpringBoot是一个内嵌了web服务器(tomcat,jetty)的可执行程序的框架,拟开发的web应用不需要war包部署到web服务器上,而是作为一个可执行程序,启动时把web服务器配置好,加载起来。springboot比较适合微服务部署方式,不在是把一堆应用放到一个web服务器下,重启web服务器会影响到其他的应用,而是每个应用独立作为一个可执行程序,启动时把web服务器配置好。
springCloud是一套微服务开发和治理的框架,是管理一大堆SpringBoot项目之间关联关系的框架,比如SpringBoot项目之间远程调用,动态服务发现,负载均衡,限流等,可以实现像dubbo一样的功能。
总结来说 @SpringBootConfiguration注解就是由一下注解来组合而成的
1.@Configuration
2.@ComponentScan
3.EnableAutoConfigurationImportSelector.class
4.AutoConfigurationPackages.Registrar.class
MyBatis数据源1配置文件配置(这里配置两个数据源):
package net.chrone.merchant.service.datasource;
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
@MapperScan(basePackages={"net.chrone.merchant.service.dfpay.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory")
public class MyBatisConfiguration{
private static final Logger logger = Logger.getLogger(MyBatisConfiguration.class);
@Autowired
private Environment env;
@Bean(name="first.datasource")
@Primary
public DataSource getDataSource() {
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName(env.getProperty("custom.datasource.driverClassName").trim());
basic.setUrl(env.getProperty("custom.datasource.url").trim());
basic.setUsername(env.getProperty("custom.datasource.username").trim());
basic.setPassword(env.getProperty("custom.datasource.password").trim());
logger.info("init first datasource now ......" + basic.isClosed());
try{
basic.setMaxActive(Integer.parseInt(env.getProperty("spring.datasource.max-active")));
}catch(Exception e){
}
try{
basic.setMaxIdle(Integer.parseInt(env.getProperty("spring.datasource.max-idle")));
}catch(Exception e){
}
try{
basic.setMinIdle(Integer.parseInt(env.getProperty("spring.datasource.min-idle")));
}catch(Exception e){
}
try{
basic.setInitialSize(Integer.parseInt(env.getProperty("spring.datasource.initial-size")));
}catch(Exception e){
}
try{
basic.setMinEvictableIdleTimeMillis(Long.parseLong(env.getProperty("spring.datasource.min-evictable-idle-time-millis")));
}catch(Exception e){
}
try{
basic.setMaxWait(Long.parseLong(env.getProperty("spring.datasource.max-wait-millis")));
}catch(Exception e){
}
try{
basic.setTimeBetweenEvictionRunsMillis(Long.parseLong(env.getProperty("spring.datasource.time-between-eviction-runs-millis")));
}catch(Exception e){
}
try{
basic.setValidationQuery(env.getProperty("spring.datasource.validation-query"));
}catch(Exception e){
}
return basic;
}
@Bean(name="sqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory() throws IOException{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(getDataSource());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:net/chrone/merchant/service/dfpay/mapper/*.xml"));
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = bean.getObject();
}catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
return sqlSessionFactory;
}
}
MyBatis数据源2配置文件配置(这里配置两个数据源):
package net.chrone.merchant.service.datasource;
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@Configuration
@PropertySource("classpath:application.properties")
@MapperScan(basePackages = { "net.chrone.merchant.service.mapper" }, sqlSessionFactoryRef = "sqlSessionFactoryEpay")
public class EpayschConfiguration{
private static final Logger logger = Logger.getLogger(EpayschConfiguration.class);
@Autowired
private Environment env;
@Bean(name="second.datasource")
public DataSource getDataSource() {
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName(env.getProperty("spring.datasource.driverClassName").trim());
basic.setUrl(env.getProperty("spring.datasource.url").trim());
basic.setUsername(env.getProperty("spring.datasource.username").trim());
basic.setPassword(env.getProperty("spring.datasource.password").trim());
logger.info("init second datasource now ......" + basic.isClosed());
try{
basic.setMaxActive(Integer.parseInt(env.getProperty("spring.datasource.max-active")));
}catch(Exception e){
}
try{
basic.setMaxIdle(Integer.parseInt(env.getProperty("spring.datasource.max-idle")));
}catch(Exception e){
}
try{
basic.setMinIdle(Integer.parseInt(env.getProperty("spring.datasource.min-idle")));
}catch(Exception e){
}
try{
basic.setInitialSize(Integer.parseInt(env.getProperty("spring.datasource.initial-size")));
}catch(Exception e){
}
try{
basic.setMinEvictableIdleTimeMillis(Long.parseLong(env.getProperty("spring.datasource.min-evictable-idle-time-millis")));
}catch(Exception e){
}
try{
basic.setMaxWait(Long.parseLong(env.getProperty("spring.datasource.max-wait-millis")));
}catch(Exception e){
}
try{
basic.setTimeBetweenEvictionRunsMillis(Long.parseLong(env.getProperty("spring.datasource.time-between-eviction-runs-millis")));
}catch(Exception e){
}
try{
basic.setValidationQuery(env.getProperty("spring.datasource.validation-query"));
}catch(Exception e){
}
return basic;
}
@Bean(name = "sqlSessionFactoryEpay")
public SqlSessionFactory sqlSessionFactory() throws IOException {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(getDataSource());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:net/chrone/merchant/service/mapper/*.xml"));
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = bean.getObject();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
return sqlSessionFactory;
}
}
服务器错误页面跳转配置bean
package net.chrone.merchant.service.config;
import org.springframework.boot.context.embedded.ErrorPage;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.http.HttpStatus;
public class ServerConfig extends ServerProperties{
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
super.customize(container);
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,"/404.jsp"));
container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/500.jsp"));
container.addErrorPages(new ErrorPage("/error.jsp"));
}
}
springMVC配置:实现页面跳转
package net.chrone.merchant.service.config;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import net.chrone.merchant.service.filter.CheckPwdFilter;
import net.chrone.merchant.service.filter.CheckURLFilter;
import net.chrone.merchant.service.interceptor.MyInterceptor;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/").addResourceLocations("/css/**");
registry.addResourceHandler("/fonts/").addResourceLocations("/fonts/**");
registry.addResourceHandler("/images/").addResourceLocations("/images/**");
registry.addResourceHandler("/scripts/").addResourceLocations("/scripts/**");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
@Bean
public FilterRegistrationBean checkPwdFilterRegistration(){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new CheckPwdFilter());
String[] interceptController = {"/mchntCenter","/agent/*","/dfpay/*","/secondarymerchant/*","/ipManager/*","/mobileValidate/*","/ct/*","/public/*","/account/*","/role/*","/accountCheck/*","/cash/*","/queryrefund/*","/refund/*","/trans/*","/recharge/*","/user/user_list","/user/user_update","/user/user_add","/user/updateUserSt","/user/checkUserId","/user/payPwd","/user/forGetPayPwd","/user/checkPwd","/user/checkPayPwd","/user/updPayPwd","/user/checkCode","/user/newPayPwd","/user/updNewPayPwd","/user/sendEmail","/user/sendSmsCode","/user/user/bindEmail","/user/bindMobile","/user/interfaceKey"};
registration.addUrlPatterns(interceptController);
registration.setName("checkPwdFilter");
return registration;
}
/**
* 错误页面
* @return
*/
@Bean
public ServerProperties getErrorConfig() {
return new ServerConfig();
}
}
自定义拦截器
package net.chrone.merchant.service.interceptor;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.chrone.merchant.service.model.MerLoginUser;
import net.chrone.merchant.service.model.MerMenu;
import net.chrone.mercha
105c4
nt.service.util.ClientSysEvnUtil;
import net.chrone.merchant.service.util.Constants;
import net.chrone.merchant.service.util.LogWriter;
import net.chrone.merchant.service.util.MD5;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.chrone.util.StringUtils;
public class MyInterceptor implements HandlerInterceptor {
private static final Logger logger = Logger.getLogger(MyInterceptor.class);
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
String url=request.getServletPath();
String ip = ClientSysEvnUtil.getIpAddr(request);
String agent = request.getHeader("user-agent");
if (url.startsWith("/public/")||url.equals("/")||url.equals("/secret/random")||url.equals("")){
request.setAttribute("head", "index");
//输出访问日志
try {
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志]--IP:" + ip + "; 来源:" + request.getHeader("referer") + "; 浏览器:" + request.getHeader("user-agent") + "; 访问路径:" + url);
}
} catch (Exception e) {
// 防御容错
}
return true;
}else{
if(request.getSession().getAttribute(Constants.LOGIN_SESSION)==null){
if(url.equals("/mchntCenter")){
request.setAttribute("out_tp", "1");
}
try{
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志-登录超时]--IP:" + ip + "; 来源:" + request.getHeader("referer") + "; 浏览器:" + request.getHeader("user-agent") + "; 访问路径:" + url);
}
}catch(Exception e){
}
request.getRequestDispatcher("/sessionTimeOut.jsp").forward(request, response);
return false;
}
MerLoginUser userInf = (MerLoginUser) request.getSession().getAttribute(Constants.LOGIN_SESSION);
//输出访问日志
try {
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志]--IP:" + ip + "; 商户:" + userInf.getTaccountid() + "; 操作员:" + userInf.getId() + "; 访问路径:" + url);
}
} catch (Exception e) {
// 防御容错
}
String flag = MD5.md5(ip+agent);
if(!flag.equals(Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId())) && null != Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId())){
request.getSession().removeAttribute(Constants.LOGIN_SESSION);
request.getSession().removeAttribute(Constants.LOGIN_MENU);
request.setAttribute("out_tp", "3");
request.getRequestDispatcher("/sessionTimeOut.jsp").forward(request, response);
try{
if(!url.startsWith("/images") && !url.startsWith("/css") && !url.startsWith("/scripts")){
logger.info("[操作日志-异地登录]--IP:" + ip + "; 商户:" + userInf.getTaccountid() + "; 操作员:" + userInf.getId() + "; 访问路径:" + url + "; flag-n:" + flag + "; flag-s:" + Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId()) );
}
}catch(Exception e){
}
return false;
}
if(null == Constants.LOGIN_SESSION_ID_MAP.get(userInf.getId())){
Constants.LOGIN_SESSION_ID_MAP.put(userInf.getId(),flag);
}
if(url.startsWith("/mchntCenter")){
request.getSession().removeAttribute("leftfid");
request.getSession().removeAttribute("leftid");
}
if(StringUtils.isNotEmpty(request.getParameter("leftfid"))){
request.getSession().setAttribute("leftfid", request.getParameter("leftfid"));
}
if(StringUtils.isNotEmpty(request.getParameter("leftid"))){
request.getSession().setAttribute("leftid", request.getParameter("leftid"));
}
if(defaultAuth(url)){//默认权限
return true;
}
if(!urlIsAuth(request, url)){
request.getRequestDispatcher("/authError.jsp").forward(request, response);
return false;
}
return true;
}
}
/**
*默认权限
* @return
*/
public boolean defaultAuth(String url){
List<String> list = new ArrayList<String>();
list.add("/home");
list.add("/secret/random");
list.add("/mchntCenter");
list.add("/loginOut");
list.add("/error");
list.add("/public/loginWithMobileSecurityCode");//手机验证
list.add("/user/checkPwd");//检查密码
list.add("/user/checkPayPwd");//检查支付密码
list.add("/user/sendEmail");//发送邮件验证
list.add("/user/checkCode");//检查验证码
list.add("/user/checkUserId");//检查用户名
list.add("/user/updPwdSucc");//密码修改成功跳转
list.add("/user/sendSmsCode");//发送验证码
list.add("/user/hideKey");//隐藏密钥
list.add("/cash/cash");//提现
list.add("/cash/cashConfirm");//提现
list.add("/cash/cashSub");//提现
list.add("/trans/transAccount");//转账
list.add("/trans/verifyInAccount");//转账
list.add("/trans/transAccountConfirm");//转账
list.add("/trans/transAccountSub");//转账
list.add("/trans/verifyPayPwd");//转账
list.add("/recharge/index");//充值
list.add("/recharge/rechargeConfirm");//充值
list.add("/recharge/rechargeSub");//充值
list.add("/user/forGetPayPwd");//忘记支付密码
list.add("/user/newPayPwd");//忘记支付密码
list.add("/user/payPwd");//支付密码
list.add("/user/loginPwd");//登录密码
list.add("/user/forGetPayPwd");//忘记支付密码
list.add("/user/newPayPwd");//忘记支付密码
list.add("/user/payPwd");//支付密码
list.add("/user/loginPwd");//登录密码
list.add("/user/updLoginPwd");//登录密码保存
list.add("/user/updNewPayPwd");//忘记支付密码保存
list.add("/user/updPayPwd");//修改支付密码保存
list.add("/mernotice/updateReadCount");//更新阅读商户通知信息
for(String l:list){
if(url.startsWith(l)){
return true;
}
}
return false;
}
/**
* url是否有访问权限
* @return
*/
public boolean urlIsAuth(HttpServletRequest request,String url){
List<MerMenu> menuInfList = (List<MerMenu>) request.getSession().getAttribute(Constants.LOGIN_MENU);
for(MerMenu menuInf:menuInfList){
try {
if(StringUtils.isNotEmpty(menuInf.getUrl().trim())&&url.startsWith(menuInf.getUrl())){
return true;
}
} catch (Exception e) {
LogWriter.error("异常菜单:"+menuInf);
e.printStackTrace();
}
}
return false;
}
}
自定义url过滤器
package net.chrone.merchant.service.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import net.chrone.merchant.service.util.ClientSysEvnUtil;
import net.chrone.merchant.service.util.LogWriter;
public class CheckURLFilter implements Filter {
@Override
public void init(FilterConfig filterconfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletrequest,
ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletrequest;
HttpServletResponse res = (HttpServletResponse) servletresponse;
String urlString = req.getRequestURI();
if(servletrequest.getCharacterEncoding() == null || !servletrequest.getCharacterEncoding().toUpperCase().equals("UTF-8")){
servletrequest.setCharacterEncoding("UTF-8");
}
LogWriter.info("RemoteAddr:"+ClientSysEvnUtil.getIpAddr(req)+" 开始执行:"+urlString);
long bt = System.currentTimeMillis();
Map<String, String[]> map = servletrequest.getParameterMap();
for(String m:map.keySet()){
if(m.indexOf("password") != -1 || m.indexOf("Password") != -1)
continue;
String[] v = (String[]) map.get(m);
LogWriter.info(m+":"+v[0]);
}
filterchain.doFilter(servletrequest, servletresponse);
long et = System.currentTimeMillis();
LogWriter.debug(urlString+"执行完毕! 耗时:"+(et-bt));
}
@Override
public void destroy() {
}
}
自定义缓存
package net.chrone.merchant.service.config;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* 缓存,超时时间单位:分钟
*
* @author zhangzw 2015-05-19
*
*/
public class Cache<K, V> {
// 声明缓存
private LoadingCache<K, V> graphs;
/**
*
* @param timeOut
* 分钟
*/
public Cache(long timeOut) {
Initialize(timeOut);
}
/**
* 初始化缓存容器
*/
private void Initialize(long timeOut) {
if (timeOut > 0) {
graphs = CacheBuilder.newBuilder()
.expireAfterWrite(timeOut, TimeUnit.MINUTES) //
.build(new CacheLoader<K, V>() {
public V load(K key) {
// 取消默认的自动缓存添加器
return null;
}
});
} else {
graphs = CacheBuilder.newBuilder().build(new CacheLoader<K, V>() {
public V load(K key) {
// 取消默认的自动缓存添加器
return null;
}
});
}
}
/**
* 获取缓存信息
*
* @param key
* @return
*/
@SuppressWarnings("finally")
public V get(K key) {
V v = null;
try {
v = graphs.get(key);
} catch (ExecutionException e) {
} finally {
return v;
}
}
/**
* 设置缓存信息
*
* @param key
* @param value
*/
public void put(K key, V value) {
if (null != key && null != value)
graphs.put(key, value);
}
/**
* 删除一个缓存
*
* @param key
*/
public void remove(String key) {
graphs.invalidate(key);
}
/**
* 清空全部缓存
*/
public void clearAll() {
graphs.invalidateAll();
}
}
springboot启动main方法
package net.chrone.merchant.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//@ServletComponentScan
@SpringBootApplication
@EnableTransactionManagement
@ImportResource({"classpath:applicationContext.xml"})
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Springboot 常用注解
@SpringBootApplication:
包含@Configuration、@EnableAutoConfiguration、@ComponentScan
通常用在主类上。
@Repository:
用于标注数据访问组件,即DAO组件。
@Service:
用于标注业务层组件。
@RestController:
用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody。
@ResponseBody:
表示该方法的返回结果直接写入HTTP response body中
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
@Component:
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@ComponentScan:
组件扫描。个人理解相当于<context:component-scan>,如果扫描到有@Component @Controller @Service等这些注解的类,则把这些类注册为bean。
@Configuration:
指出该类是 Bean 配置的信息源,相当于XML中的<beans></beans>,一般加在主类上。
@Bean:
相当于XML中的<bean></bean>,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
@EnableAutoConfiguration:
让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,一般加在主类上。
@AutoWired:
byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
当加上(required=false)时,就算找不到bean也不报错。
@Qualifier:
当有多个同一类型的Bean时,可以用@Qualifier("name")来指定。与@Autowired配合使用
@Resource(name="name",type="type"):
没有括号内内容的话,默认byName。与@Autowired干类似的事。
@RequestMapping:
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
该注解有六个属性:
params:指定request中必须包含某些参数值时,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
value:指定请求的实际地址,指定的地址可以是URI Template 模式
method:指定请求的method类型, GET、POST、PUT、DELETE等
consumes:指定处理请求的提交内容类型(Content-Type),如application/json,text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
@RequestMapping(value="/testRequestMapping",method= RequestMethod.POST )
案例:
@Controller
@RequestMapping("/user")
public class UserController {
private Logger logger = LoggerFactory.getLogger(LoginController.class);
@Autowired
private MerLoginUserService merLoginUserService;
@RequestMapping("user_list")
public String list(HttpServletRequest request,String start,Model model){
return "user/user_list";
}
}
@RequestParam:
用在方法的参数前面。
@RequestParam String a 相当于String a =request.getParameter("a")。
@PathVariable:
路径变量。参数与大括号里的名字一样要相同。
RequestMapping("user/get/mac/{macAddress}")
public String getByMacAddress(@PathVariable String macAddress){
�
//do something;
}
}
@Profiles
Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。
任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。
@Configuration
@
@Profile("prod")
public class ProductionConfiguration {
// ...
}
}
比如:@Profile("product")
生产环境下加载
@Profile("dev")
开发环境下加载
@Profile("test")
测试环境下加载
@ConfigurationProperties
Spring Boot将尝试校验外部的配置,默认使用JSR-303(如果在classpath路径中)。
你可以轻松的为你的@ConfigurationProperties类添加JSR-303 javax.validation约束注解:
@Component
@
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
@
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
}
全局异常处理
@ControllerAdvice:
包含@Component。可以被扫描到。
统一处理异常。
@ExceptionHandler(Exception.class):
用在方法上面表示遇到这个异常就执行以下方法。
================================================================================================
spring-boot默认提供内嵌的tomcat,所以打包直接生成jar包,用java -jar命令就可以启动。但是,有时候我们更希望一个tomcat来管理多个项目,这种情况下就需要项目是war格式的包而不是jar格式的包。spring-boot同样提供了解决方案,只需要简单的几步更改就可以了,这里提供maven项目的解决方法:
1.将springboot项目的启动类Application.java继承SpringBootServletInitializer并重写configure方法
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{ return application.sources(Application.class); }
public static void main(String[] args) throws Exception
{SpringApplication.run(Application.class, args); }
}
2.在pom.xml文件中,project下面增加package标签
<packaging>war</packaging>
3.还是在pom.xml文件中,dependencies下面添加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>
或者这种方法:
相关文章推荐
- Spring-Boot快速搭建web项目详细总结
- SpringBoot+Shiro+MyBatisPlus搭建前后端分离的多模块项目
- IDEA 快速搭建springboot项目,返回HTML首页
- @Springboot搭建项目controller层接收json格式的对象失败
- 【项目搭建】使用spring-boot进行REST风格的微服务开发入门
- 搭建spring boot集成mybatis项目入门
- Spring Cloud搭建微服务架构----使用Spring boot开发web项目
- 如何使用eclipse搭建SpringBoot项目
- 扩展:通过SPRING INITIALIZR工具产生基础项目搭建SpringBoot+maven项目
- java 搭建基于springboot的ssh(spring + springmvc + hibernate)的gradle项目(基础篇)
- 使用eclipse搭建springboot项目
- Spring Boot / Spring MVC 入门实践 (一) :环境搭建与第一个项目
- 搭建一个spring-boot项目 3
- spring boot项目搭建 发布 打包弯路全纪录
- IDEA上面搭建一个SpringBoot的web-mvc项目
- 快速搭建一个简单的springboot项目
- 使用SpringBoot搭建小型项目,集成mybatis,redis,swagger2,并部署在外部容器中。
- [置顶] 使用IDEA搭建Spring Boot入门项目
- 快速搭建Spring Boot项目
- springboot+Rabit实战三:(springboot+rabbit 项目搭建)