portaldacalheta.pt
  • หลัก
  • การจัดการโครงการ
  • การเพิ่มขึ้นของระยะไกล
  • การบริหารโครงการ
  • เครื่องมือและบทช่วยสอน
ส่วนหน้าของเว็บ

การสร้างแอปพลิเคชันเว็บสมัยใหม่ด้วย AngularJS และ Play Framework



การเลือกเครื่องมือที่เหมาะสมสำหรับวัตถุประสงค์ที่ถูกต้องนั้นไปได้ไกลโดยเฉพาะอย่างยิ่งเมื่อต้องสร้างเว็บแอปพลิเคชันสมัยใหม่ พวกเราหลายคนคุ้นเคยกับ AngularJS และการพัฒนาส่วนหน้าเว็บแอปพลิเคชันที่มีประสิทธิภาพนั้นง่ายเพียงใด แม้ว่าหลายคนจะโต้แย้งการใช้เว็บเฟรมเวิร์กยอดนิยมนี้ แต่ก็มีข้อเสนอมากมายและสามารถเป็นได้ ทางเลือกที่เหมาะสม สำหรับความต้องการที่หลากหลาย ในทางกลับกันส่วนประกอบที่คุณใช้ในส่วนหลังจะกำหนดประสิทธิภาพของเว็บแอปพลิเคชันเป็นอย่างมากเนื่องจากส่วนประกอบเหล่านี้มีอิทธิพลต่อประสบการณ์ของผู้ใช้โดยรวม เล่น เป็นเว็บเฟรมเวิร์กความเร็วสูงสำหรับ Java และ Scala มันขึ้นอยู่กับสถาปัตยกรรมน้ำหนักเบาไร้สถานะเป็นมิตรกับเว็บและเป็นไปตามรูปแบบ MVC และหลักการที่คล้ายกับ Rails และ Django

เว็บแอปพลิเคชันที่มี angularjs และ play framework



ในบทความนี้เราจะมาดูวิธีที่เราสามารถใช้ AngularJS และ Play เพื่อสร้างแอปพลิเคชันบล็อกง่ายๆด้วยกลไกการตรวจสอบสิทธิ์พื้นฐานและความสามารถในการโพสต์และความคิดเห็น การพัฒนา AngularJS , กับบางอย่าง Twitter Bootstrap สารพัดจะช่วยให้เราสามารถขับเคลื่อนประสบการณ์การใช้งานแอปพลิเคชันแบบหน้าเดียวบนแบ็คเอนด์ REST API ที่ใช้ Play



แอปพลิเคชันบนเว็บ - เริ่มต้นใช้งาน

AngularJS Application Skeleton

แอพ AngularJS และ Play จะอยู่ในไดเรกทอรีไคลเอนต์และเซิร์ฟเวอร์ตามนั้น ในตอนนี้เราจะสร้างไดเร็กทอรี 'ไคลเอนต์'



mkdir -p blogapp/client

ในการสร้างโครงกระดูกแอปพลิเคชัน AngularJS เราจะใช้ Yeoman ซึ่งเป็นเครื่องมือนั่งร้านที่น่าทึ่ง การติดตั้ง Yeoman เป็นเรื่องง่าย . การใช้มันเพื่อนั่งร้านแอปพลิเคชั่น AngularJS โครงกระดูกที่เรียบง่ายอาจง่ายกว่า:

cd blogapp/client yo angular

การรันคำสั่งที่สองจะตามมาด้วยตัวเลือกสองสามตัวที่คุณต้องเลือก สำหรับโครงการนี้เราไม่จำเป็นต้องมี“ Sass (with Compass)” เราจะต้องใช้ Boostrap พร้อมกับปลั๊กอิน AngularJS ต่อไปนี้:



  • angular-animate.js
  • Angular-cookies.js
  • เชิงมุมทรัพยากร js
  • เชิงมุมเส้นทาง js
  • angular-sanitize.js
  • เชิงมุมสัมผัส js

ณ จุดนี้เมื่อคุณเสร็จสิ้นการเลือกของคุณคุณจะเริ่มเห็นเอาต์พุต NPM และ Bower บนเทอร์มินัลของคุณ เมื่อการดาวน์โหลดเสร็จสมบูรณ์และติดตั้งแพ็กเกจแล้วคุณจะมีโครงกระดูกแอปพลิเคชัน AngularJS พร้อมใช้งาน

เล่น Framework Application Skeleton

วิธีการอย่างเป็นทางการในการสร้างแอปพลิเคชัน Play ใหม่เกี่ยวข้องกับการใช้เครื่องมือ typesafe Activator ก่อนที่จะใช้งานได้คุณต้องดาวน์โหลดและติดตั้งลงในคอมพิวเตอร์ของคุณ หากคุณใช้ Mac OS และใช้ Homebrew คุณสามารถติดตั้งเครื่องมือนี้ด้วยคำสั่งบรรทัดเดียว:



brew install typesafe-activator

การสร้างแอปพลิเคชัน Play จากบรรทัดคำสั่งนั้นง่ายมาก:

cd blogapp/ activator new server play-java cd server/

การนำเข้าสู่ IDE

ในการนำเข้าแอปพลิเคชันใน IDE เช่น Eclipse หรือ IntelliJ คุณต้อง 'eclipsify' หรือ 'ทำให้เป็นอุดมคติ' แอปพลิเคชันของคุณ โดยเรียกใช้คำสั่งต่อไปนี้:



activator

เมื่อคุณเห็นพรอมต์ใหม่ให้พิมพ์“ eclipse” หรือ“ idea” แล้วกด Enter เพื่อเตรียมรหัสแอปพลิเคชันสำหรับ Eclipse หรือ IntelliJ ตามลำดับ

