Spark开发简单示例

一个Spark的简单示例

涉及的内容有:
        设置端口、设置线程池、设置静态资源目录、拦截器、捕获异常、模板的使用等一些简单展示
主要流程为:
        用户没有登录就不能访问登录以外的页面(可直接访问的静态资源除外),登录后可以访问所有的用户列表(并没有做其他功能)
 
关于环境的搭建可以参考:“Spark开发环境搭建
 
所有的java代码如下
 
UserService.java(并没有使用数据库等,直接写死的数据)
package me.ooi.testSpark;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * <p>用户service</p>
 * <p>Author: jun.zhao</p>
 * <p>Date: 2016年10月24日</p>
 */
public class UserService {
    
    //这里就用一个map保存一下用户信息了
    public Map<String, User> users = new HashMap<>() ; 
    
    public UserService(){
        users.put("1", new User("1","小明",17)) ; 
        users.put("2", new User("2","小红",18)) ; 
        users.put("3", new User("3","小刚",19)) ; 
    }
    
    //根据用户名查询用户
    public User getUserByName(String name){
        Optional<User> user = users.values().stream().filter(u->u.getName().equals(name)).findFirst() ; 
        if( user.isPresent() ){
            return user.get() ; 
        }else {
            return null ; 
        }
    }
    
    //获取所有的用户
    public List<User> findUser(){
        return users.values().stream().collect(Collectors.toList()) ;  
    }
}

User.java

package me.ooi.testSpark;
/**
 * <p>用户</p>
 * <p>Author: jun.zhao</p>
 * <p>Date: 2016年10月24日</p>
 */
public class User {
    
    private String id ; 
    private String name ; 
    private Integer age ;
    public User() {
        super();
    }
    public User(String id, String name, Integer age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    } 
    
}

UserMgr.java(这里是示例的主要内容,一些需要注意的都写了注释)

package me.ooi.testSpark;
import static spark.Spark.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
import spark.ModelAndView;
import spark.Session;
import spark.template.freemarker.FreeMarkerEngine;
/**
 * <p>一个用户管理的例子</p>
 * <p>Author: jun.zhao</p>
 * <p>Date: 2016年10月24日</p>
 */
public class UserMgr {
    
    public static final Logger LOG = LoggerFactory.getLogger(HelloSpark.class) ; 
    
    private static final Configuration FREEMARKER_CFG = new Configuration() ;
    
    public static final String SESSION_USER = "session_user" ; 
    
    private UserService userService = new UserService() ; 
    
    static{
        String templateDir = getWebContentDir()+"template" ; 
        try {
            if( LOG.isInfoEnabled() ){
                LOG.info("模板目录为:"+templateDir) ; 
            }
            FREEMARKER_CFG.setDirectoryForTemplateLoading(new File(templateDir));
        } catch (IOException e) {
            e.printStackTrace();
        }
        FREEMARKER_CFG.setDefaultEncoding("UTF-8");
        FREEMARKER_CFG.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
    }
    
    
    public void init(){
        configServer();
        configStaticFile();
        configFilter();
        configRequest();
    }
    
    //设置服务器的一些参数
    public void configServer(){
        //设置端口
        //This has to be done before using routes and filters
        port(8080) ; 
        
        //设置线程池
        int maxThreads = 1000;
        int minThreads = 10;
        int timeOutMillis = 30*1000;
        threadPool(maxThreads, minThreads, timeOutMillis);
    }
    
    public static String getWebContentDir(){
        //webcontent下的文件
        String root = System.getProperty("user.dir") ; 
        String webContentDir = root + File.separator + "WebContent" + File.separator ; 
        return webContentDir ; 
    }
    
    //静态文件设置
    public void configStaticFile(){
        //测试html等静态资源,这些资源可以直接访问
        //classpath下文件
        staticFiles.location("/publicres") ; 
        //webcontent下的文件
        String publicDir = getWebContentDir() + "public" ;  ; 
        if( LOG.isInfoEnabled() ){
            LOG.info("public目录为:"+publicDir) ; 
        }
        staticFiles.externalLocation(publicDir) ; 
    }
    