เพื่อความกระชับเราจะกล่าวถึงขั้นตอนการนำเข้าโปรเจ็กต์ไปยัง IntelliJ ในบทความนี้เท่านั้น กระบวนการอิมพอร์ตไปยัง Eclipse ควรจะง่ายพอ ๆ กัน ในการนำเข้าโปรเจ็กต์ไปยัง IntelliJ ให้เริ่มต้นด้วยการเปิดใช้งานตัวเลือก“ โปรเจ็กต์จากแหล่งที่มาที่มีอยู่…” ที่อยู่ใน“ ไฟล์ -> ใหม่” จากนั้นเลือกไฟล์ build.sbt ของคุณแล้วคลิก“ ตกลง” เมื่อคลิก“ ตกลง” อีกครั้งในกล่องโต้ตอบถัดไป IntelliJ ควรเริ่มนำเข้าแอปพลิเคชัน Play ของคุณเป็นโครงการ SBT



typesafe Activator ยังมาพร้อมกับอินเทอร์เฟซผู้ใช้แบบกราฟิกซึ่งคุณสามารถใช้เพื่อ สร้างรหัสแอปพลิเคชันโครงกระดูกนี้ .

ตอนนี้เราได้นำเข้าแอปพลิเคชัน Play ของเราไปยัง IntelliJ แล้วเราควรนำเข้าแอปพลิเคชัน AngularJS ของเราไปยังพื้นที่ทำงานด้วย เราสามารถนำเข้าเป็นโครงการแยกต่างหากหรือเป็นโมดูลไปยังโครงการที่มีอยู่ซึ่งแอปพลิเคชัน Play อาศัยอยู่



ที่นี่เราจะนำเข้าแอปพลิเคชัน Angular เป็นโมดูล ภายใต้เมนู“ ไฟล์” เราจะเลือกตัวเลือก“ ใหม่ -> โมดูลจากแหล่งที่มาที่มีอยู่…” จากกล่องโต้ตอบเราจะเลือกไดเร็กทอรี 'ไคลเอนต์' และคลิกที่ 'ตกลง' ในสองหน้าจอถัดไปให้คลิกที่“ ถัดไป” และ“ เสร็จสิ้น” ตามลำดับ

วางไข่เซิร์ฟเวอร์ท้องถิ่น

ณ จุดนี้ควรเริ่มแอปพลิเคชัน AngularJS เป็นงาน Grunt จาก IDE ได้ ขยายโฟลเดอร์ไคลเอนต์ของคุณแล้วคลิกขวาที่ Gruntfile.js ในเมนูป๊อปอัพให้เลือก“ Show Grunt Tasks” แผงที่มีข้อความ 'Grunt' จะปรากฏขึ้นพร้อมรายการงาน:

วางไข่เซิร์ฟเวอร์ท้องถิ่น

ในการเริ่มให้บริการแอปพลิเคชันให้ดับเบิลคลิกที่“ ให้บริการ” สิ่งนี้ควรเปิดเว็บเบราว์เซอร์เริ่มต้นของคุณทันทีและชี้ไปที่ที่อยู่ localhost คุณควรเห็นหน้า AngularJS ที่มีรูปทรงที่มีโลโก้ของ Yeoman อยู่

ต่อไปเราต้องเปิดแอปพลิเคชันเซิร์ฟเวอร์ส่วนหลังของเรา ก่อนที่เราจะดำเนินการต่อเราต้องแก้ไขปัญหาสองสามประการ:

  1. ตามค่าเริ่มต้นทั้งแอปพลิเคชัน AngularJS (บูตโดย Yeoman) และแอปพลิเคชัน Play จะพยายามทำงานบนพอร์ต 9000
  2. ในการใช้งานจริงแอปพลิเคชันทั้งสองจะทำงานภายใต้โดเมนเดียวและเราอาจใช้ Nginx เพื่อกำหนดเส้นทางตามคำขอ แต่ในโหมดการพัฒนาเมื่อเราเปลี่ยนหมายเลขพอร์ตของหนึ่งในแอปพลิเคชันเหล่านี้เว็บเบราว์เซอร์จะปฏิบัติต่อแอปพลิเคชันเหล่านี้ราวกับว่าทำงานบนโดเมนที่แตกต่างกัน

ในการแก้ไขปัญหาทั้งสองนี้สิ่งที่เราต้องทำคือใช้ Grunt proxy เพื่อให้คำขอ AJAX ทั้งหมดไปยังแอปพลิเคชัน Play เป็นพร็อกซี ด้วยเหตุนี้โดยพื้นฐานแล้วแอ็พพลิเคชันเซิร์ฟเวอร์ทั้งสองนี้จะพร้อมใช้งานที่หมายเลขพอร์ตเดียวกัน

ก่อนอื่นให้เราเปลี่ยนหมายเลขพอร์ตของแอปพลิเคชันเซิร์ฟเวอร์ Play เป็น 9090 ในการดำเนินการนี้ให้เปิดหน้าต่าง“ Run / Debug Configurations” โดยคลิกที่“ Run -> Edit Configurations” จากนั้นเปลี่ยนหมายเลขพอร์ตในช่อง 'URL To Open' คลิกที่“ ตกลง” เพื่ออนุมัติการเปลี่ยนแปลงนี้และปิดหน้าต่าง การคลิกที่ปุ่ม“ เรียกใช้” ควรเริ่มกระบวนการแก้ไขการอ้างอิง - บันทึกของกระบวนการนี้จะเริ่มปรากฏขึ้น

วางไข่เซิร์ฟเวอร์ท้องถิ่น

เมื่อเสร็จแล้วคุณสามารถไปที่ http: // localhost: 9090 บนเว็บเบราว์เซอร์ของคุณและในไม่กี่วินาทีคุณจะสามารถเห็นแอปพลิเคชัน Play ของคุณ ในการกำหนดค่า Grunt proxy ก่อนอื่นเราต้องติดตั้งแพ็คเกจ Node.js ขนาดเล็กโดยใช้ NPM:

cd blogapp/client npm install grunt-connect-proxy --save-dev

ต่อไปเราต้องปรับแต่ง Gruntfile.js ของเรา ในไฟล์นั้นให้ค้นหางาน 'เชื่อมต่อ' และแทรกคีย์ / ค่า 'พร็อกซี' ไว้ด้านหลัง:

proxies: [ { context: '/app', // the context of the data service host: 'localhost', // wherever the data service is running port: 9090, // the port that the data service is running on changeOrigin: true } ],

ตอนนี้ Grunt จะพร็อกซีคำขอทั้งหมดไปยัง“ / app / *” ไปยังแอปพลิเคชัน Back-end Play วิธีนี้จะช่วยให้เราไม่ต้องอยู่ในรายการที่อนุญาตพิเศษทุกครั้งที่โทรไปยังส่วนหลัง นอกจากนี้เรายังต้องปรับแต่งพฤติกรรม livereload ของเรา:

livereload: { options: { open: true, middleware: function (connect) { var middlewares = []; // Setup the proxy middlewares.push(require('grunt-connect-proxy/lib/utils').proxyRequest); // Serve static files middlewares.push(connect.static('.tmp')); middlewares.push(connect().use( '/bower_components', connect.static('./bower_components') )); middlewares.push(connect().use( '/app/styles', connect.static('./app/styles') )); middlewares.push(connect.static(appConfig.app)); return middlewares; } } },

ในที่สุดเราจำเป็นต้องเพิ่มการพึ่งพาใหม่ '' configureProxies: server 'ให้กับงาน' ให้บริการ ':

grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'wiredep', 'concurrent:server', 'autoprefixer:server', 'configureProxies:server', 'connect:livereload', 'watch' ]); });

เมื่อรีสตาร์ท Grunt คุณควรสังเกตบรรทัดต่อไปนี้ในบันทึกของคุณที่ระบุว่าพร็อกซีกำลังทำงาน:

Running 'autoprefixer:server' (autoprefixer) task File .tmp/styles/main.css created. Running 'configureProxies:server' (configureProxies) task Running 'connect:livereload' (connect) task Started connect web server on http://localhost:9000

การสร้างแบบฟอร์มลงทะเบียน

เราจะเริ่มต้นด้วยการสร้างแบบฟอร์มลงทะเบียนสำหรับแอปพลิเคชันบล็อกของเรา นอกจากนี้ยังช่วยให้เราตรวจสอบได้ว่าทุกอย่างทำงานตามที่ควร เราสามารถใช้ Yeoman เพื่อสร้างตัวควบคุมการสมัครและดูใน AngularJS:

yo angular:controller signup yo angular:view signup

ต่อไปเราควรอัปเดตการกำหนดเส้นทางของแอปพลิเคชันของเราเพื่ออ้างอิงมุมมองที่สร้างขึ้นใหม่นี้และลบตัวควบคุมและมุมมอง 'เกี่ยวกับ' ที่สร้างขึ้นโดยอัตโนมัติซ้ำซ้อน จากภายในไฟล์“ app / scripts / app.js” ให้ลบการอ้างอิงถึง“ app / scripts / controllers / about.js” และ“ app / views / about.html” ออกโดยให้:

.config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }) .when('/signup', { templateUrl: 'views/signup.html', controller: 'SignupCtrl' }) .otherwise({ redirectTo: '/' });

ในทำนองเดียวกันให้อัปเดตไฟล์“ app / index.html” เพื่อลบลิงก์ที่ซ้ำซ้อนและเพิ่มลิงก์ไปยังหน้าลงชื่อสมัครใช้:

  • Home
  • Signup

นอกจากนี้ให้ลบแท็กสคริปต์สำหรับ“ about.js”:

Email Password Sign up!

จากนั้นเพิ่มแบบฟอร์มในไฟล์“ signup.html” ของเรา:

angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log) { $scope.signup = function() { var payload = { email : $scope.email, password : $scope.password }; $http.post('app/signup', payload) .success(function(data) { $log.debug(data); }); }; });

เราจำเป็นต้องทำให้แบบฟอร์มถูกประมวลผลโดยตัวควบคุมเชิงมุม เป็นที่น่าสังเกตว่าเราไม่จำเป็นต้องเพิ่มแอตทริบิวต์ 'ng-controller' โดยเฉพาะในมุมมองของเราเนื่องจากตรรกะการกำหนดเส้นทางของเราใน 'app.js' จะทำให้ตัวควบคุมทำงานโดยอัตโนมัติก่อนที่มุมมองของเราจะโหลด สิ่งที่เราต้องทำเพื่อวางสายแบบฟอร์มนี้คือมีฟังก์ชัน 'สมัครใช้งาน' ที่เหมาะสมซึ่งกำหนดไว้ใน $ scope ควรทำในไฟล์“ signup.js”:

public static Result signup() { return ok('Success!'); }

ตอนนี้ให้เราเปิดคอนโซลนักพัฒนาซอฟต์แวร์ Chrome เปลี่ยนไปใช้แท็บ 'เครือข่าย' แล้วลองส่งแบบฟอร์มการสมัคร

ตัวอย่างแบบฟอร์มสมัครสมาชิก Angular Play

เราจะเห็นว่า Play back-end ตอบกลับโดยธรรมชาติพร้อมกับหน้าแสดงข้อผิดพลาด 'ไม่พบการดำเนินการ' คาดว่าจะยังไม่ได้ดำเนินการ แต่ความหมายก็คือการตั้งค่าพร็อกซี Grunt ของเราทำงานได้อย่างถูกต้อง!

ต่อไปเราจะเพิ่ม“ การดำเนินการ” ซึ่งโดยพื้นฐานแล้วเป็นวิธีการในตัวควบคุมแอปพลิเคชัน Play ในคลาส 'แอปพลิเคชัน' ในแพ็กเกจ 'แอป / คอนโทรลเลอร์' ให้เพิ่มวิธีการใหม่ 'สมัครใช้งาน':