    //用户权限拦截器
    public void configFilter(){
        //不需要登录的地址
        List<String> dontNeedLoginPathList = new ArrayList<>() ; 
        dontNeedLoginPathList.add("/login") ; 
        dontNeedLoginPathList.add("/login.html") ; 
        
        //假设session中有用户,则可以访问所有内容,否则提示登录
        before((request, response) -> {
            if( LOG.isInfoEnabled() ){
                LOG.info("拦截器拦截请求:"+request.pathInfo()) ; 
            }
            if( !dontNeedLoginPathList.contains(request.pathInfo()) ){
                Session session = request.session() ; 
                User u = session.attribute(SESSION_USER) ; 
                if( u == null ){
                    response.redirect("/login.html") ; 
                    //终止请求继续走下去(不终止的话拦截器就没有意义了)
                    halt() ;
                }
            }
        }) ; 
    }
    
    //所有的流程
    public void configRequest(){
        
        //异常处理,不处理异常就不知道报了什么异常
        exception(RuntimeException.class, (exception, request, response) -> {
            //...
            exception.printStackTrace() ;
            halt(500) ; 
        });
        
        exception(Exception.class, (exception, request, response) -> {
            //...
            exception.printStackTrace() ;
            halt(500) ; 
        });
        
        //登录
        post("/login", (request, response) -> {
            if( LOG.isInfoEnabled() ){
                LOG.info("进入请求:"+request.pathInfo()) ; 
            }
            //这里就用name来验证用户了
            String name = request.queryParams("name") ; 
            User u = userService.getUserByName(name) ; 
            if( u == null ){
                response.redirect("/login.html") ; 
            }else {
                request.session().attribute(SESSION_USER, u) ; 
                response.redirect("/user/list");
            }
            return null ; 
        });
        
        //登出
        get("/logout", (request, response)->{
            if( LOG.isInfoEnabled() ){
                LOG.info("进入请求:"+request.pathInfo()) ; 
            }
            request.session().removeAttribute(SESSION_USER) ; 
            response.redirect("/login.html") ; 
            return null ; 
        }) ;
        
        //用户列表
        get("/user/list", (request, response)->{
            if( LOG.isInfoEnabled() ){
                LOG.info("进入请求:"+request.pathInfo()) ; 
            }
            Map<String, Object> data = new HashMap<>() ; 
            List<User> userList = userService.findUser() ; 
            data.put("userList", userList) ; 
            return new ModelAndView(data, "user/list.html") ; 
        }, new FreeMarkerEngine(FREEMARKER_CFG)) ; 
        
    }
}

HelloSpark.java(Main方法)

package me.ooi.testSpark;
public class HelloSpark {
    public static void main(String[] args) {
        new UserMgr().init();
    }
}

在pom.xml中加入spark的freemarker插件

<dependency>
            <groupId>com.sparkjava</groupId>
            <artifactId>spark-template-freemarker</artifactId>
            <version>2.3</version>
        </dependency>

 

需要新建的目录如下
1,在资源目录“src/main/resources”下新建“publicres(注意:文件名不能为java package不能使用的名字)”文件夹作为可以直接访问的文件
    如:文件“publicres/test.html”,则可以直接通过“http://locahost:8080/test.html”的方式访问
2,在WebContent下分别新建“public(存放一些可以直接访问的文件)”和“template(存放一些模板)”文件夹
 
这个例子需要的页面如下
1,WebContent/public/login.html(可直接访问到)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="name">
</form>
</body>
</html>

2,WebContent/template/user/list.html(作为模板使用,模板引擎为freemarker)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<table>
    <thead>
        <tr>
            <th>id</th>
            <th>名字</th>
            <th>年龄</th>
        </tr>
    </thead>
    <tbody>
        <#list userList as u>
            <tr>
                <td>${u.id}</td>
                <td>${u.name}</td>
                <td>${u.age}</td>
            </tr>    
        </#list>
    </tbody>
</table>
</body>
</html>
发布
导出为jar包后,将WebContent整个拷贝("WEB-INF"和"META-INF"两个目录不需要拷贝)到和jar包同一目录下(如下图所示),使用java -jar命令启动即可,这样就可以动态修改WebContent里面的页面和模板了。

 

posted @ 2016-10-25 16:49  行-云  阅读(10046)  评论(0编辑  收藏  举报