POST /app/signup controllers.Application.signup

ตอนนี้เปิดไฟล์“ conf / route” และเพิ่มบรรทัดต่อไปนี้:

db.default.driver=org.h2.Driver db.default.url='jdbc:h2:mem:play' db.default.user=sa db.default.password='' ... ebean.default='models.*'

สุดท้ายเรากลับไปที่เว็บเบราว์เซอร์ http: // localhost: 9000 / # / signup การคลิกปุ่ม 'ส่ง' ในครั้งนี้ควรให้สิ่งที่แตกต่างออกไป:

ตัวอย่างแบบฟอร์มสมัครสมาชิก Angular Play ในเบราว์เซอร์

คุณควรจะเห็นค่าฮาร์ดโค้ดที่ส่งกลับซึ่งเป็นค่าที่เราเขียนในวิธีการลงทะเบียน หากเป็นเช่นนั้นเราก็พร้อมที่จะดำเนินการต่อเนื่องจากสภาพแวดล้อมการพัฒนาของเราพร้อมและกำลังทำงานสำหรับทั้งแอปพลิเคชัน Angular และ Play

การกำหนดโมเดล Ebean ใน Play

ก่อนกำหนดโมเดลให้เราเลือกพื้นที่เก็บข้อมูลก่อน ในบทความนี้เราจะใช้ฐานข้อมูล H2 ในหน่วยความจำ ในการเปิดใช้งานให้ค้นหาและยกเลิกการใส่ข้อคิดเห็นบรรทัดต่อไปนี้ในไฟล์“ application.conf”:

applyEvolutions.default=true

และเพิ่มบรรทัดต่อไปนี้:

อะไรทำให้เกิดวิกฤตหนี้กรีซ
// User.java @Entity public class User extends Model { @Id public Long id; @Column(length = 255, unique = true, nullable = false) @Constraints.MaxLength(255) @Constraints.Required @Constraints.Email public String email; @Column(length = 64, nullable = false) private byte[] shaPassword; @OneToMany(cascade = CascadeType.ALL) @JsonIgnore public List posts; public void setPassword(String password) { this.shaPassword = getSha512(password); } public void setEmail(String email) { this.email = email.toLowerCase(); } public static final Finder find = new Finder( Long.class, User.class); public static User findByEmailAndPassword(String email, String password) { return find .where() .eq('email', email.toLowerCase()) .eq('shaPassword', getSha512(password)) .findUnique(); } public static User findByEmail(String email) { return find .where() .eq('email', email.toLowerCase()) .findUnique(); } public static byte[] getSha512(String value) { try { return MessageDigest.getInstance('SHA-512').digest(value.getBytes('UTF-8')); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } }

รูปแบบโดเมนบล็อกของเราค่อนข้างเรียบง่าย ก่อนอื่นเรามีผู้ใช้ที่สามารถสร้างโพสต์จากนั้นแต่ละโพสต์สามารถแสดงความคิดเห็นได้โดยผู้ใช้ที่ลงชื่อเข้าใช้ มาสร้างแบบจำลอง Ebean ของเรากัน

ผู้ใช้

// BlogPost.java @Entity public class BlogPost extends Model { @Id public Long id; @Column(length = 255, nullable = false) @Constraints.MaxLength(255) @Constraints.Required public String subject; @Column(columnDefinition = 'TEXT') @Constraints.Required public String content; @ManyToOne public User user; public Long commentCount; @OneToMany(cascade = CascadeType.ALL) public List comments; public static final Finder find = new Finder( Long.class, BlogPost.class); public static List findBlogPostsByUser(final User user) { return find .where() .eq('user', user) .findList(); } public static BlogPost findBlogPostById(final Long id) { return find .where() .eq('id', id) .findUnique(); } }

โพสต์บล็อก

// PostComment.java @Entity public class PostComment extends Model { @Id public Long id; @ManyToOne @JsonIgnore public BlogPost blogPost; @ManyToOne public User user; @Column(columnDefinition = 'TEXT') public String content; public static final Finder find = new Finder( Long.class, PostComment.class); public static List findAllCommentsByPost(final BlogPost blogPost) { return find .where() .eq('post', blogPost) .findList(); } public static List findAllCommentsByUser(final User user) { return find .where() .eq('user', user) .findList(); } }

เขียนความคิดเห็น

// Application.java public static Result signup() { Form signUpForm = Form.form(SignUp.class).bindFromRequest(); if ( signUpForm.hasErrors()) { return badRequest(signUpForm.errorsAsJson()); } SignUp newUser = signUpForm.get(); User existingUser = User.findByEmail(newUser.email); if(existingUser != null) { return badRequest(buildJsonResponse('error', 'User exists')); } else { User user = new User(); user.setEmail(newUser.email); user.setPassword(newUser.password); user.save(); session().clear(); session('username', newUser.email); return ok(buildJsonResponse('success', 'User created successfully')); } } public static class UserForm { @Constraints.Required @Constraints.Email public String email; } public static class SignUp extends UserForm { @Constraints.Required @Constraints.MinLength(6) public String password; } private static ObjectNode buildJsonResponse(String type, String message) { ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', message); wrapper.put(type, msg); return wrapper; }

การดำเนินการสมัครจริง

ตอนนี้เรามาสร้างการกระทำจริงครั้งแรกของเราโดยให้ผู้ใช้ลงทะเบียน:

yo angular:service alerts

โปรดทราบว่าการรับรองความถูกต้องที่ใช้ในแอพนี้เป็นพื้นฐานมากและไม่แนะนำให้ใช้ในการผลิต

ส่วนที่น่าสนใจคือเรากำลังใช้แบบฟอร์ม Play เพื่อจัดการกับแบบฟอร์มการสมัคร เรากำหนดข้อ จำกัด สองสามข้อในคลาสฟอร์มการสมัครของเรา การตรวจสอบความถูกต้องจะดำเนินการให้เราโดยอัตโนมัติโดยไม่จำเป็นต้องใช้ตรรกะการตรวจสอบที่ชัดเจน

หากเรากลับไปที่แอปพลิเคชัน AngularJS ในเว็บเบราว์เซอร์และคลิกที่“ ส่ง” อีกครั้งเราจะเห็นว่าเซิร์ฟเวอร์ตอบสนองด้วยข้อผิดพลาดที่เหมาะสมซึ่งจำเป็นต้องกรอกข้อมูลในช่องเหล่านี้

ส่งแบบฟอร์มการเล่น

การจัดการข้อผิดพลาดของเซิร์ฟเวอร์ใน AngularJS

ดังนั้นเราจึงได้รับข้อผิดพลาดจากเซิร์ฟเวอร์ แต่ผู้ใช้แอปพลิเคชันไม่รู้ว่าเกิดอะไรขึ้น อย่างน้อยที่สุดที่เราทำได้คือแสดงข้อผิดพลาดให้กับผู้ใช้ของเรา ตามหลักการแล้วเราจำเป็นต้องเข้าใจว่าเราได้รับข้อผิดพลาดประเภทใดและแสดงข้อความที่ใช้งานง่าย มาสร้างบริการแจ้งเตือนง่ายๆที่จะช่วยให้เราแสดงข้อผิดพลาด

ขั้นแรกเราต้องสร้างเทมเพลตบริการด้วย Yeoman:

angular.module('clientApp') .factory('alertService', function($timeout) { var ALERT_TIMEOUT = 5000; function add(type, msg, timeout) { if (timeout) { $timeout(function(){ closeAlert(this); }, timeout); } else { $timeout(function(){ closeAlert(this); }, ALERT_TIMEOUT); } return alerts.push({ type: type, msg: msg, close: function() { return closeAlert(this); } }); } function closeAlert(alert) { return closeAlertIdx(alerts.indexOf(alert)); } function closeAlertIdx(index) { return alerts.splice(index, 1); } function clear(){ alerts = []; } function get() { return alerts; } var service = { add: add, closeAlert: closeAlert, closeAlertIdx: closeAlertIdx, clear: clear, get: get }, alerts = []; return service; } );

จากนั้นเพิ่มรหัสนี้ใน“ alerts.js”:

yo angular:controller alerts

ตอนนี้เรามาสร้างตัวควบคุมแยกต่างหากที่รับผิดชอบการแจ้งเตือน:

angular.module('clientApp') .controller('AlertsCtrl', function ($scope, alertService) { $scope.alerts = alertService.get(); }); bower install angular-bootstrap --save

ตอนนี้เราต้องแสดงข้อความแสดงข้อผิดพลาด Bootstrap ที่ดีจริงๆ วิธีที่ง่ายที่สุดคือการใช้ UI เชิงมุม . เราสามารถใช้ Bower เพื่อติดตั้ง:

angular .module('clientApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.bootstrap' ])

ใน“ app.js” ต่อท้ายโมดูล Angular UI:

{{ alert.msg }}

มาเพิ่มคำสั่งการแจ้งเตือนในไฟล์“ index.html” ของเรา:

วิธีการเขียนเอกสารทางเทคนิคสำหรับซอฟต์แวร์
angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log, alertService, $location, userService) { $scope.signup = function() { var payload = { email : $scope.email, password : $scope.password }; $http.post('app/signup', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'email' || key === 'password') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } if(status === 500) { alertService.add('danger', 'Internal server error!'); } }) }; });

ในที่สุดเราต้องอัปเดตตัวควบคุมการสมัคร:

yo angular:view dashboard yo angular:controller dashboard

ตอนนี้ถ้าเราส่งแบบฟอร์มเปล่าอีกครั้งเราจะเห็นข้อผิดพลาดปรากฏเหนือแบบฟอร์ม:

ข้อผิดพลาดในการเล่นเชิงมุม

ขณะนี้ข้อผิดพลาดได้รับการจัดการแล้วเราจำเป็นต้องดำเนินการบางอย่างเมื่อการสมัครผู้ใช้สำเร็จ เราสามารถเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าแดชบอร์ดที่เขาสามารถเพิ่มโพสต์ได้ แต่ก่อนอื่นเราต้องสร้างมัน:

angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log, alertService, $location) { // .. .success(function(data) { if(data.hasOwnProperty('success')) { $location.path('/dashboard'); } });

แก้ไขวิธีการลงทะเบียนตัวควบคุม 'signup.js' เพื่อให้ประสบความสำเร็จจะเปลี่ยนเส้นทางผู้ใช้:

.when('/dashboard', { templateUrl: 'views/dashboard.html', controller: 'DashboardCtrl' })

เพิ่มเส้นทางใหม่ใน“ apps.js”:

yo angular:service user

เราต้องติดตามด้วยว่าผู้ใช้เข้าสู่ระบบหรือไม่ให้เราสร้างบริการแยกต่างหากสำหรับสิ่งนั้น:

// user.js angular.module('clientApp') .factory('userService', function() { var username = ''; return { username : username }; }); .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = $scope.email; $location.path('/dashboard');; } });

และแก้ไขตัวควบคุมการสมัครเพื่อตั้งค่าผู้ใช้เป็นผู้ที่เพิ่งลงทะเบียน:

public static Result login() { Form loginForm = Form.form(Login.class).bindFromRequest(); if (loginForm.hasErrors()) { return badRequest(loginForm.errorsAsJson()); } Login loggingInUser = loginForm.get(); User user = User.findByEmailAndPassword(loggingInUser.email, loggingInUser.password); if(user == null) { return badRequest(buildJsonResponse('error', 'Incorrect email or password')); } else { session().clear(); session('username', loggingInUser.email); ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', 'Logged in successfully'); msg.put('user', loggingInUser.email); wrapper.put('success', msg); return ok(wrapper); } } public static Result logout() { session().clear(); return ok(buildJsonResponse('success', 'Logged out successfully')); } public static Result isAuthenticated() { if(session().get('username') == null) { return unauthorized(); } else { ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', 'User is logged in already'); msg.put('user', session().get('username')); wrapper.put('success', msg); return ok(wrapper); } } public static class Login extends UserForm { @Constraints.Required public String password; }

ก่อนที่เราจะเพิ่มฟังก์ชันการทำงานหลักในการเพิ่มโพสต์เรามาดูแลคุณลักษณะที่สำคัญอื่น ๆ เช่นความสามารถในการเข้าสู่ระบบและออกจากระบบการแสดงข้อมูลผู้ใช้บนแดชบอร์ดและการเพิ่มการรองรับการตรวจสอบสิทธิ์ในส่วนหลัง

การรับรองความถูกต้องขั้นพื้นฐาน

ไปที่แอปพลิเคชัน Play ของเราและดำเนินการเข้าสู่ระบบและออกจากระบบ เพิ่มบรรทัดเหล่านี้ใน“ Application.java”:

public class Secured extends Security.Authenticator { @Override public String getUsername(Context ctx) { return ctx.session().get('username'); } @Override public Result onUnauthorized(Context ctx) { return unauthorized(); } }

ต่อไปเราจะเพิ่มความสามารถในการอนุญาตการโทรแบ็คเอนด์เฉพาะกับผู้ใช้ที่ตรวจสอบสิทธิ์เท่านั้น สร้าง“ Secured.java” ด้วยรหัสต่อไปนี้:

yo angular:controller menu

เราจะใช้คลาสนี้ในภายหลังเพื่อป้องกันการกระทำใหม่ ๆ ต่อไปเราควรปรับแต่งเมนูหลักของแอปพลิเคชัน AngularJS เพื่อให้แสดงชื่อผู้ใช้และลิงก์ออกจากระบบ ด้วยเหตุนี้เราต้องสร้างตัวควบคุม:

// menu.js angular.module('clientApp') .controller('MenuCtrl', function ($scope, $http, userService, $location) { $scope.user = userService; $scope.logout = function() { $http.get('/app/logout') .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = ''; $location.path('/login'); } }); }; $scope.$watch('user.username', function (newVal) { if(newVal === '') { $scope.isLoggedIn = false; } else { $scope.username = newVal; $scope.isLoggedIn = true; } }); }); yo angular:controller login yo angular:view login

เรายังต้องการมุมมองและตัวควบคุมสำหรับหน้าเข้าสู่ระบบ:

Email Password Log in // login.js angular.module('clientApp') .controller('LoginCtrl', function ($scope, userService, $location, $log, $http, alertService) { $scope.isAuthenticated = function() { if(userService.username) { $log.debug(userService.username); $location.path('/dashboard'); } else { $http.get('/app/isauthenticated') .error(function() { $location.path('/login'); }) .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = data.success.user; $location.path('/dashboard'); } }); } }; $scope.isAuthenticated(); $scope.login = function() { var payload = { email : this.email, password : this.password }; $http.post('/app/login', payload) .error(function(data, status){ if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'email' || key === 'password') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { alertService.add('danger', 'Invalid login or password!'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data){ $log.debug(data); if(data.hasOwnProperty('success')) { userService.username = data.success.user; $location.path('/dashboard'); } }); }; });
  • Sign up!
  • Login
{{ username }} Toggle Dropdown
  • Dashboard
  • Logout

ต่อไปเราจะปรับแต่งเมนูเพื่อให้สามารถแสดงข้อมูลผู้ใช้:

yo angular:view addpost

ตอนนี้หากคุณลงชื่อเข้าใช้แอปพลิเคชันคุณควรจะเห็นหน้าจอต่อไปนี้:

เล่นภาพหน้าจอ

การเพิ่มโพสต์

ตอนนี้เรามีกลไกการลงทะเบียนและการตรวจสอบสิทธิ์ขั้นพื้นฐานแล้วเราสามารถลงไปใช้งานฟังก์ชันการโพสต์ได้ มาเพิ่มมุมมองและตัวควบคุมใหม่สำหรับการเพิ่มโพสต์

Subject Post Submit post yo angular:controller addpost // addpost.js angular.module('clientApp') .controller('AddpostCtrl', function ($scope, $http, alertService, $location) { $scope.post = function() { var payload = { subject : $scope.subject, content: $scope.content }; $http.post('/app/post', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'subject' || key === 'content') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { $location.path('/login'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data) { $scope.subject = ''; $scope.content = ''; alertService.add('success', data.success.message); }); }; }); .when('/addpost', { templateUrl: 'views/addpost.html', controller: 'AddpostCtrl' })

จากนั้นเราอัปเดต“ app.js” เพื่อรวม:

  • Dashboard
  • Add post
  • Logout

ต่อไปเราจะแก้ไข“ index.html” เพื่อเพิ่มลิงค์สำหรับมุมมอง“ addpost” ของเราในเมนูแดชบอร์ด:

// Post.java public class Post extends Controller { public static Result addPost() { Form postForm = Form.form(PostForm.class).bindFromRequest(); if (postForm.hasErrors()) { return badRequest(postForm.errorsAsJson()); } else { BlogPost newBlogPost = new BlogPost(); newBlogPost.commentCount = 0L; newBlogPost.subject = postForm.get().subject; newBlogPost.content = postForm.get().content; newBlogPost.user = getUser(); newBlogPost.save(); } return ok(Application.buildJsonResponse('success', 'Post added successfully')); } private static User getUser() { return User.findByEmail(session().get('username')); } public static class PostForm { @Constraints.Required @Constraints.MaxLength(255) public String subject; @Constraints.Required public String content; } }

ตอนนี้ในฝั่งแอปพลิเคชัน Play มาสร้างตัวควบคุมโพสต์ใหม่ด้วยวิธี addPost:

POST /app/post controllers.Post.addPost

เพิ่มรายการใหม่ในไฟล์เส้นทางเพื่อให้สามารถจัดการกับวิธีการที่เพิ่มใหม่ในการกำหนดเส้นทาง:

// Application.java public static Result getPosts() { return ok(Json.toJson(BlogPost.find.findList())); }

ณ จุดนี้คุณควรจะเพิ่มโพสต์ใหม่ได้

การเพิ่มโพสต์ใหม่ใน Play

กำลังแสดงโพสต์

การเพิ่มโพสต์มีคุณค่าเพียงเล็กน้อยหากเราไม่สามารถแสดงได้ สิ่งที่เราต้องการทำคือแสดงรายการโพสต์ทั้งหมดในหน้าหลัก เราเริ่มต้นด้วยการเพิ่มวิธีการใหม่ในตัวควบคุมแอปพลิเคชันของเรา:

GET /app/posts controllers.Application.getPosts

และลงทะเบียนในไฟล์เส้นทางของเรา:

// main.js angular.module('clientApp') .controller('MainCtrl', function ($scope, $http) { $scope.getPosts = function() { $http.get('app/posts') .success(function(data) { $scope.posts = data; }); }; $scope.getPosts(); });

ถัดไปในแอปพลิเคชัน AngularJS ของเราเราปรับเปลี่ยนคอนโทรลเลอร์หลักของเรา:

{{ post.subject }}

{{ post.content }}

Post by: {{ post.user.email }} | Comments {{ post.commentCount }}

สุดท้ายลบทุกอย่างออกจาก“ main.html” และเพิ่มสิ่งนี้:

yo angular:controller viewpost yo angular:view viewpost

ตอนนี้ถ้าคุณโหลดโฮมเพจของแอปพลิเคชันคุณจะเห็นสิ่งที่คล้ายกับสิ่งนี้:

โหลดตัวอย่าง Angularjs Play แล้ว

เราควรมีมุมมองแยกต่างหากสำหรับแต่ละโพสต์

// viewpost.js angular.module('clientApp') .controller('ViewpostCtrl', function ($scope, $http, alertService, userService, $location) { $scope.user = userService; $scope.params = $routeParams; $scope.postId = $scope.params.postId; $scope.viewPost = function() { $http.get('/app/post/' + $scope.postId) .error(function(data) { alertService.add('danger', data.error.message); }) .success(function(data) { $scope.post = data; }); }; $scope.viewPost(); });

{{ post.subject }}

{{ post.content }}

Post by: {{ post.user.email }} | Comments {{ post.commentCount }}
app.js: .when('/viewpost/:postId', { templateUrl: 'views/viewpost.html', controller: 'ViewpostCtrl' })

และเส้นทาง AngularJS:

// Application.java public static Result getPost(Long id) { BlogPost blogPost = BlogPost.findBlogPostById(id); if(blogPost == null) { return notFound(buildJsonResponse('error', 'Post not found')); } return ok(Json.toJson(blogPost)); }

เช่นเดิมเราได้เพิ่มวิธีการใหม่ให้กับตัวควบคุมแอปพลิเคชันของเรา:

GET /app/post/:id controllers.Application.getPost(id: Long)

…และเส้นทางใหม่:

// dashboard.js angular.module('clientApp') .controller('DashboardCtrl', function ($scope, $log, $http, alertService, $location) { $scope.loadPosts = function() { $http.get('/app/userposts') .error(function(data, status) { if(status === 401) { $location.path('/login'); } else { alertService.add('danger', data.error.message); } }) .success(function(data) { $scope.posts = data; }); }; $scope.loadPosts(); });

ตอนนี้ถ้าคุณไปที่ http: // localhost: 9000 / # / viewpost / 1 คุณจะสามารถโหลดมุมมองสำหรับโพสต์ที่ต้องการได้ ต่อไปเราจะเพิ่มความสามารถในการดูโพสต์ของผู้ใช้ในแดชบอร์ด:

My Posts

No posts yet. Add a post {{ post.subject }} | Comments {{ post.commentCount }}
// Post.java public static Result getUserPosts() { User user = getUser(); if(user == null) { return badRequest(Application.buildJsonResponse('error', 'No such user')); } return ok(Json.toJson(BlogPost.findBlogPostsByUser(user))); }

เพิ่มวิธีการใหม่ให้กับ Post controller ตามด้วยเส้นทางที่ตรงกับวิธีนี้:

GET /app/userposts controllers.Post.getUserPosts // Post.java public static Result addComment() { Form commentForm = Form.form(CommentForm.class).bindFromRequest(); if (commentForm.hasErrors()) { return badRequest(commentForm.errorsAsJson()); } else { PostComment newComment = new PostComment(); BlogPost blogPost = BlogPost.findBlogPostById(commentForm.get().postId); blogPost.commentCount++; blogPost.save(); newComment.blogPost = blogPost; newComment.user = getUser(); newComment.content = commentForm.get().comment; newComment.save(); return ok(Application.buildJsonResponse('success', 'Comment added successfully')); } } public static class CommentForm { @Constraints.Required public Long postId; @Constraints.Required public String comment; }

ตอนนี้เมื่อคุณสร้างโพสต์โพสต์เหล่านั้นจะปรากฏบนแดชบอร์ด:

โพสต์ใหม่ที่แสดงบนแดชบอร์ด

การแสดงความคิดเห็น

ในการใช้ฟังก์ชันการแสดงความคิดเห็นเราจะเริ่มต้นด้วยการเพิ่มวิธีการใหม่ในตัวควบคุมโพสต์:

POST /app/comment controllers.Post.addComment

และเช่นเคยเราต้องลงทะเบียนเส้นทางใหม่สำหรับวิธีนี้:

$scope.addComment = function() { var payload = { postId: $scope.postId, comment: $scope.comment }; $http.post('/app/comment', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'comment') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { $location.path('/login'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data) { alertService.add('success', data.success.message); $scope.comment = ''; $scope.viewPost(); }); };

ในแอปพลิเคชัน AngularJS ของเราเราเพิ่มสิ่งต่อไปนี้ใน“ viewpost.js”:

By: {{ comment.user.email }}
{{ comment.content }}

Login to comment

Add comment

Comment Add comment

และสุดท้ายเพิ่มบรรทัดต่อไปนี้ใน“ viewpost.html”:

|_+_|

ตอนนี้หากคุณเปิดโพสต์ใด ๆ คุณจะสามารถเพิ่มและดูความคิดเห็นได้

ดูภาพหน้าจอความคิดเห็น

อะไรต่อไป?

ในบทช่วยสอนนี้เราได้สร้างบล็อก AngularJS ด้วยแอปพลิเคชัน Play ที่ทำหน้าที่เป็นแบ็คเอนด์ REST API แม้ว่าแอปพลิเคชันจะไม่มีการตรวจสอบข้อมูลที่มีประสิทธิภาพ (โดยเฉพาะในฝั่งไคลเอ็นต์) และความปลอดภัย แต่หัวข้อเหล่านี้อยู่นอกขอบเขตของบทช่วยสอนนี้ มีจุดมุ่งหมายเพื่อแสดงให้เห็นถึงหนึ่งในวิธีที่เป็นไปได้มากมายในการสร้างแอปพลิเคชันประเภทนี้ เพื่อความสะดวกซอร์สโค้ดของแอปพลิเคชันนี้ได้รับการอัปโหลดไปยัง ที่เก็บ GitHub .

หากคุณพบว่าการรวมกันของ AngularJS และ Play ในการพัฒนาแอปพลิเคชันบนเว็บน่าสนใจฉันขอแนะนำให้คุณอ่านหัวข้อต่อไปนี้เพิ่มเติม:

  • เอกสาร AngularJS
  • เล่นเอกสาร
  • แนวทางการรักษาความปลอดภัยที่แนะนำในแอป JS หน้าเดียวพร้อม Play as back-end (มีตัวอย่าง)
  • Secure REST API โดยไม่ต้องใช้ OAuth
  • ปลั๊กอินการรับรองความถูกต้องของ Ready Play (อาจใช้งานไม่ได้เต็มรูปแบบสำหรับแอปพลิเคชัน JavaScript แบบหน้าเดียว แต่สามารถใช้เป็นตัวอย่างที่ดีได้)

ทำไมคุณต้องอัพเกรดเป็น Java 8 อยู่แล้ว

ส่วนหน้าของเว็บ

ทำไมคุณต้องอัพเกรดเป็น Java 8 อยู่แล้ว
พลังไฮบริด: ข้อดีและประโยชน์ของ Flutter

พลังไฮบริด: ข้อดีและประโยชน์ของ Flutter

มือถือ

โพสต์ยอดนิยม
ตลาด Crowdfunding Equity ของสหรัฐมีการเติบโตขึ้นตามความคาดหวังหรือไม่?
ตลาด Crowdfunding Equity ของสหรัฐมีการเติบโตขึ้นตามความคาดหวังหรือไม่?
คู่มือสำคัญสำหรับ Qmake
คู่มือสำคัญสำหรับ Qmake
หลักการออกแบบ Mobile UX
หลักการออกแบบ Mobile UX
MIDI Tutorial: การสร้างแอปพลิเคชั่นเสียงบนเบราว์เซอร์ที่ควบคุมโดยฮาร์ดแวร์ MIDI
MIDI Tutorial: การสร้างแอปพลิเคชั่นเสียงบนเบราว์เซอร์ที่ควบคุมโดยฮาร์ดแวร์ MIDI
Init.js: คำแนะนำเกี่ยวกับสาเหตุและวิธีการใช้ JavaScript แบบ Full-Stack
Init.js: คำแนะนำเกี่ยวกับสาเหตุและวิธีการใช้ JavaScript แบบ Full-Stack
 
Splash of EarlGrey - UI การทดสอบแอพ ApeeScape Talent
Splash of EarlGrey - UI การทดสอบแอพ ApeeScape Talent
จาก Node.js ไปจนถึงการจ่ายภาษีอิสระของคุณ: บทสัมภาษณ์กับ Developer ที่ประสบความสำเร็จ
จาก Node.js ไปจนถึงการจ่ายภาษีอิสระของคุณ: บทสัมภาษณ์กับ Developer ที่ประสบความสำเร็จ
ขายธุรกิจของคุณ? หยุดทิ้งเงินไว้บนโต๊ะ
ขายธุรกิจของคุณ? หยุดทิ้งเงินไว้บนโต๊ะ
บทช่วยสอนเกี่ยวกับส่วนขยายแอป iOS 8
บทช่วยสอนเกี่ยวกับส่วนขยายแอป iOS 8
ผู้จัดการการเติบโต
ผู้จัดการการเติบโต
โพสต์ยอดนิยม
  • ฉันต้องการ llc ประเภทใด
  • cfo ของบริษัททำอะไร
  • แนวทางปฏิบัติที่ดีที่สุดสำหรับการทดสอบหน่วย java
  • เทอร์มินัลบลูมเบิร์กสำหรับนักลงทุนรายย่อย
  • aws Solutions Architect Associate คู่มือการศึกษา
  • วิธีตั้งโปรแกรมหุ่นยนต์ใน java
หมวดหมู่
  • การจัดการโครงการ
  • การเพิ่มขึ้นของระยะไกล
  • การบริหารโครงการ
  • เครื่องมือและบทช่วยสอน
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt